# Agent recipes (/agent-recipes)

End-to-end API key and OAuth workflows you can copy, paste, and run. The CLI path is recommended when your runtime can execute shell commands; direct HTTP examples are included for custom clients and environments where the CLI is not available.



See [CLI](/cli) for installation, credential resolution, output flags, and exit codes. See [Conventions](/conventions) for shared direct HTTP rules.

> **Substitutions used below**
>
> * `$AK` — your Agent Key (`ak-...`)
> * `$SK` — your standard API key (`sk-...`)
> * `$OAUTH_TOKEN` — an OAuth access token with the scopes required by the recipe
> * `$BASE` — `https://portal.eprospera.com` in production, `https://staging-portal.eprospera.com` in staging
> * `$EPROSPERA_API_KEY` — the key the CLI reads when `--api-key` is not passed
> * `$VOUCHER` — a code that fully covers the invoice (`API1234` in staging; see [Testing in staging](/testing-in-staging))

For automation, prefer:

```bash
eprospera --json --yes <group> <command>
```

***

## Recipe 1 — RPN lookup → registry search → fetch entity [#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.read`
&#x2A;*Prerequisites:** Read-only Agent Key. Manifestation of Will is **not** required.
&#x2A;*Note:** `entity get` / `GET /api/v1/legal_entities/{id}` only returns entities created via the API (see [Agent Keys → Important Limitations](/agent-keys#important-limitations)).

### CLI [#cli]

```bash
export EPROSPERA_API_KEY="$AK"

# 1. If you have an RPN, confirm it exists and is active
eprospera --json entity verify 80000000000012

# 2. Search by RPN or name to get a legal-entity UUID
eprospera --json entity search 80000000000012
eprospera --json entity search "Acme Holdings"

# 3. Fetch the entity by id
eprospera --json entity get <id>
```

`entity verify` confirms existence and active status; it does not return the legal-entity UUID. Use `entity search` before `entity get`.

### Direct HTTP [#direct-http]

```bash
curl -s -X POST "$BASE/api/v1/verify_rpn" \
  -H "Authorization: Bearer $AK" \
  -H "Content-Type: application/json" \
  -d '{"rpn": "80000000000012"}'

curl -s -X POST "$BASE/api/v1/registries/legal_entities/search" \
  -H "Authorization: Bearer $AK" \
  -H "Content-Type: application/json" \
  -d '{"query": "Acme Holdings"}'

curl -s "$BASE/api/v1/legal_entities/<id>" \
  -H "Authorization: Bearer $AK"
```

**Watch for**

* `entity verify` returning `"not_found"` → the RPN string is malformed or unknown; do not retry.
* Search returning an empty `results` array → broaden the query, or split multi-word queries on whitespace.
* CLI exit code `5` / HTTP `404` on entity fetch → either the entity does not exist, or it was created outside the API and is invisible to Agent Keys.

***

## Recipe 2 — Fully automated LLC incorporation [#recipe-2--fully-automated-llc-incorporation]

Create an LLC application, pay it with a fully-discounting voucher, and pick up the resulting legal-entity record. Zero browser hops when the prerequisites are satisfied.

**Required scopes:** `agent:entity.application.create`, `agent:entity.application.pay`, `agent:entity.application.read`, `agent:entity.read`
&#x2A;*Prerequisites:**

* Active **Manifestation of Will** signed by the Agent Key owner.
* The **Agreement of Coexistence** for the relevant residency type (Resident or e-Resident LLC) must be **pre-accepted** during MoW signing. Without this, the create response includes `nextSteps.signature`, which requires a human browser session.
* A voucher code that fully covers the application invoice and is owned by the key owner.
* The owner is an active e-Resident or Resident.

Create `application.json`:

```json
{
  "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"
  }
}
```

### CLI [#cli-1]

