Skip to content

Skills for AI Agents

A capability map and decision tree for LLM-based callers. Read this before making your first request — it is shorter than the reference docs and will save you from probing endpoints that are empty by design.

If you are the developer wiring an agent up to this API, paste this page (or /llms-full.txt) into your agent's system prompt or skill folder.

TL;DR — what an agent must internalize before the first call

  • Three docs, in order: Agent Keys (credentials & scopes) → Conventions (auth header, errors, rate limits) → this page (capabilities & dead ends) → Agent recipes (copy-paste workflows).
  • Base URL: https://portal.eprospera.com (production) or https://staging-portal.eprospera.com (staging). There is no api.eprospera.com.
  • Every Agent Key request is scope-checked. 403 means the key is missing the scope, not that the resource is absent.
  • A 404 from GET /api/v1/legal_entities/{id} usually means "created outside the API", not "no such entity." Agent Keys can only see API-created records — see Why your call might return empty.
  • There are no webhooks. Long-running operations (application review, payment processing) must be polled — see Polling, not webhooks.

Capability matrix

What you can do with each credential type, what to call, what scope you need, and the most common dead-end. All paths are relative to the base URL above.

Discovery & registry reads

I want to…CallCredentialsRequired scopeCommon dead-end
Confirm an RPN existsPOST /api/v1/verify_rpnsk-, ak-agent:verify_rpnRate-limited: 5,000/day, 50/minute per key.
Search the registry by name/RPNPOST /api/v1/registries/legal_entities/searchsk-, ak-agent:registry.searchEmpty results ≠ bug. Try fewer words; the server already splits input.
Fetch one legal entity by IDGET /api/v1/legal_entities/{id}sk-, ak-agent:entity.readAgent Keys see only API-created entities. 404 is the most common response for IDs the agent did not itself produce.
Fetch entity documentsGET /api/v1/legal_entities/{id}/documentssk-, ak-agent:entity.documents.readSame limitation as above.

Personal data of the key owner

These endpoints accept Agent Keys and OAuth tokens, but not standard sk- keys.

I want to read…CallCredentialsRequired scope
The owner's profileGET /api/v1/me/natural-personak-, OAuthagent:person.details.read / eprospera:person.details.read
The owner's residency statusGET /api/v1/me/natural-person/residencyak-, OAuthagent:person.residency.read / eprospera:person.residency.read
The owner's ID-verification artifactsGET /api/v1/me/natural-person/id-verificationak-, OAuthagent:person.id_verification.read / eprospera:person.id_verification.read

Entity formation (writes)

Write scopes require an active signed Manifestation of Will on the key owner's account. Headless incorporation additionally requires the Agreement of Coexistence for the target residency type to be pre-accepted during MoW signing — otherwise the create call returns a nextSteps.signature URL that needs a human browser session.

I want to…CallCredentialsRequired scope
List my API-created applicationsGET /api/v1/legal_entity_applicationssk-, ak-agent:entity.application.read
Get one applicationGET /api/v1/legal_entity_applications/{id}sk-, ak-agent:entity.application.read
Create an LLC applicationPOST /api/v1/legal_entity_applicationssk-, ak-agent:entity.application.create
Pay an application with a fully-discount couponPOST /api/v1/legal_entity_applications/{id}/pay/couponsk-, ak-agent:entity.application.pay
Start a hosted Stripe / crypto checkoutPOST /api/v1/legal_entity_applications/{id}/checkout_sessionsk- onlyn/a — temporarily disabled for Agent Keys

For a copy-paste end-to-end flow, see Recipe 2 — Fully automated LLC incorporation.

OAuth-only: acting on behalf of a user across their entities

Use OAuth (with PKCE) when the calling user has consented to share their entity portfolio — typically a sign-in-with-e-Próspera integration. Agent Keys are not accepted on /me/legal-entities*; calls with an ak- token return 401.

I want to…CallRequired scope
List all entities the user representsGET /api/v1/me/legal-entitieseprospera:entity.read
Fetch one of those entitiesGET /api/v1/me/legal-entities/{id}eprospera:entity.read
Fetch its documentsGET /api/v1/me/legal-entities/{id}/documentseprospera:entity.documents.read

See the OAuth overview for the authorization-code flow.

Decision tree — pick the right endpoint

