Appearance
Agent recipes
End-to-end Agent Key workflows you can copy, paste, and run. Each recipe lists the required scopes, the prerequisites the human owner of the key must satisfy, and the terminal states the agent should watch for.
Base URL throughout: https://portal.eprospera.com. See Conventions for shared rules (auth, errors, timestamps, pagination, rate limits).
Substitutions used below
$AK— your Agent Key (ak-...)$BASE—https://portal.eprospera.comin production,https://staging-portal.eprospera.comin staging
Recipe 1 — RPN lookup → registry search → fetch entity
Resolve a free-text query to a single legal entity, then fetch its full record.
Required scopes: agent:verify_rpn, agent:registry.search, agent:entity.readPrerequisites: Read-only Agent Key. Manifestation of Will is not required. Note: GET /api/v1/legal_entities/{id} only returns entities created via the API (see Agent Keys → Important Limitations).
bash
# 1. If you have an RPN, confirm it exists and is active
curl -s -X POST "$BASE/api/v1/verify_rpn" \
-H "Authorization: Bearer $AK" \
-H "Content-Type: application/json" \
-d '{"rpn": "80000000000012"}'
# → {"result":"found_legal_entity","active":true}
# 2. If you only have a name, search the registry
curl -s -X POST "$BASE/api/v1/registries/legal_entities/search" \
-H "Authorization: Bearer $AK" \
-H "Content-Type: application/json" \
-d '{"query": "Acme Holdings"}'
# → {"results":[{"id":"...","name":"Acme Holdings","extension":"LLC","residentPermitNumber":"80..."}]}
# 3. Fetch the entity by id
curl -s "$BASE/api/v1/legal_entities/<id>" \
-H "Authorization: Bearer $AK"Watch for
verify_rpnreturns"not_found"→ the RPN string is malformed or unknown; do not retry.- Search returns an empty
resultsarray → broaden the query, or split multi-word queries on whitespace (the server already does this for matching). 404onGET /legal_entities/{id}→ either the entity does not exist, or it was created outside the API and is therefore invisible to Agent Keys. There is no way to disambiguate.
Recipe 2 — Fully automated LLC incorporation
Create an LLC application, pay it with a fully-discounting coupon, and pick up the resulting legal-entity record. Zero browser hops.
Required scopes: agent:entity.application.create, agent:entity.application.pay, agent:entity.application.read, agent:entity.readPrerequisites:
- Active Manifestation of Will signed by the Agent Key owner (required for any write scope).
- The Agreement of Coexistence for the relevant residency type (Resident or e-Resident LLC) must be pre-accepted during MoW signing. Without this, step 1's response includes a
nextSteps.signatureURL that requires a human browser session. - A coupon code that fully covers the application invoice and is owned by the key owner.
- The owner is an active e-Resident or Resident.
bash
# 1. Create the application
curl -s -X POST "$BASE/api/v1/legal_entity_applications" \
-H "Authorization: Bearer $AK" \
-H "Content-Type: application/json" \
-d '{
"applicationData": {
"residencyType": "e-Resident",
"entityType": "llc",
"name": "Acme Robotics",
"extension": "LLC",
"principalOffice": {
"country": "US",
"line1": "100 Main St",
"line2": null,
"city": "Wilmington",
"state": "DE",
"postalCode": "19801"
},
"contactEmail": "owner@example.com",
"registeredAgentProvider": "prospera_employment_solutions"
}
}'
# → {"data":{"id":"<APP_ID>","statusId":"Draft",...},"nextSteps":{"signature":null}}
# If "nextSteps.signature" is non-null, the AOC was not pre-accepted — stop and ask the
# owner to accept the AOC in Developer settings, then retry from step 1.
# 2. Apply the coupon to fully pay the invoice
curl -s -X POST "$BASE/api/v1/legal_entity_applications/<APP_ID>/pay/coupon" \
-H "Authorization: Bearer $AK" \
-H "Content-Type: application/json" \
-d '{"couponCode": "FOUNDER100"}'
# → {"success":true,"data":{"statusId":"Pending Review",...}}
# 3. Poll for approval (every 30s, with backoff)
curl -s "$BASE/api/v1/legal_entity_applications/<APP_ID>" \
-H "Authorization: Bearer $AK"
# → watch data.statusId for "Approved" (terminal) or "Rejected" (terminal)
# 4. Fetch the resulting legal-entity record
curl -s "$BASE/api/v1/legal_entities/<legalEntityId from step 3>" \
-H "Authorization: Bearer $AK"Terminal application states: Approved (success — data.legalEntityId is populated) and Rejected (failure — inspect the application in the portal for review notes).
Watch for
400on step 1 withdetails→ schema validation failed; fix and retry.409on step 1 → entity name collides with an existing entity of the same type; pick a new name.400on step 2 withapplication is not in Draft status→ it was already paid or already submitted.500on step 2 mentioning coupon → coupon is missing, expired, or under-funds the invoice. The owner is notified by email automatically.403on any step → the Agent Key is missing the required scope, or the MoW was revoked (which auto-revokes write-capable keys).
Recipe 3 — Hosted-checkout incorporation
Same as Recipe 2 but the agent owner pays interactively in a browser instead of with a coupon.
Required scopes: agent:entity.application.create, agent:payment.initiate, agent:entity.application.read, agent:entity.readPrerequisites: All of Recipe 2 except the coupon. AOC pre-acceptance still required for the application to auto-submit after payment.
bash
# 1. Create the application (same as Recipe 2 step 1)
# 2. Create a checkout session and hand the URL to the owner
curl -s -X POST "$BASE/api/v1/legal_entity_applications/<APP_ID>/checkout_session" \
-H "Authorization: Bearer $AK" \
-H "Content-Type: application/json" \
-d '{
"paymentProvider": "stripe",
"redirectUrl": "https://your-app.example/post-checkout",
"email": "owner@example.com"
}'
# → {"data":{"url":"https://checkout.stripe.com/..."},"invoiceId":"<INVOICE_ID>"}
# 3. Owner completes payment in the browser. After return, poll the application:
curl -s "$BASE/api/v1/legal_entity_applications/<APP_ID>" \
-H "Authorization: Bearer $AK"
# 4. Fetch the legal-entity record once approved (same as Recipe 2 step 4).Supported paymentProvider values: stripe, stripe-crypto, lnbits, solana-pay-ptc.
Watch for
400withapplication is not in Draft status→ already paid; skip to polling.redirectUrlmust be a valid absolute URL — it is required by the payment providers.
Recipe 4 — Read account holder profile
Fetch the human owner's identity, residency status, and (if available) ID-verification artifacts. Useful for KYC review, compliance summaries, or pre-filling forms on the agent owner's behalf.
Required scopes: agent:person.details.read, agent:person.residency.read, agent:person.id_verification.readPrerequisites: Read-only Agent Key. MoW not required.
bash
# 1. Personal details
curl -s "$BASE/api/v1/me/natural-person" \
-H "Authorization: Bearer $AK"
# 2. Residency status
curl -s "$BASE/api/v1/me/natural-person/residency" \
-H "Authorization: Bearer $AK"
# 3. ID verification (signed URLs valid for ~1 hour — download promptly)
curl -s "$BASE/api/v1/me/natural-person/id-verification" \
-H "Authorization: Bearer $AK"Watch for
/api/v1/me/natural-personreturningnull→ the owner has no approved residency yet, so there is no natural-person record to read./residencyreturningactiveResidency: nullwithwasEverResident: true→ the owner is a former resident; treat as inactive./id-verificationreturning all-nulldocument URLs → the owner has not completed ID verification.- These endpoints accept OAuth tokens and Agent Keys — but not standard
sk-keys.
Polling guidance
For Recipes 2 and 3, poll GET /api/v1/legal_entity_applications/{id} every 30 seconds for the first 2 minutes, then back off to every 5 minutes. There are no webhooks today (see Conventions → Webhooks). Approved and Rejected are terminal — stop polling.
Common errors quick-reference
| Status | Likely cause |
|---|---|
400 | Request body fails Zod validation (details lists offending paths) or state precondition fail. |
401 | Missing/invalid Authorization header, or the Agent Key was revoked. |
403 | The Agent Key lacks a required scope, or the MoW was revoked (auto-revoking write-capable keys). |
404 | Resource does not exist or is invisible to your Agent Key (e.g. entity was created outside the API). |
409 | Entity name conflict on POST /legal_entity_applications. |
429 | Rate limit exceeded on verify_rpn / registries/.../search (5,000/day, 50/minute per key). |
500 | Server error. Retry with exponential back-off only for idempotent (read) operations. |