```bash
export EPROSPERA_API_KEY="$AK"

# 1. Validate locally while preparing the JSON request
eprospera --json --dry-run application create --file application.json

# 2. Create the application
eprospera --json --yes application create --file application.json
# Capture data.id as APP_ID.
# If nextSteps.signature is non-null, stop and ask the owner to accept the AOC in a browser.

# 3. Apply the fully covering voucher
eprospera --json --yes application pay "$APP_ID" --voucher "$VOUCHER"

# 4. Poll until approval or terminal failure
eprospera --json application watch "$APP_ID" --timeout 30m
# Capture data.legalEntityId once statusId is Approved.

# 5. Fetch the resulting legal-entity record
eprospera --json entity get "$LEGAL_ENTITY_ID"
```

### Direct HTTP [#direct-http-1]

```bash
curl -s -X POST "$BASE/api/v1/legal_entity_applications" \
  -H "Authorization: Bearer $AK" \
  -H "Content-Type: application/json" \
  --data @application.json

curl -s -X POST "$BASE/api/v1/legal_entity_applications/<APP_ID>/pay/voucher" \
  -H "Authorization: Bearer $AK" \
  -H "Content-Type: application/json" \
  -d '{"voucherCode": "$VOUCHER"}'

curl -s "$BASE/api/v1/legal_entity_applications/<APP_ID>" \
  -H "Authorization: Bearer $AK"

curl -s "$BASE/api/v1/legal_entities/<LEGAL_ENTITY_ID>" \
  -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). CLI exit code `10` means the application or payment reached a terminal failure state.

**Watch for**

* CLI exit code `8` / HTTP `400` on create → schema validation failed; fix `application.json`.
* CLI exit code `6` / HTTP `409` on create → entity name collides with an existing entity of the same type; pick a new name.
* `nextSteps.signature` is non-null → the AOC was not pre-accepted; a browser signature is required.
* Voucher errors → voucher is missing, expired, redeemed, or under-funds the invoice.
* CLI exit code `4` / HTTP `403` → missing scope or revoked MoW.

***

## Recipe 3 — Resident-paid incorporation [#recipe-3--resident-paid-incorporation]

Agent Key hosted-checkout creation is temporarily disabled. For delegated flows, use the voucher recipe above, or create the application with the Agent Key and have the resident complete payment in the portal.

Standard API keys can create a hosted checkout for API-created applications.
The redirect URL must be an absolute URL, and the payment provider can be sent
with `--provider` or as an inline JSON object with `--payment-method`.

### CLI [#cli-2]

```bash
export EPROSPERA_API_KEY="$SK"

eprospera --json --yes application checkout <application-id> \
  --redirect-url https://example.com/return \
  --provider stripe
```

### Direct HTTP [#direct-http-2]

Use `POST /api/v1/legal_entity_applications/{id}/checkout_session`; the
[checkout reference](/reference/post-legal-entity-applications-id-checkout-session)
defines the supported request and response fields.

**Watch for**

* An Agent Key receives `403`; do not retry it as a checkout credential.
* The application must have been created through the API and still be payable.
* Treat the returned checkout URL as short-lived and open it in the resident's browser.

***

## Recipe 4 — Read account holder profile [#recipe-4--read-account-holder-profile]

Fetch the human owner's identity, residency status, and 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.read`
&#x2A;*Prerequisites:** Read-only Agent Key. MoW not required.

### CLI [#cli-3]

```bash
export EPROSPERA_API_KEY="$AK"

eprospera --json --fields id,fullName,email me profile
eprospera --json me residency
eprospera --json me id-verification
```

### Direct HTTP [#direct-http-3]

```bash
curl -s "$BASE/api/v1/me/natural-person" \
  -H "Authorization: Bearer $AK"

curl -s "$BASE/api/v1/me/natural-person/residency" \
  -H "Authorization: Bearer $AK"

curl -s "$BASE/api/v1/me/natural-person/id-verification" \
  -H "Authorization: Bearer $AK"
```

**Watch for**