Walk this top-down. Stop at the first row that matches your goal.

  1. You have an RPN string and want to know if it is real and active.POST /api/v1/verify_rpn with agent:verify_rpn.

  2. You have a human-readable name (or a partial RPN) and want to find the entity.POST /api/v1/registries/legal_entities/search with agent:registry.search. If results is empty, broaden the query — do not retry the same input.

  3. You have a legal-entity ID that your own agent created earlier.GET /api/v1/legal_entities/{id} with agent:entity.read.

  4. You have a legal-entity ID that came from outside this API (a human formed it in the portal, or a different account formed it).Not reachable with an Agent Key. Either ask the entity owner to authenticate via OAuth and call /api/v1/me/legal-entities/{id}, or have them transfer the formation through the API. Do not retry the Agent Key call — the 404 will not change.

  5. You want data about the human who owns the Agent Key (or the OAuth user).GET /api/v1/me/natural-person* with the matching agent:person.* or eprospera:person.* scope. Standard sk- keys are rejected here.

  6. You want a list of all legal entities a user represents (not just API-created ones). → OAuth only. GET /api/v1/me/legal-entities with eprospera:entity.read. An Agent Key on this path returns 401.

  7. You want to incorporate a new LLC. → See Recipe 2. The prerequisites (MoW + pre-accepted AOC + funding coupon) must be confirmed by the human owner before the agent starts — there is no headless path around them.

  8. You want to know when an application is approved. → Poll GET /api/v1/legal_entity_applications/{id} — see Polling, not webhooks.

Why your call might return empty

Read this section any time a response is unexpectedly empty, 404, 401, or 403. Most of these are by design, not bugs.

SymptomCauseFix
GET /legal_entity_applications returns { "data": [] }Agent Keys see only API-created applications (createdViaAPI: true). Applications started in the portal are invisible.If the owner started the application in the portal, the agent cannot list it. Restart it through the API, or have the owner finish it in the portal.
GET /legal_entities/{id} returns 404Either the entity does not exist, or it was created outside the API and is invisible to Agent Keys. There is no way to disambiguate.If you expect the entity to exist, use OAuth and /me/legal-entities/{id} instead.
GET /me/legal-entities* returns 401You sent an Agent Key (ak-...). This route family is OAuth-only.Switch to an OAuth access token; the user must complete the consent flow first.
Any endpoint returns 403The Agent Key is missing the required scope. It does not mean the resource is missing.The owner must regenerate the key with the scope (visible in the scope reference).
POST /legal_entity_applications returns 200 with nextSteps.signatureThe Agreement of Coexistence for that residency type was not pre-accepted on the owner's account.The owner opens that URL once in a browser to sign. After that, future creates of the same residency type are fully headless.
Any endpoint returns 429Per-key rate limit. verify_rpn and registries/legal_entities/search are capped at 50/minute and 5,000/day.Respect the Retry-After header. Spread bursty work; the limits are per-key, so spinning up more keys does not help.
Search returns { "results": [] }Query was too narrow or used punctuation the registry does not index.Reduce to the most distinctive single word. The server already tokenizes multi-word input on whitespace.
verify_rpn returns "not_found"The RPN string is malformed or unknown.Do not retry the same RPN. Treat as terminal.

Polling, not webhooks

There are no webhook callbacks today. Two state machines require polling:

OperationEndpoint to pollSuggested cadenceTerminal states
Legal-entity applicationGET /api/v1/legal_entity_applications/{id}Every 30 s, with backoff to 5 min after the first 10 minutes.Approved (then fetch the new legal_entities/{id}), Rejected.
Coupon paymentSame endpoint — the application transitions through Paid once the coupon clears.Every 10 s for ~1 minute.Paid (or PaymentFailed).

Always include a hard timeout in your polling loop (the recipes use 30 minutes) and surface the last response to the human if you exit without a terminal state.

Machine-readable resources

If your agent has fetch capability, ingest these instead of scraping rendered pages:

  • /llms.txt — short Markdown index of every doc page, per the llms.txt standard.
  • /llms-full.txt — every endpoint, scope, request/response shape, and convention concatenated into a single plain-text file. This is the densest single artifact for system-prompt injection.
  • /openapi.yaml — OpenAPI 3.1 spec. Use for client generation or schema-driven tool definitions (MCP, function-calling).

Where to go next

  • Pick credentials: Agent Keys — what they are, who can issue them, scope reference, limitations.
  • Get the shared rules right: Conventions — auth header, response envelopes, error envelope, status codes, timestamps, rate limits.
  • Copy a working workflow: Agent recipes — RPN lookup, automated LLC incorporation, resident-paid incorporation, profile reads.
  • Long-form incorporation walkthrough: Incorporating an entity.
  • Sign in with e-Próspera: OAuth overview.