* `/api/v1/me/natural-person` returning `null` → the owner has no approved residency yet.
* `/residency` returning `activeResidency: null` with `wasEverResident: true` → the owner is a former resident; treat as inactive.
* `/id-verification` returning all-`null` document URLs → the owner has not completed ID verification.
* These commands/endpoints accept OAuth tokens **and** Agent Keys — but **not** standard `sk-` keys.

***

## Recipe 5 — Read consented entities and tax records [#recipe-5--read-consented-entities-and-tax-records]

Use OAuth to inspect the signed-in user's own tax records or records for a legal
entity they selected during consent and still represent. These operations are
read-only; they do not create, edit, submit, or pay a filing.

**Required scopes:** `eprospera:entity.read` for entity profiles,
`eprospera:entity.documents.read` for entity documents, and the matching
`eprospera:person.tax.read` or `eprospera:entity.tax.read` scope for tax data.

### CLI [#cli-4]

```bash
eprospera auth login --oauth

# Inspect the entities selected during consent.
eprospera --json me legal-entities list
eprospera --json me legal-entities get <entity-id>
eprospera --json me legal-entities documents <entity-id>

# Read personal tax status and submitted income-tax filings.
eprospera --json tax status --subject personal
eprospera --json tax list --subject personal --type income --year 2025
eprospera --json tax get <filing-id>
eprospera tax download <filing-id> --document assessment --output assessment.pdf

# Replace "personal" with a consented entity UUID for entity tax data.
eprospera --json tax status --subject <entity-id>
```

### Direct HTTP [#direct-http-4]

```bash
curl -s "$BASE/api/v1/me/legal-entities" \
  -H "Authorization: Bearer $OAUTH_TOKEN"

curl -s "$BASE/api/v1/me/tax/summary?subject=personal" \
  -H "Authorization: Bearer $OAUTH_TOKEN"

curl -s "$BASE/api/v1/me/tax/filings?subject=personal&type=income&year=2025" \
  -H "Authorization: Bearer $OAUTH_TOKEN"

curl --fail --location \
  "$BASE/api/v1/me/tax/filings/<filing-id>/documents/assessment" \
  -H "Authorization: Bearer $OAUTH_TOKEN" \
  --output assessment.pdf
```

**Watch for**

* An empty entity list can be valid when the user selected no entities during consent.
* `403 insufficient_scope` means the token lacks the matching personal or entity scope.
* Entity access ends if consent is revoked or the user stops representing the entity.
* Tax responses and PDFs are confidential financial information; keep them out of logs and source control.

See [Tax and legal-entity data](/tax-and-entity-data) for pagination, access
boundaries, and local-file handling guidance.

***

## Polling guidance [#polling-guidance]

For CLI workflows, prefer:

```bash
eprospera --json application watch <application-id> --timeout 30m
```

For direct HTTP, 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](/conventions#webhooks)). `Approved` and `Rejected` are terminal — stop polling.

## Common errors quick-reference [#common-errors-quick-reference]

| CLI exit | HTTP status | Likely cause                                                                |
| -------- | ----------- | --------------------------------------------------------------------------- |
| `2`      | n/a         | Invalid command syntax or missing argument; inspect `eprospera schema`.     |
| `3`      | `401`       | Missing/invalid credential, or the Agent Key was revoked.                   |
| `4`      | `403`       | The credential lacks a required scope, consent, or active MoW.              |
| `5`      | `404`       | Resource does not exist or is invisible to your Agent Key.                  |
| `6`      | `409`       | Entity name conflict or impossible state transition.                        |
| `7`      | `429`       | Rate limit exceeded on `verify_rpn` / registry search.                      |
| `8`      | `400`       | Request body fails validation or a state precondition failed.               |
| `9`      | n/a         | Polling or network timeout; surface the last known state.                   |
| `10`     | n/a         | Application or voucher reached terminal failure.                            |
| `1`      | `500`       | Unexpected server or CLI failure; retry only idempotent reads with backoff. |
