# Agent Keys (/agent-keys) Agent Keys let an e-resident delegate specific API capabilities to an AI agent, CLI workflow, or third-party service without sharing their personal standard API key. ## Base URL [#base-url] | Environment | Origin | | ----------- | -------------------------------------- | | Production | `https://portal.eprospera.com` | | Staging | `https://staging-portal.eprospera.com` | All endpoint paths in this document are relative to that origin. The API ships from the same host as the consumer portal — there is no separate `api.eprospera.com`. ## TL;DR for agents [#tldr-for-agents] * Prefer the [official CLI](/cli) when your runtime can execute shell commands; it wraps the same API with JSON-first commands and stable exit codes. * Send the key as `Authorization: Bearer ak-...` on every request. * Every endpoint is **scope-checked**; missing scope returns `403`. * Shared rules (errors, status codes, timestamps, rate limits, pagination) are documented once in [Conventions](/conventions) — endpoint pages do not repeat them. * For copy-pasteable end-to-end CLI and HTTP workflows (incorporation, profile reads, registry lookups), see [Agent recipes](/agent-recipes). * CLI source repository: [Honduras-Prospera-inc/eprospera-cli](https://github.com/Honduras-Prospera-inc/eprospera-cli). * A machine-readable `openapi.yaml` and an `llms-full.txt` summary are published at the docs site root. ## What Agent Keys Are [#what-agent-keys-are] * **Standard API keys (`sk-`)** are still for personal or first-party use. They are not scoped and should not be shared. * **Agent Keys (`ak-`)** are created by the account owner in the e-Próspera settings UI and can only do the actions the owner explicitly selects. * Agent Keys are additive. Existing standard API key behavior does not change. ## Who Can Create Them [#who-can-create-them] Only the e-resident who owns the account can create an Agent Key in the portal settings page. This means Agent Key access is **not public** and **not open to arbitrary third parties**: * The account owner must create the key * The account owner must choose the scopes * The account owner must deliver the key to the service or agent they trust * The key only acts on behalf of that account, within the granted scopes ## Manifestation of Will [#manifestation-of-will] Write-capable Agent Keys require an active signed **Manifestation of Will**. * Read-only Agent Keys can be created without it * Any Agent Key with a write scope requires it * Revoking the Manifestation of Will automatically revokes linked write-capable Agent Keys The Manifestation of Will is signed in the same Developer settings area where Agent Keys are managed. ### Agreement of Coexistence (AOC) Acceptance [#agreement-of-coexistence-aoc-acceptance] When signing the Manifestation of Will, you can optionally also accept one or more Legal Entity Agreements of Coexistence (for Resident and/or e-Resident entities). If you do, agents using your key can create legal entity applications **without** requiring a separate browser-based signature step — the AOC acceptance is applied automatically from your stored acceptance. This is what enables fully automated entity incorporation via Agent Keys. Without pre-accepted AOCs, the API returns a `nextSteps.signature` URL that requires manual interaction. You can also accept additional AOCs later from the Developer settings without re-signing the Manifestation of Will. ## Drip Emails [#drip-emails] After signing the Manifestation of Will, you will receive a confirmation email. Additionally, you will receive a **weekly reminder email** every Monday as long as you have active write-capable Agent Keys. This email summarizes your active keys, recent agent activity, and reminds you of your legal responsibility to monitor or revoke keys you are no longer using. ## Audit Logs And Notifications [#audit-logs-and-notifications] All Agent Key requests are audited. Successful write actions also trigger email notifications to the account owner. Currently, notifications are sent when an Agent Key: * creates a legal entity application * applies a voucher payment to an application ## Authentication Model [#authentication-model] With the CLI, pass the key once per command or store it locally: ```bash export EPROSPERA_API_KEY="ak-..." eprospera --json entity verify 80000000000012 eprospera --api-key "$EPROSPERA_API_KEY" auth login \ --agent-key \ --scopes agent:verify_rpn,agent:registry.search ``` With direct HTTP, use Agent Keys like standard API keys: ```bash Authorization: Bearer ak-... ``` Agent Keys are **scope-checked**. A request fails with `403` if the key does not include the required scope. Standard API keys continue to work on the standard API routes that already supported them. ## Scope Reference [#scope-reference] ### Read Scopes [#read-scopes] | Scope | Description | | ----------------------------------- | ---------------------------------------------------------------------------------------------------- | | `agent:person.details.read` | Read personal details such as name, resident permit number, date of birth, address, and phone number | | `agent:person.residency.read` | Read current residency status and residency type | | `agent:person.id_verification.read` | Read identity-verification document URLs and selfie artifacts | | `agent:entity.read` | Read legal entity details for entities you represent | | `agent:entity.documents.read` | Read legal entity documents for entities you represent | | `agent:entity.application.read` | Read your API-created legal entity applications | | `agent:verify_rpn` | Verify whether an RPN exists and is active | | `agent:registry.search` | Search the legal-entity registry by name or RPN | ### Write Scopes [#write-scopes] | Scope | Description | | --------------------------------- | --------------------------------------------------- | | `agent:entity.application.create` | Create legal entity applications | | `agent:entity.application.pay` | Apply voucher payments to legal entity applications | ## Supported Commands And Endpoints [#supported-commands-and-endpoints] ### Agent-Key Read Commands [#agent-key-read-commands] | CLI command | Direct endpoint | Required Agent Scope | | ----------------------------------- | ----------------------------------------------- | ----------------------------------- | | `eprospera entity verify ` | `POST /api/v1/verify_rpn` | `agent:verify_rpn` | | `eprospera entity search ""` | `POST /api/v1/registries/legal_entities/search` | `agent:registry.search` | | `eprospera entity get ` | `GET /api/v1/legal_entities/{id}` | `agent:entity.read` | | `eprospera entity documents ` | `GET /api/v1/legal_entities/{id}/documents` | `agent:entity.documents.read` | | `eprospera application list` | `GET /api/v1/legal_entity_applications` | `agent:entity.application.read` | | `eprospera application get ` | `GET /api/v1/legal_entity_applications/{id}` | `agent:entity.application.read` | | `eprospera me profile` | `GET /api/v1/me/natural-person` | `agent:person.details.read` | | `eprospera me residency` | `GET /api/v1/me/natural-person/residency` | `agent:person.residency.read` | | `eprospera me id-verification` | `GET /api/v1/me/natural-person/id-verification` | `agent:person.id_verification.read` | ### Agent-Key Write Commands [#agent-key-write-commands] | CLI command | Direct endpoint | Required Agent Scope | | ------------------------------------------------------------ | --------------------------------------------------------- | --------------------------------- | | `eprospera --yes application create --file application.json` | `POST /api/v1/legal_entity_applications` | `agent:entity.application.create` | | `eprospera --yes application pay --voucher ` | `POST /api/v1/legal_entity_applications/{id}/pay/voucher` | `agent:entity.application.pay` | | `eprospera application watch --timeout 30m` | `GET /api/v1/legal_entity_applications/{id}` | `agent:entity.application.read` | ## Important Limitations [#important-limitations] * Agent Keys do **not** replace OAuth for consent-based legal-entity sharing flows * `/api/v1/me/legal-entities*` remains OAuth-only * There is currently no `/api/v1/legal_entities` list endpoint for Agent Keys; use known entity IDs with `GET /api/v1/legal_entities/{id}` and `GET /api/v1/legal_entities/{id}/documents` * `/api/v1/me/natural-person*` accepts OAuth access tokens or Agent Keys, but **not** standard API keys * Agent-key reads for `/api/v1/legal_entity_applications*` are limited to applications created through the API (`createdViaAPI: true`) * Agent Key checkout-session creation is temporarily disabled; use `POST /api/v1/legal_entity_applications/{id}/pay/voucher` or have the resident pay through the portal * Other existing standard-key routes that were not explicitly enabled for Agent Keys remain standard-key only ## Pagination [#pagination] List endpoints accessible to Agent Keys (`GET /api/v1/legal_entity_applications`, `GET /api/v1/legal_entities/{id}/documents`) are **not currently paginated** — the full result set is returned under `data` in a single response. There are no `?page` / `?cursor` parameters today. When pagination ships, it will mirror the envelope already used on `/api/v1/nomadlayer/applications`: ```json { "data": [ /* ... */ ], "pagination": { "page": 1, "pageSize": 20, "totalCount": 134, "pageCount": 7 } } ``` Design clients so adding a top-level `pagination` field will not break them. See [Conventions → Pagination](/conventions#pagination). ## Recommended Usage Pattern [#recommended-usage-pattern] Use: * **OAuth** when your integration needs interactive user consent and identity login * **Standard API keys (`sk-`)** for your own backend or personal automation * **Agent Keys (`ak-`)** when an e-resident is delegating narrowly scoped access to an AI agent, CLI workflow, or third-party service * **The CLI** when a shell command is acceptable and you want JSON output, local validation, polling, and stable exit codes * **Direct HTTP** when you are building a custom client, OAuth flow, or endpoint integration ## Example [#example] ```bash eprospera --api-key "ak-REDACTED" --json entity verify 80000000000012 ``` The equivalent direct HTTP request is: ```bash curl -X POST https://portal.eprospera.com/api/v1/verify_rpn \ -H "Authorization: Bearer ak-REDACTED" \ -H "Content-Type: application/json" \ -d '{"rpn": "80000000000012"}' ``` If the Agent Key includes `agent:verify_rpn`, the request succeeds. Otherwise the API returns `403`. For end-to-end multi-step CLI and HTTP flows (incorporation, profile reads, registry lookups), see [Agent recipes](/agent-recipes). --- # 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 For automation, prefer: ```bash eprospera --json --yes ``` *** ## 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` **Prerequisites:** Read-only Agent Key. Manifestation of Will is **not** required. **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 ``` `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/" \ -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` **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 FOUNDER100 # 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//pay/voucher" \ -H "Authorization: Bearer $AK" \ -H "Content-Type: application/json" \ -d '{"voucherCode": "FOUNDER100"}' curl -s "$BASE/api/v1/legal_entity_applications/" \ -H "Authorization: Bearer $AK" curl -s "$BASE/api/v1/legal_entities/" \ -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 \ --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` **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 eprospera --json me legal-entities documents # 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 eprospera tax download --document assessment --output assessment.pdf # Replace "personal" with a consented entity UUID for entity tax data. eprospera --json tax status --subject ``` ### 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//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 --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. | --- # Catalyst Program (/catalyst-program) e-Próspera's referral system: attribute residency and entity signups to your referral code and track referrals via the API. The Catalyst Program is e-Próspera's referral system. As a member, your referral code supports: * **Attribution** for referred natural persons and legal entities * **20% discount** on the first eligible paid natural-person residency application (applied automatically at checkout) Referral codes can be owned by natural persons or legal entities. ## Residency discount [#residency-discount] When a user attributed to your code reaches the payment step for an eligible residency application, the discount is applied automatically — no voucher needed. * Applies to the first paid natural-person residency application only * Does not apply to free residency options, renewals, entity applications, or other services * Does not stack with other invoice discounts ## Attributing entity incorporations [#attributing-entity-incorporations] Pass your `referralCode` when creating a legal-entity application to attribute it as a referral. If omitted, the application proceeds without attribution. ```bash curl -X POST https://portal.eprospera.com/api/v1/legal_entity_applications \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "applicationData": { "residencyType": "e-Resident", "entityType": "llc", "name": "New Company", "extension": "LLC", "principalOffice": { "line1": "123 Main Street", "city": "Roatan", "postalCode": "34101", "country": "Honduras" }, "contactEmail": "contact@example.com", "registeredAgentProvider": "prospera_employment_solutions", "registeredAgentDetails": null }, "referralCode": "MYCODE123" }' ``` See the full [POST legal\_entity\_applications](/reference/post-legal-entity-applications) reference for all available fields. ## Self-referral [#self-referral] By default, using your own referral code silently skips attribution — the application succeeds, but isn't counted as a referral. If your code has **self-referral enabled** (configured by an admin), attribution is recorded. This is useful for companies that incorporate entities on behalf of clients using a single API key. ## Checking referrals [#checking-referrals] List natural persons and legal entities referred with your code: ```bash curl -X GET https://portal.eprospera.com/api/v1/referral-codes/MYCODE123/referrals \ -H "Authorization: Bearer " ``` ```json { "code": "MYCODE123", "naturalPersons": [ { "fullName": "John Doe", "referredAt": "2024-03-15T14:30:00.000Z" } ], "legalEntities": [ { "name": "Acme Corp LLC", "rpn": "80123456789012", "referredAt": "2024-04-01T12:00:00.000Z" } ] } ``` See the full [GET referral\_codes/\[code\]/referrals](/reference/get-referral-codes-code-referrals) reference. This endpoint reports attribution only — it does not expose invoice or discount state. ## Access control [#access-control] You can only query referral codes that belong to you (your personal code, or codes owned by entities you represent). --- # e-Próspera CLI (/cli) The official CLI wraps the public API in commands that are easier for humans, scripts, CI jobs, and AI agents to call safely. Use it when your runtime can execute shell commands. Use direct HTTP only when you are building your own client, need an endpoint the CLI does not cover, or cannot install Node tooling. Source repository: [Honduras-Prospera-inc/eprospera-cli](https://github.com/Honduras-Prospera-inc/eprospera-cli). ## Install [#install] ```bash npm install -g @prospera/eprospera-cli eprospera --help ``` To update an existing installation and confirm the installed version: ```bash npm install -g @prospera/eprospera-cli@latest eprospera --version ``` The CLI requires a modern Node.js runtime. See the [`@prospera/eprospera-cli` npm package](https://www.npmjs.com/package/@prospera/eprospera-cli) for the published version and [GitHub Releases](https://github.com/Honduras-Prospera-inc/eprospera-cli/releases) for release notes and standalone bundles. ## Authenticate [#authenticate] The CLI resolves credentials in this order: 1. `--api-key ` 2. `EPROSPERA_API_KEY` 3. Credentials saved by `eprospera auth login` For one-off automation, pass the key explicitly or through the environment: ```bash export EPROSPERA_API_KEY="ak-..." eprospera --json entity verify 80000000000012 ``` To store an Agent Key for later commands, cache the scopes you granted in the portal: ```bash eprospera --api-key "$EPROSPERA_API_KEY" auth login \ --agent-key \ --scopes agent:verify_rpn,agent:registry.search,agent:entity.read ``` Use `--standard-key` instead of `--agent-key` for a standard `sk-...` key. Agent Keys remain scope-checked by the API; cached scopes are a local preflight and do not grant permissions by themselves. For user, consented-entity, and tax reads, authorize the official CLI with your e-Próspera account: ```bash eprospera auth login --oauth ``` The CLI uses device authorization, opens the consent page in a browser, and stores access and refresh tokens in the OS keychain when available. Access tokens refresh automatically. `eprospera --yes auth logout` attempts to revoke the remote tokens before deleting the local credential. ## Agent Mode [#agent-mode] For automation, prefer this shape: ```bash eprospera --json --yes ``` * `--json` prints machine-readable JSON and suppresses spinners and color. * `--raw` prints compact single-line JSON when token efficiency matters. * `--fields id,statusId,name` trims read output to selected top-level fields. * `--yes` skips confirmation prompts for write commands. * `--dry-run` validates locally and prints the request that would be sent. * `EPROSPERA_ENV=staging` points the CLI at staging. * `EPROSPERA_BASE_URL=` overrides the API base URL for trusted endpoints. Parse stdout as data. Treat stderr as diagnostics. ## Command Matrix [#command-matrix] | Goal | CLI command | Credentials | Scope | | ----------------------------- | ----------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------ | | Verify an RPN | `eprospera --json entity verify ` | `ak-`, `sk-` | `agent:verify_rpn` | | Search legal entities | `eprospera --json entity search ""` | `ak-`, `sk-` | `agent:registry.search` | | Fetch one legal entity | `eprospera --json entity get ` | `ak-`, `sk-` | `agent:entity.read` | | Fetch entity documents | `eprospera --json entity documents ` | `ak-`, `sk-` | `agent:entity.documents.read` | | List API-created applications | `eprospera --json application list` | `ak-`, `sk-` | `agent:entity.application.read` | | Create an application | `eprospera --json --yes application create --file application.json` | `ak-`, `sk-` | `agent:entity.application.create` | | Fetch one application | `eprospera --json application get ` | `ak-`, `sk-` | `agent:entity.application.read` | | Pay with voucher | `eprospera --json --yes application pay --voucher ` | `ak-`, `sk-` | `agent:entity.application.pay` | | Create hosted checkout | `eprospera --json --yes application checkout --redirect-url --provider ` | `sk-` | — | | Watch until terminal state | `eprospera --json application watch --timeout 30m` | `ak-`, `sk-` | `agent:entity.application.read` | | Read owner profile | `eprospera --json me profile` | `ak-`, OAuth | `agent:person.details.read` or `eprospera:person.details.read` | | Read owner residency | `eprospera --json me residency` | `ak-`, OAuth | `agent:person.residency.read` or `eprospera:person.residency.read` | | Read ID verification | `eprospera --json me id-verification` | `ak-`, OAuth | `agent:person.id_verification.read` or `eprospera:person.id_verification.read` | | List consented entities | `eprospera --json me legal-entities list` | OAuth | `eprospera:entity.read` | | Read a consented entity | `eprospera --json me legal-entities get ` | OAuth | `eprospera:entity.read` | | Read consented documents | `eprospera --json me legal-entities documents ` | OAuth | `eprospera:entity.documents.read` | | Show tax obligations | `eprospera --json tax status --subject ` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | | List tax filings | `eprospera --json tax list --subject --year 2025` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | | Read a tax filing | `eprospera --json tax get ` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | | Download a tax document | `eprospera tax download --document assessment` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | | List referral attribution | `eprospera --json referral list ` | `sk-` | — | | Submit a visitor pass | `eprospera --json --yes visitor-pass create ` | None | — | The CLI also includes `auth`, `config`, `completion`, and `schema` commands: ```bash eprospera --json auth whoami eprospera --json config list eprospera completion zsh eprospera schema ``` ## Common Workflows [#common-workflows] ### Verify and fetch an entity [#verify-and-fetch-an-entity] ```bash eprospera --json entity verify 80000000000012 eprospera --json entity search 80000000000012 eprospera --json entity get ``` `entity verify` confirms whether the RPN is known and active. It does not return the legal-entity UUID, so use `entity search` before `entity get`. ### Create, pay, and watch an LLC application [#create-pay-and-watch-an-llc-application] ```bash eprospera --json --dry-run application create --file application.json eprospera --json --yes application create --file application.json eprospera --json --yes application pay --voucher FOUNDER100 eprospera --json application watch --timeout 30m ``` Write-capable Agent Keys require an active Manifestation of Will. Fully headless incorporation also requires the owner to pre-accept the Agreement of Coexistence for the target residency type. See [Agent recipes](/agent-recipes) for a complete request file and failure handling. ### Create a hosted checkout with a standard key [#create-a-hosted-checkout-with-a-standard-key] ```bash eprospera --json --yes application checkout \ --redirect-url https://example.com/return \ --provider stripe ``` Hosted checkout requires a standard `sk-...` key and an API-created application. Agent Keys cannot create checkout sessions; use a fully covering voucher or let the resident complete payment in the portal instead. ### Read the key owner [#read-the-key-owner] ```bash eprospera --json --fields id,fullName,email me profile eprospera --json me residency eprospera --json me id-verification ``` These commands accept Agent Keys or OAuth credentials. Standard `sk-...` keys are not valid for `me` commands. ### Read taxes and download filed documents [#read-taxes-and-download-filed-documents] Tax responses and PDFs contain confidential financial information. The CLI can only read the signed-in user's records or a legal entity selected during consent; it cannot read other users' data or an entity that was not selected. See [Tax and legal-entity data](/tax-and-entity-data) for the complete access model and handling guidance. ```bash eprospera auth login --oauth eprospera --json tax status --subject personal eprospera --json tax list --subject personal --type income --year 2025 eprospera --json tax get eprospera --json tax download --document assessment ``` Use a consented legal-entity UUID as `--subject` for entity taxes. Downloads refuse to overwrite an existing file unless you pass `--yes`. ### Inspect referrals or submit a visitor pass [#inspect-referrals-or-submit-a-visitor-pass] Referral attribution requires a standard key. Visitor-pass submission is a public workflow and does not require a credential: ```bash eprospera --json referral list EXAMPLE_CODE eprospera --json --yes visitor-pass create \ --first-name Ada \ --last-name Lovelace \ --date-of-birth 1990-01-01 \ --email ada@example.test \ --signature "Ada Lovelace" \ --consent-to-background-check \ --referral-source "Prospera website" ``` ## Exit Codes [#exit-codes] | Code | Meaning | Agent behavior | | ---- | ------------------------------------ | ------------------------------------------------- | | `0` | Success | Continue. | | `1` | Unexpected failure | Surface the error and stop. | | `2` | Invalid usage | Fix command syntax or inspect `eprospera schema`. | | `3` | Authentication failure | Ask for a credential or run `auth login`. | | `4` | Authorization failure | Reauthorize or request the missing scope. | | `5` | Resource not found | Stop retrying the same lookup. | | `6` | Conflict | Ask for different input or state. | | `7` | Rate limit | Respect `Retry-After` and retry later. | | `8` | Validation error | Fix local input using `error.details`. | | `9` | Timeout | Surface the last polling state. | | `10` | Terminal application/payment failure | Stop and ask for new input. | Machine-mode errors use this shape: ```json { "error": { "code": "INVALID_USAGE", "message": "Human-readable failure.", "details": {} } } ``` ## When to Use Direct HTTP [#when-to-use-direct-http] Use the REST reference pages and `curl` examples when: * You are building an SDK, service integration, or browser/backend client. * You need to implement your own OAuth flow or client. * You need an endpoint the CLI does not cover. * You want exact wire-level request and response shapes. For direct HTTP rules, see [Conventions](/conventions), [Agent Keys](/agent-keys), and the endpoint reference pages. --- # Conventions (/conventions) Shared rules that apply across every endpoint of the e-Próspera API. Most reference pages link here instead of restating these conventions. If you are using the official CLI, start with [CLI](/cli). The CLI handles most of these wire-level details for you while still using the same credentials, scopes, and API behavior. ## Base URL [#base-url] All paths in this documentation are relative to one of these origins: | Environment | Origin | | ----------- | -------------------------------------- | | Production | `https://portal.eprospera.com` | | Staging | `https://staging-portal.eprospera.com` | So `GET /api/v1/legal_entities/{id}` in production is `GET https://portal.eprospera.com/api/v1/legal_entities/{id}`. There is no separate `api.eprospera.com` host — the API ships from the same origin as the consumer portal. ## Authentication [#authentication] Every authenticated request uses the `Authorization` header with a Bearer token: ```text Authorization: Bearer ``` The token can be one of four things: | Prefix / shape | Type | Notes | | -------------- | ---------------------- | ------------------------------------------------------------------------------- | | `sk-...` | Standard API key | Personal / first-party use. Never share. Not scoped. | | `ak-...` | Agent Key | Delegated, scope-checked. See [Agent Keys](/agent-keys). | | `pk-...` | Partner Key | Admin-issued, expiring, organization-scoped. See [Partner Keys](/partner-keys). | | JWT (RS256) | OAuth 2.0 access token | Issued by `/api/oauth/token`. Carries scopes from the user's consent grant. | Not every endpoint accepts every credential — see the **Authentication** block on each reference page. In particular, `/api/v1/me/*` does **not** accept standard API keys. ## Content type [#content-type] * Request bodies on `POST` endpoints are `application/json` unless the endpoint documents another type. Private proof uploads use `multipart/form-data`. * OAuth `/api/oauth/token` is `application/x-www-form-urlencoded` per RFC 6749. * All responses are `application/json` unless explicitly noted. ## Response envelopes [#response-envelopes] Most endpoints wrap successful payloads: | Endpoint shape | Envelope | | -------------------------------------- | -------------------------------------------------------- | | Single resource (`GET /resource/{id}`) | `{ "data": { ... } }` | | Collection (`GET /resource`) | `{ "data": [ ... ] }` (see [Pagination](#pagination)) | | Create flows | `{ "data": { ... }, "nextSteps": { ... } }` | | Voucher-pay endpoints | `{ "success": true, "data": { ... }, "message": "..." }` | | Search (`POST .../search`) | `{ "results": [ ... ] }` | | Verify (`POST /verify_rpn`) | `{ "result": "...", "active": true \| false }` | OAuth and JWKS endpoints follow their own RFCs (RFC 6749 / RFC 7517 / OIDC Core 1.0) and do **not** use the `data` wrapper. ## Error envelope [#error-envelope] Errors return a non-2xx status and a JSON body shaped like: ```json { "error": "short_machine_readable_code_or_message", "error_description": "Human-readable explanation. Optional.", "details": [ /* Zod issues or per-field errors. Optional. */ ] } ``` Some legacy endpoints return only `{ "error": "..." }`. Treat both shapes as the same contract: `error` is always present on a non-2xx response. `details` is most often a Zod issue array on `400` responses: ```json { "error": "Invalid request", "details": [ { "code": "invalid_type", "expected": "string", "received": "undefined", "path": ["applicationData", "name"], "message": "Required" } ] } ``` ## HTTP status codes [#http-status-codes] | Status | Meaning in this API | | ------ | ----------------------------------------------------------------------------------------------------- | | `200` | Success. | | `400` | Validation error or conflicting state (e.g. application already submitted). | | `401` | Missing, malformed, invalid, expired, or revoked credential; inactive Partner Integration. | | `403` | Credential is valid but lacks the required Agent/Partner Key scope or sufficient OAuth scope. | | `404` | Resource does not exist **or** the caller cannot see it. The two are intentionally indistinguishable. | | `409` | Conflict (e.g. legal-entity name, stale partner version, or idempotency-key reuse). | | `429` | Rate limit exceeded. See [Rate limits](#rate-limits). | | `500` | Server error. Safe to retry with backoff for idempotent operations only. | ## Timestamps [#timestamps] All timestamps are **strings in ISO 8601 / RFC 3339 UTC** form, e.g. `2024-01-15T10:30:00.000Z`. Never assume local time. Date-only fields (none currently in the API) would use `YYYY-MM-DD`. ## Nullability [#nullability] Optional fields are explicitly typed as `T | null` in this documentation and are present in responses with the value `null` rather than being omitted. If a field is documented as non-nullable, expect it to always be present. ## IDs [#ids] All identifiers are RFC 4122 v4 UUIDs (string form, lowercased, dashed) unless noted. Resident Permit Numbers (RPNs) are 14-digit numeric strings that start with `8` (legal entity) or `9` (natural person). ## Rate limits [#rate-limits] Rate limiting is per-endpoint or credential class, not global. Currently: | Endpoint | Limits | | ----------------------------------------------- | -------------------------------------------------- | | `POST /api/v1/verify_rpn` | 5,000 requests / 24 h and 50 / minute, per API key | | `POST /api/v1/registries/legal_entities/search` | 5,000 / 24 h and 50 / minute, per API key | | Partner reads | 120/min per key; 300/min per integration | | Partner updates and submission | 60/min per key; 150/min per integration | | Partner application creation | 10/min per key; 50/hour per integration | | Partner uploads | 20/min per key; 100/hour per integration | | Partner payments and vouchers | 5/min per key; 20/hour per integration | | Other endpoints | No documented limit today. | Partner throttling returns `429` with a `Retry-After` header. Invalid Partner Key attempts are limited to 20/minute per source IP. Other rate-limited endpoints may omit `Retry-After`; use exponential backoff when it is absent. ## Pagination [#pagination] Most list endpoints are not currently paginated. Two exceptions are `/api/v1/nomadlayer/applications` and the Partner Key application list. Partner applications use an opaque cursor: ```text GET /api/v1/partner/residency_applications?limit=50&cursor= ``` The partner `limit` defaults to 50 and cannot exceed 100. Read `pagination.nextCursor` for the next page. The Nomad Layer endpoint uses page-based pagination: ```json { "data": [ /* ... */ ], "pagination": { "page": 1, "pageSize": 20, "totalCount": 134, "pageCount": 7 } } ``` Other list endpoints return the full result set and have no pagination parameters today. ## Versioning [#versioning] All public endpoints live under `/api/v1/`. Breaking changes will go to a new `/api/v2/` prefix; existing `/api/v1/` endpoints remain stable. Additive changes (new fields, new optional query params, new endpoints) can land under `/api/v1/` without notice — clients should ignore unknown fields rather than reject them. ## Idempotency [#idempotency] Partner application creation, checkout creation, and voucher payment require `Idempotency-Key`. Keys are scoped to the integration and route and retained for 24 hours. Identical completed requests replay the saved response; different input or an in-progress duplicate returns `409`. `POST /legal_entity_applications` remains non-idempotent and can create a duplicate Draft when retried. Implement caller-side deduplication for that endpoint. ## Webhooks [#webhooks] There are no public webhooks. Approval, payment, AOC, and verification state must be discovered by polling the relevant `GET` endpoint. Partner responses summarize the applicant-only AOC/Veriff prerequisites in `nextSteps`; they never expose Veriff URLs or decision payloads. Recommended polling cadence is 5–30 seconds during an active flow, then exponential back-off. --- # Getting started (/getting-started) Choose an API key or OAuth, then send your first request through the CLI or direct HTTP. The e-Próspera public API can be used in two ways: * **CLI first:** use `eprospera` for shell, CI, and AI-agent workflows. * **Direct HTTP:** call the REST and OAuth endpoints yourself with `curl`, an SDK, or your backend client. Both paths reach the same public API, but the credential depends on whose data you need and what the caller is allowed to do. **Base URL:** `https://portal.eprospera.com` (production). Staging is `https://staging-portal.eprospera.com`. See [Conventions](/conventions) for shared rules. ## 1. Pick a Credential [#1-pick-a-credential] | Credential | Use it for | Where it works | | ------------------------ | ----------------------------------------------------------------------------------------- | ------------------------------------------------- | | Standard API key (`sk-`) | Your own backend, hosted checkout, referrals, and personal automation | CLI or direct HTTP | | Agent Key (`ak-`) | Delegated, explicitly scoped access for an AI agent, CLI workflow, or third-party service | CLI or direct HTTP | | OAuth | A signed-in user's profile, consented legal entities, and personal or entity tax data | Official CLI or your registered OAuth integration | For an API key, sign in to the portal and open [Settings > Developer](https://portal.eprospera.com/settings). If you are delegating access, create an Agent Key and grant only the scopes the CLI or agent needs. API keys act as you inside e-Próspera, so store them server-side or in a trusted secret manager and treat them like passwords. For OAuth data in the official CLI, no key is required. The browser consent screen identifies the requested permissions and lets the user select which legal entities to share. ## 2. Install the CLI [#2-install-the-cli] ```bash npm install -g @prospera/eprospera-cli eprospera --help ``` To update later, run `npm install -g @prospera/eprospera-cli@latest`. Published versions are available on [npm](https://www.npmjs.com/package/@prospera/eprospera-cli), with release notes and standalone bundles on [GitHub Releases](https://github.com/Honduras-Prospera-inc/eprospera-cli/releases). For one-off commands, export your key: ```bash export EPROSPERA_API_KEY="ak-..." ``` For repeated local use, store it with the CLI: ```bash eprospera --api-key "$EPROSPERA_API_KEY" auth login \ --agent-key \ --scopes agent:verify_rpn,agent:registry.search ``` Use `--standard-key` instead when storing a standard `sk-...` key. To authorize the official CLI for user, consented-entity, or tax reads: ```bash eprospera auth login --oauth ``` The CLI opens a browser for consent, stores rotating tokens securely, refreshes access tokens automatically, and attempts to revoke the remote session on logout. ## 3. Make Your First CLI Call [#3-make-your-first-cli-call] The simplest operation is verifying whether a resident permit number (RPN) belongs to a natural person or legal entity: ```bash eprospera --json entity verify 80000000000012 ``` Example response: ```json { "result": "found_legal_entity", "active": true } ``` The response tells you `80000000000012` belongs to a legal entity with an active residency. The same workflow can then search for the entity and fetch it: ```bash eprospera --json entity search 80000000000012 eprospera --json entity get ``` For automation, use `--json --yes` for write commands and parse stdout as data: ```bash eprospera --json --yes application create --file application.json ``` ## 4. Read Your Tax and Consented Entity Data [#4-read-your-tax-and-consented-entity-data] After OAuth login, list the legal entities selected during consent and inspect personal tax obligations: ```bash eprospera --json me legal-entities list eprospera --json tax status --subject personal eprospera --json tax list --subject personal --year 2025 ``` Use a returned legal-entity UUID as `--subject` to read that entity's tax data. These operations are read-only and require the corresponding personal or entity tax scope. See [Tax and legal-entity data](/tax-and-entity-data) for the complete access and sensitive-data model. ## 5. Direct HTTP Alternative [#5-direct-http-alternative] If you are building your own client, send the key as a bearer token: ```text Authorization: Bearer ak-... ``` The direct HTTP version of the first request is: ```bash curl -X POST https://portal.eprospera.com/api/v1/verify_rpn \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"rpn": "80000000000012"}' ``` Use direct HTTP when you need exact wire-level request/response shapes, an OAuth authorization-code flow for your own application, or an endpoint the CLI does not cover. The device flow is currently reserved for the official CLI. ## 6. Next Steps [#6-next-steps] * [CLI guide](/cli) — install, authenticate, run commands, handle exit codes. * [Agent recipes](/agent-recipes) — end-to-end CLI and HTTP workflows for Agent Keys. * [Agent Keys guide](/agent-keys) — delegated scopes, Manifestation of Will, limitations. * [Conventions](/conventions) — auth header, response envelopes, errors, timestamps, pagination, rate limits. * [Full `verify_rpn` reference](/reference/post-verify-rpn) — direct HTTP reference. * [Incorporate an LLC](/incorporating-entity) — long-form incorporation flow. * [OAuth / OIDC overview](/oauth-overview) — let users sign in with their e-Próspera account. * [Tax and legal-entity data](/tax-and-entity-data) — consented entities, tax filings, document downloads, and handling guidance. --- # Incorporating an entity (/incorporating-entity) This guide walks through the CLI and direct API flow for incorporating an LLC in Próspera. ## Prerequisites [#prerequisites] * An API key from [Settings > Developer](https://portal.eprospera.com/settings) * The API-key owner is an active `e-Resident` or `Resident` * Either a voucher code that covers the application invoice, or a standard API key for hosted checkout * Optional but recommended for automation: the [e-Próspera CLI](/cli) This flow can be driven either by a standard API key or by an Agent Key with the required write scopes. Agent Keys currently support voucher payments only. If you are delegating this flow to an AI agent, CLI workflow, or external service, read the [Agent Keys guide](/agent-keys) first. ## Overview [#overview] The flow has five stages: 1. Create the application. 2. Pay the application invoice (voucher or checkout session). 3. Collect the Agreement of Coexistence signature. 4. Wait until the application moves to `Pending Review`, then poll for approval. 5. Fetch the resulting legal-entity record. Payment and signature can happen in either order. The application moves out of `Draft` only after **both** are complete. ### Required Agent scopes for delegated incorporation [#required-agent-scopes-for-delegated-incorporation] If you are using an Agent Key instead of a standard API key, the key needs: * `agent:entity.application.create` * `agent:entity.application.read` * `agent:entity.read` * `agent:entity.application.pay` for voucher payments Write-capable Agent Keys require a signed Manifestation of Will. If the Manifestation of Will also includes acceptance of the relevant Agreement of Coexistence (AOC), the signature step is skipped entirely and the application can proceed directly to payment and submission — enabling fully automated entity incorporation. The `agent:entity.application.read` scope only returns applications created through this API. ## Step 1: Create the legal-entity application [#step-1-create-the-legal-entity-application] With the CLI, put the request body in `application.json`, validate it locally, then create the application: ```bash eprospera --json --dry-run application create --file application.json eprospera --json --yes application create --file application.json ``` The direct HTTP request is: ```bash curl -X POST https://portal.eprospera.com/api/v1/legal_entity_applications \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "applicationData": { "residencyType": "e-Resident", "entityType": "llc", "name": "My Company", "extension": "LLC", "principalOffice": { "line1": "123 Main Street", "city": "Roatan", "postalCode": "34101", "country": "Honduras" }, "contactEmail": "contact@mycompany.com", "registeredAgentProvider": "prospera_employment_solutions", "registeredAgentDetails": null }, "redirectUrl": "https://example.com/success" }' ``` Example response: ```json { "data": { "id": "215ea307-980e-46cb-9463-3e82d03dd08e", "statusId": "Draft", "applicationVersion": "1.0.0", "createdViaAPI": true, "submittedAt": null }, "nextSteps": { "signature": "https://portal.eprospera.com/en/application/api-terms/215ea307-980e-46cb-9463-3e82d03dd08e?token=abc123..." } } ``` The `nextSteps.signature` URL is the portal page where the signer reviews and signs the Agreement of Coexistence. If the Agent Key's Manifestation of Will includes acceptance of the relevant Agreement of Coexistence, `nextSteps.signature` will be `null` and the AOC is auto-applied from the stored acceptance. In this case, you can skip Step 3 entirely — just complete payment and the application auto-submits. ## Step 2: Pay the application invoice [#step-2-pay-the-application-invoice] Complete payment before final submission. Agent Keys can apply a voucher code directly. Standard API keys can also create a checkout session and send the user through a payment flow. If the Agreement of Coexistence has already been signed, the application may submit immediately after payment. Otherwise it remains paid and in draft until signature is completed. ### Option A: Apply a voucher [#option-a-apply-a-voucher] CLI: ```bash eprospera --json --yes application pay 215ea307-980e-46cb-9463-3e82d03dd08e --voucher STARTUP100 ``` Direct HTTP: ```bash curl -X POST https://portal.eprospera.com/api/v1/legal_entity_applications/215ea307-980e-46cb-9463-3e82d03dd08e/pay/voucher \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "voucherCode": "STARTUP100" }' ``` If the application is already signed, payment also submits it. If it is not signed yet, the endpoint still succeeds and returns a reminder message. Example response before signature: ```json { "success": true, "data": { "id": "215ea307-980e-46cb-9463-3e82d03dd08e", "statusId": "Draft", "submittedAt": null }, "message": "Application paid, but not signed yet - please sign the application to complete the process." } ``` In this unsigned-but-paid case, `statusId` remains `Draft` until the Agreement of Coexistence is signed. ### Option B: Create a checkout session [#option-b-create-a-checkout-session] Hosted checkout is currently standard-API-key only. Agent Key checkout-session creation is temporarily disabled. ```bash curl -X POST https://portal.eprospera.com/api/v1/legal_entity_applications//checkout_session \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "paymentProvider": "stripe", "redirectUrl": "https://example.com/payment-complete", "email": "contact@mycompany.com" }' ``` This returns a provider-specific checkout payload and the associated invoice ID. See the [`POST legal_entity_applications/{id}/checkout_session`](/reference/post-legal-entity-applications-id-checkout-session) reference. ## Step 3: Collect the signature [#step-3-collect-the-signature] If you accepted the Agreement of Coexistence when signing your Manifestation of Will (in Developer Settings), `nextSteps.signature` will be `null` and this step is not needed. The application auto-submits after payment. Send the signer to the `nextSteps.signature` URL returned by step 1. On that page, the signer can: * review the Agreement of Coexistence * sign it * finish submission immediately if payment is already complete If you supplied `redirectUrl` when creating the application, the signer is redirected there after completion. ## Step 4: Poll the application [#step-4-poll-the-application] Use the CLI watcher, `GET /api/v1/legal_entity_applications`, or `GET /api/v1/legal_entity_applications/{id}` to monitor status. ```bash eprospera --json application watch 215ea307-980e-46cb-9463-3e82d03dd08e --timeout 30m ``` Direct HTTP: ```bash curl -X GET https://portal.eprospera.com/api/v1/legal_entity_applications/215ea307-980e-46cb-9463-3e82d03dd08e \ -H "Authorization: Bearer " ``` Example response after submission: ```json { "data": { "id": "215ea307-980e-46cb-9463-3e82d03dd08e", "statusId": "Pending Review", "submittedAt": "2024-01-15T11:00:00.000Z", "approvedAt": null, "rejectedAt": null, "legalEntityId": null } } ``` Possible statuses: * `Draft`: waiting on payment and/or signature * `Pending Review`: submitted and awaiting review * `Approved`: approved and converted into a legal entity * `Rejected`: rejected by the review team Continue polling until the response contains both: * `statusId: "Approved"` * `legalEntityId` ## Step 5: Fetch the created legal entity [#step-5-fetch-the-created-legal-entity] CLI: ```bash eprospera --json entity get 2a4408c5-291e-4442-ba63-ac78f3f6eff7 ``` Direct HTTP: ```bash curl -X GET https://portal.eprospera.com/api/v1/legal_entities/2a4408c5-291e-4442-ba63-ac78f3f6eff7 \ -H "Authorization: Bearer " ``` Example response: ```json { "data": { "id": "2a4408c5-291e-4442-ba63-ac78f3f6eff7", "optionId": "llc", "type": "Limited Liability Company", "name": "My Company", "extension": "LLC", "nameStartsWithExtension": false, "formationDate": "2024-01-16T00:00:00.000Z", "registrationDate": "2024-01-16T09:30:00.000Z", "createdAt": "2024-01-16T09:30:00.000Z", "principalOfficeAddress": { "line1": "123 Main Street", "line2": null, "city": "Roatan", "state": null, "postalCode": "34101", "country": "Honduras" }, "residentPermitNumber": "80000000000123", "dissolutionDate": null } } ``` ## Common errors [#common-errors] | Status | Response | Meaning | | ------ | ------------------------------------------------------------- | -------------------------------------------------------------- | | `400` | `Invalid request body` | Payload does not match the schema. | | `400` | `Either registeredAgentProvider or registeredAgentDetails...` | Provide exactly one registered-agent mode. | | `400` | `Legal entity application is not in draft status` | Voucher payment only works while the application is a draft. | | `400` | `This endpoint can only be used for API-created applications` | Voucher payment is limited to API-created applications. | | `403` | `You must be an active resident...` | The API-key owner is not an active `e-Resident` or `Resident`. | | `409` | `An LLC with the name ... already exists` | The LLC name is already taken. | See the endpoint references for full request/response details: * [`POST legal_entity_applications`](/reference/post-legal-entity-applications) * [`POST legal_entity_applications/{id}/pay/voucher`](/reference/post-legal-entity-applications-id-pay-voucher) * [`POST legal_entity_applications/{id}/checkout_session`](/reference/post-legal-entity-applications-id-checkout-session) * [`GET legal_entity_applications/{id}`](/reference/get-legal-entity-applications-id) --- # Firebase Authentication integration (/oauth-firebase) Connect Firebase Authentication to e-Próspera as an OpenID Connect provider. OAuth clients are admin-provisioned. If you already have one, the client ID and redirect URIs are visible in [Settings > Developer](https://portal.eprospera.com/settings). To request a new client or re-issue a secret, use the [e-Próspera Help Center chat](https://help.eprospera.com/en/chat). Demo project: [Honduras-Prospera-inc/firebase-oauth-demo](https://github.com/Honduras-Prospera-inc/firebase-oauth-demo) ## 1. Create a Firebase project [#1-create-a-firebase-project] Create a Firebase project and a web app in the [Firebase console](https://console.firebase.google.com/). Then initialize Firebase in your app: ```ts import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; const firebaseConfig = { apiKey: "...", authDomain: "your-project.firebaseapp.com", projectId: "your-project", storageBucket: "your-project.firebasestorage.app", messagingSenderId: "...", appId: "...", }; const app = initializeApp(firebaseConfig); export const auth = getAuth(app); ``` ## 2. Add the OIDC provider in Firebase [#2-add-the-oidc-provider-in-firebase] In Firebase Authentication: 1. open **Authentication** 2. go to **Sign-in method** 3. add a new **OpenID Connect** provider Provider settings: * **Issuer** * production: `https://portal.eprospera.com` * staging: `https://staging-portal.eprospera.com` * **Client ID**: your provisioned e-Próspera OAuth client ID * **Client secret**: your provisioned e-Próspera OAuth client secret Use Firebase's generated callback URL as one of the redirect URIs on your e-Próspera OAuth client. ## 3. Request scopes [#3-request-scopes] Start with: ```text openid profile email ``` Add: * `offline_access` if your backend needs refresh tokens * `eprospera:person.details.read` * `eprospera:person.residency.read` * `eprospera:person.id_verification.read` * `eprospera:entity.read` * `eprospera:entity.documents.read` only when you need those resource APIs. ## 4. Handle refresh tokens server-side [#4-handle-refresh-tokens-server-side] If your backend calls e-Próspera APIs after sign-in, exchange and store refresh tokens on your server. Refresh tokens rotate on each use — always persist the newest `refresh_token` from `POST /api/oauth/token`. ## 5. Call resource endpoints [#5-call-resource-endpoints] After sign-in, use the access token to call e-Próspera endpoints: ```text Authorization: Bearer ``` See also: [OAuth overview](/oauth-overview) | [Token endpoint](/reference/oauth-token) | [GET /api/v1/me/natural-person](/reference/oauth-get-natural-person) --- # NextAuth.js integration (/oauth-nextauth) Use Auth.js / NextAuth with e-Próspera as a custom OIDC provider. OAuth clients are admin-provisioned. If you already have one, the client ID and redirect URIs are visible in [Settings > Developer](https://portal.eprospera.com/settings). To request a new client or re-issue a secret, use the [e-Próspera Help Center chat](https://help.eprospera.com/en/chat). ```javascript import NextAuth from 'next-auth'; async function refreshEProsperaToken(token) { const response = await fetch('https://portal.eprospera.com/api/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', Authorization: 'Basic ' + Buffer.from( `${process.env.EPROSPERA_CLIENT_ID}:${process.env.EPROSPERA_CLIENT_SECRET}` ).toString('base64'), }, body: new URLSearchParams({ grant_type: 'refresh_token', refresh_token: token.refreshToken, }), }); const refreshed = await response.json(); if (!response.ok) throw refreshed; return { ...token, accessToken: refreshed.access_token, accessTokenExpires: Date.now() + refreshed.expires_in * 1000, refreshToken: refreshed.refresh_token ?? token.refreshToken, }; } export const authOptions = { providers: [ { id: 'eprospera', name: 'eProspera', type: 'oauth', wellKnown: 'https://portal.eprospera.com/.well-known/openid-configuration', authorization: { params: { scope: 'openid email profile offline_access', }, }, idToken: true, checks: ['pkce', 'nonce', 'state'], profile(profile) { return { id: profile.sub, name: profile.name, email: profile.email, image: profile.picture, }; }, options: { clientId: process.env.EPROSPERA_CLIENT_ID, clientSecret: process.env.EPROSPERA_CLIENT_SECRET, }, }, ], callbacks: { async jwt({ token, account }) { if (account) { return { ...token, accessToken: account.access_token, accessTokenExpires: Date.now() + account.expires_in * 1000, refreshToken: account.refresh_token, }; } if (Date.now() < token.accessTokenExpires) { return token; } return refreshEProsperaToken(token); }, }, }; export default NextAuth(authOptions); ``` * Request `offline_access` if your server needs refresh tokens. * e-Próspera rotates refresh tokens — always persist the newest one from the token response. * Only request `eprospera:*` scopes if your app calls the `/api/v1/me/*` resource endpoints. --- # OAuth 2.0 / OpenID Connect (/oauth-overview) e-Próspera provides an OAuth 2.0 and OpenID Connect authorization server so third-party applications can authenticate users and access their data with consent. ## Capabilities [#capabilities] * Authenticate users with their e-Próspera account * Receive standard OIDC claims (`sub`, `name`, `email`, `picture`) * Obtain refresh tokens for long-lived server access via `offline_access` * Fetch user-authorized personal and legal-entity data through the `/api/v1/me/*` endpoints * Read personal or consented-entity tax obligations and submitted filings ## Getting credentials [#getting-credentials] OAuth clients are provisioned per account. If you already have one, you can view the **client ID**, allowed scopes, and redirect URIs in [Settings > Developer](https://portal.eprospera.com/settings). To request a new client or have your secret re-issued, use the [e-Próspera Help Center chat](https://help.eprospera.com/en/chat). ## Redirect URI requirements [#redirect-uri-requirements] Register every callback URI in full, including its scheme, host, port, path, and query string. Authorization requests use exact string matching: a URI that differs only by host capitalization, an explicit default port, or a trailing slash is still a different URI. * Production callbacks must use HTTPS. * Staging and local-development clients may use HTTP only with `127.0.0.1`, `[::1]`, or `localhost`. * Prefer `127.0.0.1` or `[::1]` for new local integrations. `localhost` remains supported for compatibility. * Credentials, fragments, and raw semicolons are not permitted. * Ports are matched exactly. Older stored callbacks may remain visible while you edit a client. They can be removed, but they are not automatically rewritten and cannot be duplicated if they no longer satisfy the current registration policy. A grandfathered HTTP callback is never accepted by the production authorization endpoint. ## Standard endpoints [#standard-endpoints] | Endpoint | URL | | ---------------------- | --------------------------------------------------------------- | | OpenID configuration | `https://portal.eprospera.com/.well-known/openid-configuration` | | JWKS | `https://portal.eprospera.com/api/oauth/.well-known/jwks.json` | | Authorization endpoint | `https://portal.eprospera.com/api/oauth/authorize` | | Device endpoint | `https://portal.eprospera.com/api/oauth/device_authorization` | | Token endpoint | `https://portal.eprospera.com/api/oauth/token` | | UserInfo endpoint | `https://portal.eprospera.com/api/oauth/userinfo` | | Revocation endpoint | `https://portal.eprospera.com/api/oauth/revoke` | | Introspection endpoint | `https://portal.eprospera.com/api/oauth/introspect` | Reference pages: * [OpenID configuration](/reference/oauth-openid-configuration) * [JWKS](/reference/oauth-jwks) * [Authorization endpoint](/reference/oauth-authorize) * [Device authorization endpoint](/reference/oauth-device-authorization) * [Token endpoint](/reference/oauth-token) * [UserInfo endpoint (GET)](/reference/oauth-userinfo) * [UserInfo endpoint (POST)](/reference/oauth-userinfo-post) * [Revocation endpoint](/reference/oauth-revoke) * [Introspection endpoint](/reference/oauth-introspect) ## Recommended initial scopes [#recommended-initial-scopes] Start with: ```text openid profile email ``` Add `offline_access` if your backend needs refresh tokens. ## Supported scopes [#supported-scopes] | Scope | Description | | --------------------------------------- | --------------------------------------------------------------- | | `openid` | Authenticate the user with e-Próspera. | | `profile` | Read the user's name and profile picture. | | `email` | Read the user's email address. | | `offline_access` | Receive a refresh token for background access-token renewal. | | `eprospera:person.details.read` | Read detailed natural-person profile data. | | `eprospera:person.residency.read` | Read the user's current residency status. | | `eprospera:person.id_verification.read` | Read the latest approved identity-verification images. | | `eprospera:entity.read` | Read legal-entity data for entities the user consents to share. | | `eprospera:entity.documents.read` | Read legal-entity documents for consented entities. | | `eprospera:person.tax.read` | Read the user's tax obligations and submitted filings. | | `eprospera:entity.tax.read` | Read tax data for consented legal entities. | ## Consent behavior [#consent-behavior] When you request entity scopes (`eprospera:entity.read`, `eprospera:entity.documents.read`, or `eprospera:entity.tax.read`), the consent screen lets the user choose which legal entities to share. The access token is limited to that selection. This means: * `GET /api/v1/me/legal-entities` can return an empty array even with a valid token. * `GET /api/v1/me/legal-entities/{id}` and `/documents` only work for consented entity IDs. * If the user is no longer a representative of an entity, it stops appearing in responses. ## Remembered consent [#remembered-consent] Once a user approves your client, the grant is remembered. Later authorization requests covered by the remembered grant skip the consent screen — the user is redirected straight back to your `redirect_uri` with a fresh authorization code. Requests for additional scopes show the consent screen again, and you can always force it with `prompt=consent`. ## Revocation from Connected apps [#revocation-from-connected-apps] Users can revoke your app's access at any time from portal **Settings → Connected apps**. Revocation invalidates all of your tokens for that user: access tokens stop working, and refresh attempts fail with `invalid_grant`. Handle `invalid_grant` by sending the user back through the authorization flow. ## PKCE [#pkce] All newly registered clients must use PKCE: send `code_challenge` + `code_challenge_method=S256` on the authorization request and the matching `code_verifier` on the token exchange. Authorization requests from PKCE-required clients without a code challenge fail with `error=invalid_request`. Existing clients without the flag should adopt PKCE too — it is strongly recommended for every integration. ## Client secret rotation [#client-secret-rotation] You can request a rotation of your client secret at any time through the [e-Próspera Help Center chat](https://help.eprospera.com/en/chat). After a rotation, the old secret keeps working during a grace period so you can deploy without downtime — update your integration to the new secret before the grace period expires. ## Resource endpoints [#resource-endpoints] For an end-to-end explanation of user and entity selection, CLI examples, and sensitive-data handling, see [Tax and legal-entity data](/tax-and-entity-data). The scopes above unlock these endpoints: | Endpoint | Required scope | | ------------------------------------------------------------------------------------------------------ | --------------------------------------- | | [GET `/api/v1/me/natural-person`](/reference/oauth-get-natural-person) | `eprospera:person.details.read` | | [GET `/api/v1/me/natural-person/residency`](/reference/oauth-get-natural-person-residency) | `eprospera:person.residency.read` | | [GET `/api/v1/me/natural-person/id-verification`](/reference/oauth-get-id-verification) | `eprospera:person.id_verification.read` | | [GET `/api/v1/me/legal-entities`](/reference/oauth-get-legal-entities) | `eprospera:entity.read` | | [GET `/api/v1/me/legal-entities/{id}`](/reference/oauth-get-legal-entities-id) | `eprospera:entity.read` | | [GET `/api/v1/me/legal-entities/{id}/documents`](/reference/oauth-get-legal-entities-id-documents) | `eprospera:entity.documents.read` | | [GET `/api/v1/me/tax/summary`](/reference/oauth-get-tax-summary) | personal or entity tax read | | [GET `/api/v1/me/tax/filings`](/reference/oauth-list-tax-filings) | personal or entity tax read | | [GET `/api/v1/me/tax/filings/{filingId}`](/reference/oauth-get-tax-filing) | personal or entity tax read | | [GET `/api/v1/me/tax/filings/{filingId}/documents/{document}`](/reference/oauth-download-tax-document) | personal or entity tax read | `/api/v1/me/natural-person/id_verification` (underscore) exists as a compatibility alias. Use `/id-verification` (hyphen) for new integrations. ## Authorization flow [#authorization-flow] * `response_type=code` is required. * `state` is required. * `nonce` is required when `openid` is in scope. * `response_mode` is optional (`query`, `fragment`, or `form_post`; default `query`). * `prompt`, `max_age`, and `login_hint` are supported — see the [authorization endpoint reference](/reference/oauth-authorize). * Every authorization response includes the `iss` parameter (RFC 9207); validate it against `https://portal.eprospera.com`. * Unauthenticated users are redirected to the portal login before returning to the authorization request. * Repeat the registered `redirect_uri` exactly during the authorization-code exchange. ## Client authentication and request encoding [#client-authentication-and-request-encoding] Send token, revocation, and introspection requests as `application/x-www-form-urlencoded`. HTTP Basic authentication is recommended: ```bash curl -X POST https://portal.eprospera.com/api/oauth/token \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=$CODE" \ -d "redirect_uri=$REDIRECT_URI" \ -d "code_verifier=$CODE_VERIFIER" ``` `client_secret_post` remains available for compatibility. Do not combine Basic authentication with body credentials, and do not repeat OAuth parameters. The official CLI is a registered public client. Its device-token and revocation requests send the client ID without a client secret. This secretless public-client mode is reserved for the official CLI; third-party clients should use their provisioned authentication method and the authorization-code flow with PKCE. ## Device authorization for the official CLI [#device-authorization-for-the-official-cli] The official `eprospera` CLI is a public OAuth client and uses the device flow, so it never embeds a client secret. Start it with: ```bash eprospera auth login --oauth ``` The CLI displays a short code and opens the portal consent page. It polls the token endpoint at the server-provided interval, handles `authorization_pending` and `slow_down`, and stores the resulting rotating refresh token securely. This flow is currently reserved for the official CLI; third-party OAuth clients use the authorization-code flow with PKCE. ## Refresh tokens [#refresh-tokens] Access tokens expire after 1 hour. If the granted scope set includes `offline_access`, the token response also includes a `refresh_token` valid for up to 180 days. Example refresh request: ```bash curl -X POST https://portal.eprospera.com/api/oauth/token \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token" \ -d "refresh_token=$REFRESH_TOKEN" ``` Refresh tokens rotate on every successful refresh. Always persist the newest `refresh_token` from the response. You may request a reduced scope set on refresh, provided it is a subset of the originally granted scopes. When `openid` is granted, the refresh response also includes a fresh `id_token` whose `auth_time` remains the time of the user's original authentication. Reusing an already rotated refresh token revokes its token family; restart the authorization flow after `invalid_grant`. ## Bearer-token errors [#bearer-token-errors] Protected endpoints return a `WWW-Authenticate: Bearer` challenge for missing or invalid access tokens. A valid token without the required scope returns `403` with `error="insufficient_scope"`. The UserInfo endpoint supports both GET and POST. ## Framework guides [#framework-guides] * [Integration with NextAuth.js](/oauth-nextauth) * [Integration with Firebase Authentication](/oauth-firebase) --- # Partner Keys (/partner-keys) Partner Keys let an approved organization create and manage natural-person residency applications over REST. Each `pk-...` key belongs to one Partner Integration and can access only that integration's applications. The actors have separate responsibilities: the partner manages application data, private proof uploads, payment, status, and submission. The authenticated applicant personally accepts the Agreement of Coexistence (AOC) and completes Veriff inside eProspera. Partners cannot submit a signature, start Veriff, receive a Veriff URL, or read Veriff documents or decisions through this API. ## Base URL [#base-url] | Environment | Origin | | ----------- | -------------------------------------- | | Production | `https://portal.eprospera.com` | | Staging | `https://staging-portal.eprospera.com` | ## Provisioning and key lifecycle [#provisioning-and-key-lifecycle] Partner integrations and keys are issued by eProspera administrators. They are not self-service. * The raw key is displayed once. eProspera stores only its SHA-256 hash. * Keys expire after 90 days. * Issuing a replacement key shortens older active keys to a maximum seven-day overlap. * A key can be revoked immediately. Integrations can be suspended or revoked independently. * Authentication is rejected when the key is expired or revoked, the integration is not active, or its legal entity is dissolved. * Redirect and checkout return URLs must use an HTTPS origin approved on the integration. Send the key on every request: ```text Authorization: Bearer pk-... ``` ## Scopes [#scopes] | Scope | Capability | | ----------------------------------- | ----------------------------------------------------------------- | | `partner:person.application.read` | List and read this integration's applications and private uploads | | `partner:person.application.create` | Create applications and upload proof of address | | `partner:person.application.update` | Update Draft applications and upload proof of address | | `partner:person.application.pay` | Create checkout sessions and apply voucher payments | | `partner:person.application.submit` | Submit a completed application | There is no API scope for signing the Agreement of Coexistence. Applicant consent always occurs on an eProspera-hosted page. ## Endpoints [#endpoints] | Method | Path | Required scope | | ------- | -------------------------------------------------------------- | --------------------------------------------------- | | `POST` | `/api/v1/partner/residency_applications` | `partner:person.application.create` | | `GET` | `/api/v1/partner/residency_applications` | `partner:person.application.read` | | `GET` | `/api/v1/partner/residency_applications/{id}` | `partner:person.application.read` | | `PATCH` | `/api/v1/partner/residency_applications/{id}` | `partner:person.application.update` | | `POST` | `/api/v1/uploads/proof_of_address` | `create` or `update` | | `GET` | `/api/v1/uploads/proof_of_address/{uploadId}` | `read`, `create`, or `update` | | `POST` | `/api/v1/partner/residency_applications/{id}/checkout_session` | `partner:person.application.pay` | | `POST` | `/api/v1/partner/residency_applications/{id}/pay/voucher` | `partner:person.application.pay` | | `POST` | `/api/v1/partner/residency_applications/{id}/pay/coupon` | `partner:person.application.pay` (deprecated alias) | | `POST` | `/api/v1/partner/residency_applications/{id}/submit` | `partner:person.application.submit` | Cross-partner reads and mutations return `404` so the existence of another integration's resources is not disclosed. ## Secure application flow [#secure-application-flow] ### Partner and applicant responsibilities [#partner-and-applicant-responsibilities] | Stage | Partner through the Partner API | Applicant inside eProspera | | --------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ | | Application | Creates the Draft and updates data using `expectedVersion` | — | | Proof and payment | Uploads private proof of address and completes checkout or voucher payment | — | | Account access | Reads `applicantPortalAccess` status only; never receives the claim token | Claims the account from the 24-hour email and logs in | | AOC acceptance | Fetches and delivers the current `agreementUrl`; **the partner cannot sign** | Authenticates as the application owner and signs only on eProspera | | Veriff | Reads `verificationRequired` and `submitReady` only; **cannot initiate Veriff or view its data** | Starts and completes Veriff in the authenticated portal | | Submission and status | Submits when `submitReady` is `true`, then polls application status | — | 1. Create a Draft with `POST /partner/residency_applications` and a unique `Idempotency-Key`. eProspera sends the applicant a single-use account-claim link that expires after 24 hours. 2. Choose one proof path: upload a document using the new application ID, or send `applicationData.personalDetails.proofOfAddressSwornStatement` inline on create/PATCH. 3. For the upload path only, attach the returned opaque `proofOfAddressUploadId` with `PATCH /partner/residency_applications/{id}` and the latest `expectedVersion`. The sworn-statement path skips upload and attachment. 4. Pay with a checkout session or voucher. Each payment request requires its own `Idempotency-Key`. 5. Instruct the applicant to use the claim email and log in to eProspera. Fetch the application again after the final PATCH, then send that applicant the current `nextSteps.agreementUrl`. 6. The agreement URL contains a 30-minute, single-use token. eProspera requires the applicant's Auth0 login and verifies that the logged-in subject owns the application. During login, the bearer is held server-side behind a short-lived, single-use opaque continuation rather than copied into login or `returnTo` URLs. A different user receives `404`, and admin impersonation is not accepted as applicant identity. 7. After acceptance, fetch the application again: acceptance consumes the link and increments `version`. Use the refreshed version for any later PATCH. 8. The logged-in applicant starts and completes Veriff in the authenticated eProspera portal. The partner sees only `applicantPortalAccess`, `nextSteps.verificationRequired`, and `nextSteps.submitReady`. 9. Submit the application after `nextSteps.submitReady` becomes `true`. The hosted agreement page selects the applicable AOC server-side. Acceptance records the agreement ID and version, SHA-256 hashes of its content and the legally relevant application data, the authenticated applicant's Auth0 subject, signer name, signature image, timestamp, IP address, user agent, and access-token ID. A legally relevant PATCH invalidates the current acceptance and returns a new `agreementUrl`; submission also rejects consent if application data changed through another path. Bearer-only acceptances without a matching authenticated signer are not valid for submission. Submission requires current agreement acceptance, proof of address, a paid invoice, and approved identity verification. AOC acceptance and payment endpoints never submit the application; submission occurs only through `/submit` with `partner:person.application.submit`. ## Create and update contracts [#create-and-update-contracts] Create requests require `Idempotency-Key`: ```bash curl -X POST https://portal.eprospera.com/api/v1/partner/residency_applications \ -H "Authorization: Bearer pk-REDACTED" \ -H "Idempotency-Key: application-ada-20260716" \ -H "Content-Type: application/json" \ -d '{ "applicationData": { "residencyType": "e_resident", "personalDetails": { "givenName": "Ada", "surname": "Lovelace", "email": "applicant@example.com", "dateOfBirth": "1990-12-10", "sex": "female", "countryOfBirth": "GB", "citizenships": ["GB"], "alternateNamesAttestation": false, "criminalBackgroundAttestation": true, "address": { "line1": "123 Main St", "city": "London", "postalCode": "SW1A 1AA", "country": "GB" }, "phoneNumber": "+447700900123" } }, "redirectUrl": "https://partner.example/return" }' ``` An update sends the full application DTO plus the response's latest `version`: ```json { "expectedVersion": 3, "applicationData": { "residencyType": "e_resident", "personalDetails": { "givenName": "Ada", "surname": "Lovelace", "email": "applicant@example.com", "dateOfBirth": "1990-12-10", "sex": "female", "countryOfBirth": "GB", "citizenships": ["GB"], "alternateNamesAttestation": false, "criminalBackgroundAttestation": true, "proofOfAddressUploadId": "12345678-abcd-4abc-8abc-123456789012", "address": { "line1": "123 Main St", "city": "London", "postalCode": "SW1A 1AA", "country": "GB" }, "phoneNumber": "+447700900123" } } } ``` Once an invoice is paid, the residency type and applicant email are locked. A stale `expectedVersion` returns `409` with `currentVersion`. ## Response fields [#response-fields] Application responses include: | Field | Meaning | | -------------------------------------------------------- | ---------------------------------------------------------------- | | `version` | Integer used as the next PATCH `expectedVersion` | | `applicationData` | Curated application data | | `applicationData.personalDetails.proofOfAddressUploadId` | Opaque private-upload ID, when an upload is attached | | `applicantPortalAccess` | Claim/login metadata; never contains credentials or a Veriff URL | | `nextSteps.agreementUrl` | Hosted consent URL while current acceptance is required | | `nextSteps.proofOfAddressRequired` | Whether proof is still missing | | `nextSteps.paymentRequired` | Whether payment is still required | | `nextSteps.verificationRequired` | Whether portal identity verification is still required | | `nextSteps.verificationInstructions` | Applicant-facing portal verification guidance, when required | | `nextSteps.submitReady` | Whether all submission prerequisites currently pass | `nextSteps.agreementUrl` is ephemeral. Fetch the application after every PATCH and after AOC acceptance. Do not cache or reuse an older URL or `version`. `applicantPortalAccess.claimLinkSent` and `claimLinkSentAt` describe whether the current mutation enqueued a claim email. GET requests do not send email and therefore return `false` and `null` for those fields. Application lists use cursor pagination: ```text GET /api/v1/partner/residency_applications?limit=50&cursor= ``` `limit` defaults to 50 and cannot exceed 100. The response contains `pagination.nextCursor`, or `null` on the final page. ## Idempotency [#idempotency] Application creation, checkout creation, and voucher payment require an `Idempotency-Key` containing 8–128 URL-safe characters. Records are retained for 24 hours per integration and route. * An identical completed request replays the stored response with `Idempotency-Replayed: true`. * Reusing a key with different input returns `409`. * A duplicate received while the original is processing returns `409`. ## Rate limits [#rate-limits] Limits are enforced by both API key and integration: | Class | Per key | Per integration | | ---------------------- | ---------- | --------------- | | Reads | 120/minute | 300/minute | | Updates and submission | 60/minute | 150/minute | | Application creation | 10/minute | 50/hour | | Uploads | 20/minute | 100/hour | | Payment and vouchers | 5/minute | 20/hour | Invalid credentials are limited to 20 attempts per minute per source IP. A throttled request returns `429` and a `Retry-After` header. ## Errors [#errors] | Status | Meaning | | ------ | --------------------------------------------------------------- | | `400` | Invalid request, disallowed redirect origin, or invalid state | | `401` | Missing, invalid, expired, or revoked key; inactive integration | | `403` | Valid key without the required scope | | `404` | Resource missing or owned by another integration | | `409` | Stale application version or idempotency conflict | | `429` | Rate limit exceeded; use `Retry-After` | Every successful action, denied scoped action, throttling decision, inactive-key attempt, and admin key lifecycle change is durably audited without storing raw credentials. --- # Skills for AI Agents (/skills-for-agents) A CLI-first 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 e-Próspera, paste this page (or `/llms-full.txt`) into your agent's system prompt or skill folder. Official CLI: [Honduras-Prospera-inc/eprospera-cli](https://github.com/Honduras-Prospera-inc/eprospera-cli). ## TL;DR — what an agent must internalize before the first call [#tldr--what-an-agent-must-internalize-before-the-first-call] * **Use the CLI first when shell access is available:** `eprospera --json --yes `. * **Docs, in order:** [CLI](/cli) (install, auth, exit codes) → [Agent Keys](/agent-keys) or [OAuth](/oauth-overview) (credentials & scopes) → [Conventions](/conventions) (HTTP rules) → this page (capabilities & dead ends) → [Agent recipes](/agent-recipes) (copy-paste workflows). * **Every Agent Key request is scope-checked.** CLI exit code `4` or HTTP `403` means the key is missing the scope, **not** that the resource is absent. * **A `404` / CLI exit code `5` from legal-entity reads 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](#why-your-call-might-return-empty). * **Consented entities and tax records require OAuth.** They are read-only and limited to the signed-in user or selected entities the user still represents. * **There are no webhooks.** Use `eprospera application watch --timeout 30m` or poll the direct API — see [Polling, not webhooks](#polling-not-webhooks). ## Invocation Rules [#invocation-rules] Prefer this shape for automation: ```bash eprospera --json --yes ``` * Parse stdout as JSON. Treat stderr as diagnostics. * Use `--raw` when compact single-line JSON is better. * Use `--fields id,statusId,name` to reduce read responses. * Use `--dry-run` before write commands while constructing request files. * Put credentials in `--api-key`, `EPROSPERA_API_KEY`, or `auth login`; never echo tokens. * Use `EPROSPERA_ENV=staging` for staging checks. * Use direct HTTP only when the CLI does not cover the task or you are implementing your own client. ## CLI Capability Matrix [#cli-capability-matrix] | I want to… | Run | Credentials | Required scope | Common dead-end | | ------------------------------- | ----------------------------------------------------------------------------------------- | ------------ | ----------------------------------------------------------------------------- | ----------------------------------------------------------- | | Confirm an RPN exists | `eprospera --json entity verify ` | `sk-`, `ak-` | `agent:verify_rpn` | RPN must be 14 digits starting with 8 or 9. | | Search the registry | `eprospera --json entity search ""` | `sk-`, `ak-` | `agent:registry.search` | Empty results are not a bug; broaden or simplify the query. | | Fetch one legal entity | `eprospera --json entity get ` | `sk-`, `ak-` | `agent:entity.read` | Agent Keys see only API-created entities. | | Fetch entity documents | `eprospera --json entity documents ` | `sk-`, `ak-` | `agent:entity.documents.read` | Same API-created-entity limitation. | | List API-created applications | `eprospera --json application list` | `sk-`, `ak-` | `agent:entity.application.read` | Portal-created applications are invisible to Agent Keys. | | Create an LLC application | `eprospera --json --yes application create --file application.json` | `sk-`, `ak-` | `agent:entity.application.create` | JSON fails schema validation, or AOC was not pre-accepted. | | Fetch an application | `eprospera --json application get ` | `sk-`, `ak-` | `agent:entity.application.read` | The application must have been created through the API. | | Pay with a voucher | `eprospera --json --yes application pay --voucher ` | `sk-`, `ak-` | `agent:entity.application.pay` | Voucher must fully cover the invoice. | | Create hosted checkout | `eprospera --json --yes application checkout --redirect-url --provider ` | `sk-` | — | Agent Key checkout is disabled. | | Watch for approval | `eprospera --json application watch --timeout 30m` | `sk-`, `ak-` | `agent:entity.application.read` | Rejected/payment-failed states are terminal. | | Read the owner's profile | `eprospera --json me profile` | `ak-`, OAuth | `agent:person.details.read` / `eprospera:person.details.read` | Standard `sk-` keys are not valid for `me` commands. | | Read residency status | `eprospera --json me residency` | `ak-`, OAuth | `agent:person.residency.read` / `eprospera:person.residency.read` | Missing residency-read scope. | | Read ID-verification artifacts | `eprospera --json me id-verification` | `ak-`, OAuth | `agent:person.id_verification.read` / `eprospera:person.id_verification.read` | Signed URLs expire; download promptly. | | List consented entities | `eprospera --json me legal-entities list` | OAuth | `eprospera:entity.read` | An empty list is valid when no entities were selected. | | Read a consented entity | `eprospera --json me legal-entities get ` | OAuth | `eprospera:entity.read` | Consent and current representation are both required. | | Read consented entity documents | `eprospera --json me legal-entities documents ` | OAuth | `eprospera:entity.documents.read` | Consent and current representation are both required. | | Show tax obligations | `eprospera --json tax status --subject ` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | Scope must match `personal` or the selected entity. | | List tax filings | `eprospera --json tax list --subject --year 2025` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | Cursors are opaque; never edit or decode them. | | Read one tax filing | `eprospera --json tax get ` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | The filing must be visible to the current grant. | | Download a tax document | `eprospera tax download --document assessment` | OAuth | `eprospera:person.tax.read` or `eprospera:entity.tax.read` | Output contains confidential financial information. | | List referral attribution | `eprospera --json referral list ` | `sk-` | — | Agent Keys are not valid for referral reads. | | Submit a visitor pass | `eprospera --json --yes visitor-pass create ` | None | — | All applicant fields and explicit consent are required. | ## Direct HTTP Mapping [#direct-http-mapping] When you cannot use the CLI, call the underlying endpoints directly. All paths are relative to `https://portal.eprospera.com` in production or `https://staging-portal.eprospera.com` in staging. | CLI command | Direct endpoint | | ------------------------------------------------- | -------------------------------------------------------------- | | `entity verify ` | `POST /api/v1/verify_rpn` | | `entity search ""` | `POST /api/v1/registries/legal_entities/search` | | `entity get ` | `GET /api/v1/legal_entities/{id}` | | `entity documents ` | `GET /api/v1/legal_entities/{id}/documents` | | `application list` | `GET /api/v1/legal_entity_applications` | | `application create --file application.json` | `POST /api/v1/legal_entity_applications` | | `application get ` / `application watch ` | `GET /api/v1/legal_entity_applications/{id}` | | `application pay --voucher ` | `POST /api/v1/legal_entity_applications/{id}/pay/voucher` | | `application checkout …` | `POST /api/v1/legal_entity_applications/{id}/checkout_session` | | `me profile` | `GET /api/v1/me/natural-person` | | `me residency` | `GET /api/v1/me/natural-person/residency` | | `me id-verification` | `GET /api/v1/me/natural-person/id-verification` | | `me legal-entities list` | `GET /api/v1/me/legal-entities` | | `me legal-entities get ` | `GET /api/v1/me/legal-entities/{id}` | | `me legal-entities documents ` | `GET /api/v1/me/legal-entities/{id}/documents` | | `tax status` | `GET /api/v1/me/tax/summary` | | `tax list` | `GET /api/v1/me/tax/filings` | | `tax get ` | `GET /api/v1/me/tax/filings/{filingId}` | | `tax download …` | `GET /api/v1/me/tax/filings/{filingId}/documents/{document}` | | `referral list ` | `GET /api/v1/referral-codes/{code}/referrals` | | `visitor-pass create …` | `POST /api/v1/visitor_pass_applications` | The legal-entity portfolio and tax endpoint families are OAuth-only. Agent Keys cannot use them. Consent limits entity access to the user's selection, and the corresponding personal or entity tax scope is required for every tax request. ## Decision Tree — Pick the Right Command [#decision-tree--pick-the-right-command] Walk this top-down. Stop at the first row that matches your goal. 1. **You need to store or inspect credentials.** → `eprospera auth login`, `eprospera --json auth whoami`, or `eprospera --yes auth logout`. 2. **You have an RPN string and want to know if it is real and active.** → `eprospera --json entity verify `. 3. **You have a human-readable name or partial RPN and want to find the entity.** → `eprospera --json entity search ""`. If results are empty, broaden the query — do not retry the same input. 4. **You have a legal-entity ID that your own agent created earlier.** → `eprospera --json entity get `. 5. **You have a legal-entity ID from outside this API.** → **Not reachable with an Agent Key.** Use OAuth and `/api/v1/me/legal-entities/{id}`, or ask the owner to form/manage the entity through the API. Do not retry the Agent Key call. 6. **You want data about the human who owns the Agent Key or OAuth credential.** → `eprospera --json me profile`, `me residency`, or `me id-verification` with the matching scope. 7. **You want entities the OAuth user selected during consent.** → `eprospera --json me legal-entities list`, then `get` or `documents` with a returned ID. 8. **You want personal or consented-entity tax data.** → Log in with OAuth, then use `tax status`, `tax list`, `tax get`, or `tax download`. Use `--subject personal` or a consented entity UUID. 9. **You want to incorporate a new LLC.** → See [Recipe 2](/agent-recipes#recipe-2-fully-automated-llc-incorporation). Confirm MoW, pre-accepted AOC, and a fully covering voucher before the agent starts. 10. **You want the resident to pay through hosted checkout.** → Use `application checkout` with a standard key. Agent Keys cannot create checkout sessions. 11. **You want to know when an application is approved.** → `eprospera --json application watch --timeout 30m`. 12. **You need referral attribution or a public visitor pass.** → Use `referral list` with a standard key or `visitor-pass create` without a credential. 13. **You need exact wire-level request and response shapes.** → Use the direct HTTP reference pages. ## Why Your Call Might Return Empty [#why-your-call-might-return-empty] Read this section any time a response is unexpectedly empty, `404`, CLI exit code `5`, `401`, `403`, or CLI exit code `4`. Most of these are **by design**, not bugs. | Symptom | Cause | Fix | | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | `application list` returns `{ "data": [] }` | Agent Keys see **only API-created applications** (`createdViaAPI: true`). Applications started in the portal are invisible. | Restart through the API/CLI, or have the owner finish it in the portal. | | `entity get ` exits `5` or HTTP returns `404` | Either the entity does not exist, or it was created outside the API and is invisible to Agent Keys. | Use OAuth and `/me/legal-entities/{id}` if the owner must share non-API-created entities. | | `/me/legal-entities*` returns `401` | You sent an Agent Key (`ak-...`). This route family is OAuth-only. | Switch to an OAuth access token. | | Tax request returns `invalid_subject` | `subject` was empty or was neither `personal` nor a legal-entity UUID. | Omit `subject` for all authorized subjects, or pass one valid subject. | | Any command exits `4` or HTTP returns `403` | The credential lacks the required scope, consent, or MoW. | Reauthorize OAuth or ask the owner for a key with the required access. | | `application create` returns `nextSteps.signature` | The Agreement of Coexistence was not pre-accepted. | The owner opens the signature URL once in a browser. Future creates of that residency type can be headless. | | Any command exits `7` or HTTP returns `429` | Per-key rate limit. `verify_rpn` and registry search are capped at 50/minute and 5,000/day. | Respect `Retry-After` and back off. | | Search returns `{ "results": [] }` | Query was too narrow or used punctuation the registry does not index. | Reduce to the most distinctive single word. | | `entity verify` returns `"not_found"` | The RPN string is malformed or unknown. | Treat as terminal; do not retry the same RPN. | ## Polling, Not Webhooks [#polling-not-webhooks] There are no webhook callbacks today. Prefer the CLI watcher: ```bash eprospera --json application watch --timeout 30m ``` Direct HTTP callers should poll `GET /api/v1/legal_entity_applications/{id}` every **30 seconds** for the first 2 minutes, then back off to every **5 minutes**. `Approved` and `Rejected` are terminal — stop polling. ## Machine-Readable Resources [#machine-readable-resources] If your agent has fetch capability, ingest these instead of scraping rendered pages: * [Official CLI](https://github.com/Honduras-Prospera-inc/eprospera-cli) — source repository for the e-Próspera CLI. * [CLI package on npm](https://www.npmjs.com/package/@prospera/eprospera-cli) — current published version and installation metadata. * [CLI releases](https://github.com/Honduras-Prospera-inc/eprospera-cli/releases) — changelog and standalone bundles. * [`/llms.txt`](/llms.txt) — short Markdown index of every doc page, per the [llms.txt standard](https://llmstxt.org/). * [`/llms-full.txt`](/llms-full.txt) — CLI commands, endpoints, scopes, request/response shapes, and conventions in one plain-text file. * [`/openapi.yaml`](/openapi.yaml) — OpenAPI 3.1 spec for direct HTTP clients. ## Where To Go Next [#where-to-go-next] * **Use the CLI:** [CLI](/cli) — install, authenticate, command matrix, exit codes. * **Pick credentials:** [Agent Keys](/agent-keys) — what they are, who can issue them, scope reference, limitations. * **Copy a workflow:** [Agent recipes](/agent-recipes) — CLI and HTTP flows for registry lookup, incorporation, profile reads, and OAuth tax data. * **Build direct HTTP clients:** [Conventions](/conventions) and the reference pages. * **Sign in with e-Próspera:** [OAuth overview](/oauth-overview). * **Read consented entities and taxes:** [Tax and legal-entity data](/tax-and-entity-data). --- # Tax and legal-entity data (/tax-and-entity-data) Use OAuth or the official CLI to read your own tax records and data for legal entities you actively represent and explicitly consent to share. The e-Próspera public API provides read-only access to personal tax records and to selected legal entities. It cannot return other users' records or entities the user did not consent to share. ## Available data [#available-data] An authorized user can: * view personal tax obligations, including open and overdue periods; * list submitted income-tax and VAT filings; * inspect a submitted filing and its calculated amounts; * download an assessment or filed-return PDF; * list legal entities selected during OAuth consent; * read a selected entity's profile and available documents; and * perform the same read-only tax operations for a selected entity they still actively represent. These endpoints do not create, edit, submit, or pay a tax filing. Tax summaries are calculated without creating draft statements. ## Access boundaries [#access-boundaries] | Data | Required scope | Additional checks | | ------------------------ | --------------------------------- | --------------------------------------------------------------------------------------------- | | Personal tax records | `eprospera:person.tax.read` | The OAuth user can only request their own records. | | Legal-entity profile | `eprospera:entity.read` | The entity must be selected during consent. | | Legal-entity documents | `eprospera:entity.documents.read` | The entity must be selected during consent. | | Legal-entity tax records | `eprospera:entity.tax.read` | The entity must be selected during consent and the user must remain an active representative. | Selecting an entity during consent does not permanently bypass membership checks. If the user stops representing that entity, subsequent requests stop returning its data. ## Use the official CLI [#use-the-official-cli] Authorize the CLI in a browser: ```bash eprospera auth login --oauth ``` The browser consent page shows the requested permissions and lets the user select which legal entities to share. The CLI client has no embedded secret and requests only the published user and entity scopes. List and inspect the entities available to the CLI: ```bash eprospera --json me legal-entities list eprospera --json me legal-entities get eprospera --json me legal-entities documents ``` Read personal tax information: ```bash eprospera --json tax status --subject personal eprospera --json tax list --subject personal --type income --year 2025 eprospera --json tax get eprospera tax download --document assessment ``` For entity taxes, pass a consented legal-entity UUID: ```bash eprospera --json tax status --subject eprospera --json tax list --subject --type vat --year 2025 eprospera tax download --document return --output filed-return.pdf ``` `tax list` returns an opaque cursor for the next page when more filings are available. Pass that value back with `--cursor`; do not parse or modify it. ## Direct API endpoints [#direct-api-endpoints] | Operation | Endpoint | | ----------------------- | ------------------------------------------------------------------------------------------------------ | | List consented entities | [GET `/api/v1/me/legal-entities`](/reference/oauth-get-legal-entities) | | Read one entity | [GET `/api/v1/me/legal-entities/{id}`](/reference/oauth-get-legal-entities-id) | | Read entity documents | [GET `/api/v1/me/legal-entities/{id}/documents`](/reference/oauth-get-legal-entities-id-documents) | | Read tax status | [GET `/api/v1/me/tax/summary`](/reference/oauth-get-tax-summary) | | List submitted filings | [GET `/api/v1/me/tax/filings`](/reference/oauth-list-tax-filings) | | Read one filing | [GET `/api/v1/me/tax/filings/{filingId}`](/reference/oauth-get-tax-filing) | | Download a tax document | [GET `/api/v1/me/tax/filings/{filingId}/documents/{document}`](/reference/oauth-download-tax-document) | Use `subject=personal` for the authenticated user's records or `subject=` for a consented legal entity. Tax endpoints accept the matching personal or entity tax scope; having one does not grant the other. ## Handling sensitive information [#handling-sensitive-information] Tax amounts, filing history, assessments, returns, and some legal-entity documents are confidential financial information. * Do not place access tokens, refresh tokens, tax responses, or downloaded documents in source control or shared logs. * Treat JSON and human-readable terminal output as sensitive; shell redirection and CI log capture can persist it. * Tax PDFs are created with owner-only file permissions on supported platforms. The CLI refuses to overwrite an existing file unless `--yes` is supplied. * Use `eprospera --yes auth logout` to revoke the remote OAuth session and remove the locally stored credential. The CLI stores credentials in the operating-system keychain when available. Its protected local-file fallback is intended for a single-user workstation, not a shared machine. --- # Testing in staging (/testing-in-staging) Use separate staging accounts and credentials to test e-Próspera API, OAuth, and payment integrations without affecting production. ## Base URLs [#base-urls] | Environment | Base URL | | ----------- | -------------------------------------- | | Production | `https://portal.eprospera.com` | | Staging | `https://staging-portal.eprospera.com` | ## Getting access [#getting-access] Create or sign in to your account in the [staging portal](https://staging-portal.eprospera.com), then open [Settings > Developer](https://staging-portal.eprospera.com/settings) to create a standard API key or an Agent Key. Staging mirrors the production API and OAuth behavior unless noted, but its accounts, data, credentials, and payment setup are separate. Create the key in the environment you want to test. Some write operations require an active residency. You can apply for residency in the staging portal without affecting production. OAuth clients are not self-service. If your integration needs OAuth / OIDC, request a staging client through the [e-Próspera Help Center chat](https://help.eprospera.com/en/chat). ## Making requests [#making-requests] With the CLI, set `EPROSPERA_ENV=staging`: ```bash export EPROSPERA_API_KEY="" EPROSPERA_ENV=staging eprospera --json entity verify 80000000000012 ``` For direct HTTP, use the staging base URL: ```bash curl -X POST https://staging-portal.eprospera.com/api/v1/verify_rpn \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"rpn": "80000000000012"}' ``` See the [quickstart](/getting-started) for more details. ## OAuth in staging [#oauth-in-staging] OAuth uses the same authorization flow as production at the staging base URL, but it requires a separately provisioned staging client. See the [OAuth overview](/oauth-overview) for the full flow. Staging clients may redirect to a partner application running locally over HTTP, provided the complete callback uses a loopback host: ```text http://127.0.0.1:3001/oauth/callback http://[::1]:3001/oauth/callback http://localhost:3001/oauth/callback ``` Prefer the IP-literal forms for new integrations. The authorization request must send the registered value exactly, including the port, path, and trailing slash. This exception is available only in development and staging; production continues to require HTTPS even if an older HTTP value remains stored. ## Testing entity-application payments [#testing-entity-application-payments] Standard API keys can test hosted checkout or [voucher payment](/reference/post-legal-entity-applications-id-pay-voucher). Agent Keys support voucher payment only. For no-cost staging tests, use this reusable voucher to incorporate as many entities as you need: ```text API1234 ``` --- # Docs releases section (/releases/docs-releases-section) 2026-07-27 · News — API changes and product updates now publish under Releases. Product update for integrators. Not an API contract change. The public API docs now include a [Releases](/releases) section for both **API** changelog items and **product news**. ## Why [#why] Partners need a single place to scan what changed — new scopes and endpoints, deprecations, and launches that affect integrations — without digging through guides or OpenAPI diffs alone. ## What to expect [#what-to-expect] * **API** entries call out contract impact and link to the relevant reference or guide pages. * **News** entries cover programs, tooling, and other product updates that change how you integrate. * The [versioning policy](/conventions#versioning) is unchanged: `/api/v1/` stays additive; breaking changes go to a new `/api/vN` prefix. New posts appear in the sidebar under **Releases**, newest first. --- # e-Próspera CLI v0.3.0 (/releases/eprospera-cli-0-3-0) 2026-08-12 · News — OAuth login, consented legal-entity reads, and read-only tax commands are now available in the official CLI. Product update for CLI users and automation authors. The matching API capabilities are documented in [OAuth device authorization and tax reads](/releases/oauth-device-and-tax-api). [`@prospera/eprospera-cli` v0.3.0](https://www.npmjs.com/package/@prospera/eprospera-cli) adds browser-based OAuth device login and commands for user-consented legal-entity and tax data. ## Install or update [#install-or-update] ```bash npm install -g @prospera/eprospera-cli@latest eprospera --version ``` The [GitHub v0.3.0 release](https://github.com/Honduras-Prospera-inc/eprospera-cli/releases/tag/v0.3.0) also includes standalone bundles for Linux, macOS, and Windows. ## What changed [#what-changed] * `eprospera auth login --oauth` uses the official public-client device flow. * Access tokens refresh automatically with rotating refresh tokens. * `eprospera --yes auth logout` attempts remote revocation before removing the local credential. * `me legal-entities list`, `get`, and `documents` read entities selected during consent. * `tax status`, `list`, `get`, and `download` read personal or consented-entity tax records. * Tax downloads use owner-only permissions where supported and refuse accidental overwrites. ## Access and data handling [#access-and-data-handling] Tax commands are read-only. They can access only the signed-in user's records or an entity selected during consent that the user still represents. Tax responses, assessments, returns, and some entity documents are confidential; keep them out of logs, source control, and shared workspaces. See the [CLI guide](/cli) for the complete command matrix and [Tax and legal-entity data](/tax-and-entity-data) for scopes and access boundaries. --- # Releases (/releases) API changes and product news for partners integrating with e-Próspera. This section covers **API changes** and **product news** that matter to integrators — new endpoints and scopes, deprecations, partner programs, and launches that affect how you build on e-Próspera. ## What belongs here [#what-belongs-here] | Kind | Examples | | -------- | ---------------------------------------------------------------------------------------------------------- | | **API** | New endpoints or scopes, additive fields, deprecations, breaking changes destined for `/api/v2/` | | **News** | Partner programs, credential models, CLI releases, and other product updates that change how you integrate | Stable versioning policy still lives in [Conventions](/conventions#versioning): `/api/v1/` stays additive; breaking changes move to a new `/api/vN` prefix. ## How we publish [#how-we-publish] Each release is its own page under `/releases/…`, listed newest-first in the sidebar. Entries use a short title, a date in the description, and a clear **API** or **News** label so you can scan quickly. When you ship something partners need to know about, add an MDX file in `content/releases/`, prepend its slug to `content/releases/meta.json`, and keep this index as the landing page. --- # OAuth device authorization and tax reads (/releases/oauth-device-and-tax-api) 2026-08-12 · API — Additive OAuth endpoints and scopes now support the official CLI, consented entities, and read-only tax data. Additive public API update. Existing authorization-code integrations continue to work without changes. The public OAuth surface now supports the official CLI's device authorization flow and read-only access to personal or consented legal-entity tax records. ## OAuth additions [#oauth-additions] * The [device authorization endpoint](/reference/oauth-device-authorization) issues a user code and verification URL for the registered official CLI. * The token endpoint supports device-code polling by that public client. * The [revocation endpoint](/reference/oauth-revoke) accepts the official public client without an embedded secret. * OpenID discovery publishes the device and revocation capabilities supported by the server. The device flow is currently reserved for the official CLI. Third-party OAuth clients continue to use the authorization-code flow with PKCE. ## New consented data [#new-consented-data] The following OAuth scopes are available: | Scope | Access | | --------------------------------- | --------------------------------------------------- | | `eprospera:entity.read` | Profiles for legal entities selected during consent | | `eprospera:entity.documents.read` | Documents for selected legal entities | | `eprospera:person.tax.read` | The signed-in user's tax status and filings | | `eprospera:entity.tax.read` | Tax data for selected legal entities | New read-only resources include: * [Consented legal entities](/reference/oauth-get-legal-entities) * [Tax obligations](/reference/oauth-get-tax-summary) * [Submitted tax filings](/reference/oauth-list-tax-filings) * [One submitted filing](/reference/oauth-get-tax-filing) * [Tax assessment and return downloads](/reference/oauth-download-tax-document) Entity selection during consent does not override representation checks. If a user stops representing an entity, later requests stop returning its data. These endpoints do not create, modify, submit, or pay tax filings. See [OAuth 2.0 / OpenID Connect](/oauth-overview) for the protocol details and [Tax and legal-entity data](/tax-and-entity-data) for examples and confidential-data handling. --- # Operate as an AI agent for a resident (/use-cases/ai-agents) Act on a resident's behalf with a scoped Agent Key — from read-only lookups to zero-browser LLC incorporation under a Manifestation of Will. You build an AI assistant, an autonomous agent, or an automation service that acts for one specific e-Próspera account holder — reading their records, preparing filings, or incorporating entities they own. **Credential:** an [Agent Key](/agent-keys) (`ak-`), created by the resident in their portal with exactly the scopes you need. This is the delegation model designed for agents: the key acts *as the resident*, every write is attributed and notifies the owner, and write scopes only work under a signed **Manifestation of Will** (MoW). ## Start read-only [#start-read-only] Read scopes need no MoW. A key with `agent:verify_rpn`, `agent:registry.search`, `agent:entity.read`, and `agent:person.*.read` lets you: ```bash export EPROSPERA_API_KEY="ak-..." eprospera --json entity verify 90000000000123 # RPN check eprospera --json entity search "Acme Holdings" # registry search eprospera --json person get # the owner's profile eprospera --json person residency # residency status ``` All four read recipes, with direct-HTTP equivalents, are in [Agent recipes](/agent-recipes). ## Graduate to writes: zero-browser incorporation [#graduate-to-writes-zero-browser-incorporation] With `agent:entity.application.create|pay|read` plus an MoW that **pre-accepted the Agreement of Coexistence**, your agent can incorporate an LLC with no human browser session: ```bash eprospera --json --yes application create --file application.json eprospera --json --yes application pay --voucher "" eprospera --json application get # poll: Approved / Rejected ``` If the AOC wasn't pre-accepted, the create response returns `nextSteps.signature` — pause and hand the owner that URL. Payment for Agent Keys is voucher-only (hosted checkout is disabled for `ak-`). Every write action emails the key owner, and a weekly reminder lists active Manifestations of Will. Build your agent to expect the owner revoking a key or scope at any time — handle `403` by stopping, not retrying. ## Make your agent discoverable-ready [#make-your-agent-discoverable-ready] This documentation is built for machine consumption: fetch [/llms.txt](/llms.txt) for an index, append `.md` to any page URL for raw markdown, and load [/openapi.yaml](/openapi.yaml) for the full typed surface. The [Skills for AI agents](/skills-for-agents) page is a capability map and decision tree written for LLM-based callers. ## What this API does not do [#what-this-api-does-not-do] * No public webhooks — poll application status (5–30s during active flows, then back off). * No hosted checkout for Agent Keys; no acting across multiple owners with one key. * Entity reads only cover API-created entities; use registry search for the rest. ## Next steps [#next-steps] * [Agent Keys](/agent-keys) — scopes, MoW, limitations * [CLI](/cli) — JSON-first commands and exit codes * [Agent recipes](/agent-recipes) — copy-paste workflows --- # Register event visitors with zero credentials (/use-cases/event-visitor-passes) Submit visitor-pass applications from your event site, coworking space, or tourism platform — no API key required. You host a conference in Próspera, run a coworking space, or operate a travel platform, and you want attendees to request their Próspera visitor pass directly from your own registration flow. **Credential:** none. [POST visitor\_pass\_applications](/reference/post-visitor-pass-applications) is the one unauthenticated endpoint in the API — a deliberate zero-friction entry point. ## The flow [#the-flow] Collect the visitor's details in your form, then submit them: ```bash curl -s -X POST https://portal.eprospera.com/api/v1/visitor_pass_applications \ -H "Content-Type: application/json" \ -d '{ "firstName": "Jane", "lastName": "Doe", "email": "jane@example.com", "signature": "", "consentToBackgroundCheck": true, "referralSource": "Acme Conference 2026" }' ``` The applicant receives follow-up steps by email; your platform's job ends at submission. Use `referralSource` to identify your event or venue — it's how arrivals get attributed to you. `consentToBackgroundCheck` must be `true` and the signature must be the applicant's own. Present the consent language to the visitor yourself — don't pre-tick it. ## Pair it with verification [#pair-it-with-verification] If your venue also gates access for existing residents, combine this with [RPN verification](/use-cases/verify-residents) using a standard API key: visitors go through the pass flow, residents get verified in one call. ## What this API does not do [#what-this-api-does-not-do] * No status polling for visitor passes — the applicant is contacted by email; there is no read-back endpoint. * No bulk submission; one application per visitor. ## Next steps [#next-steps] * [POST visitor\_pass\_applications](/reference/post-visitor-pass-applications) — full request schema * [Getting started](/getting-started) — if you outgrow the no-auth surface --- # Incorporate LLCs as a formation platform (/use-cases/incorporation-platform) Create Próspera LLC applications, take payment, poll to approval, and deliver the entity documents — end to end over the API. You run an incorporation service, a startup-in-a-box product, or a law-firm workflow tool, and you want to form Próspera LLCs for your customers programmatically. **Credential:** a standard API key (`sk-`) for the hosted-checkout flow, or an [Agent Key](/agent-keys) (`ak-`) with write scopes for the fully automated voucher flow. The application is always created on behalf of an active Resident or e-Resident. ## The flow [#the-flow] 1. **Create the application** — [POST legal\_entity\_applications](/reference/post-legal-entity-applications) with the entity name, extension, principal office, and `registeredAgentProvider`. The response includes `nextSteps` (signature, payment). 2. **Take payment** — either: * [Hosted checkout session](/reference/post-legal-entity-applications-id-checkout-session) (`sk-` only): redirect your customer to the returned URL; supports card and Bitcoin/Lightning providers. * [Voucher](/reference/post-legal-entity-applications-id-pay-voucher): fully server-side when a voucher covers the invoice — this is the only payment path available to Agent Keys. 3. **Poll to approval** — [GET legal\_entity\_applications/\{id}](/reference/get-legal-entity-applications-id) every 5–30 seconds during an active session, backing off after. Terminal states are `Approved` and `Rejected`. 4. **Deliver the entity** — on approval the application exposes `legalEntityId`; fetch [the entity](/reference/get-legal-entities-id) and [its documents](/reference/get-legal-entities-id-documents) (certificate of incorporation and filings) for your customer. The complete request payloads, signature (AOC) handling, and a copy-paste CLI version live in the [Incorporating an entity](/incorporating-entity) tutorial and [Agent recipes](/agent-recipes) (Recipes 2 & 3). ```bash # Fully automated CLI variant (Agent Key + voucher) eprospera --json --yes application create --file application.json eprospera --json --yes application pay --voucher "" eprospera --json application get # poll until Approved ``` The Agreement of Coexistence must be signed by the entity owner. With an Agent Key whose Manifestation of Will pre-accepted the AOC, incorporation is zero-browser; otherwise the create response includes `nextSteps.signature` and the owner completes it in the portal. ## Track your referrals [#track-your-referrals] If you're a [Catalyst Program](/catalyst-program) member, pass your `referralCode` in the create-application body to attribute each incorporation, then list what you've referred with [GET referral\_codes/\{code}/referrals](/reference/get-referral-codes-code-referrals) (`sk-` only). The endpoint reports attribution only — invoice and discount state are not exposed. ## What this API does not do [#what-this-api-does-not-do] * No public webhooks — poll application status. * Hosted checkout is not available to Agent Keys (voucher or portal payment only). * Application lists via Agent Keys only include API-created records. ## Next steps [#next-steps] * [Incorporating an entity](/incorporating-entity) — the full tutorial * [Agent Keys](/agent-keys) — delegation, MoW, write scopes * [Testing in staging](/testing-in-staging) — rehearse the whole flow safely --- # Onboard residents as a relocation partner (/use-cases/residency-partner) Submit and manage natural-person residency applications for your clients with a Partner Key — drafts, documents, payment, and submission. You run a relocation service, an immigration consultancy, or a digital-nomad platform, and you onboard clients into Próspera residency on their behalf. **Credential:** a Partner Key (`pk-`), issued by the e-Próspera team to approved organizations — [Partner Keys](/partner-keys) covers issuance, 90-day expiry, security responsibilities, and rate limits. This surface is separate from Agent Keys: it is organization-scoped, not person-delegated. ## The flow [#the-flow] 1. **Create a Draft** — [POST partner/residency\_applications](/reference/post-residency-applications) with the applicant's personal details and a unique `Idempotency-Key`. e-Próspera emails the applicant a single-use account-claim link (24-hour expiry). 2. **Complete the data** — [PATCH partner/residency\_applications/\{id}](/reference/patch-residency-applications-id) with `expectedVersion` for optimistic concurrency. 3. **Attach proof of address** — [upload the document](/reference/post-uploads-proof-of-address) to get an opaque `proofOfAddressUploadId`, then attach it via PATCH. (The sworn-statement path skips the upload.) 4. **Pay** — [hosted checkout](/reference/post-residency-applications-id-checkout-session) or [voucher](/reference/post-residency-applications-id-pay-voucher), each with its own `Idempotency-Key`. 5. **Hand off to the applicant** — the applicant claims their account, signs the Agreement of Coexistence at `nextSteps.agreementUrl`, and completes identity verification in their own session. 6. **Submit and poll** — once `nextSteps.submitReady` is `true`, call [POST …/submit](/reference/post-residency-applications-id-submit), then poll [GET …/\{id}](/reference/get-residency-applications-id) until `Approved`/`Rejected`. The full nine-step secure flow — including which fields each scope unlocks and the per-endpoint rate limits — is in [Partner Keys](/partner-keys). Your organization can never sign the Agreement of Coexistence or start/read identity verification (Veriff) for an applicant — those happen only in the applicant's own authenticated e-Próspera session. Your integration prepares everything, then reads `nextSteps` to know when the applicant has done their part. ## What this API does not do [#what-this-api-does-not-do] * No public webhooks — poll application status (lists support cursor pagination). * No Veriff initiation or results via Partner Keys. * Partner Keys expire after 90 days — build rotation into your ops calendar. ## Next steps [#next-steps] * [Partner Keys](/partner-keys) — the complete integration contract * [Uploads reference](/reference/post-uploads-proof-of-address) — private document handling * [Conventions](/conventions) — idempotency, errors, pagination --- # Add "Sign in with e-Próspera" to your app (/use-cases/sign-in-with-eprospera) Authenticate users with OAuth 2.0 / OpenID Connect and, with their consent, read verified residency and entity data. You build a SaaS product, a community platform, or a fintech app, and you want users to sign in with their e-Próspera account — optionally proving they are a verified Próspera resident or entity owner. **Credential:** an OAuth client (client ID + secret), created by the e-Próspera team. The flow is standard authorization-code with PKCE (required), documented end to end in the [OAuth overview](/oauth-overview). ## Two integration tiers [#two-integration-tiers] **Tier 1 — login and identity.** Request `openid profile email`. You get a standards-compliant OIDC login with signed ID tokens — enough for authentication. **Tier 2 — verified residency data.** Additionally request `eprospera:person.details.read`, `eprospera:person.residency.read`, `eprospera:person.id_verification.read`, or the `eprospera:entity.*` scopes. With the user's consent you can then read their residency status, ID-verification state, and consented legal entities — turning "sign in" into "prove you're a resident." ## The flow [#the-flow] 1. **Authorize** — redirect to [GET /api/oauth/authorize](/reference/oauth-authorize) with PKCE (`S256`), `state`, and (for `openid`) a `nonce`. Users see a consent screen; approved consent is remembered for repeat visits. 2. **Exchange the code** — [POST /api/oauth/token](/reference/oauth-token). Access tokens live 1 hour; request `offline_access` for 180-day refresh tokens. 3. **Read the user** — [GET /api/oauth/userinfo](/reference/oauth-userinfo) returns the standard claims plus `eprospera:rpn` for verified residents. 4. **Read consented resources** — [natural person](/reference/oauth-get-natural-person) · [residency](/reference/oauth-get-natural-person-residency) · [ID verification](/reference/oauth-get-id-verification) · [legal entities](/reference/oauth-get-legal-entities) and their [documents](/reference/oauth-get-legal-entities-id-documents). Discovery, keys, and token hygiene: [openid-configuration](/reference/oauth-openid-configuration) · [JWKS](/reference/oauth-jwks) · [revoke](/reference/oauth-revoke) · [introspect](/reference/oauth-introspect). Users choose which of their legal entities to share during consent — `GET /api/oauth/me/legal-entities` can legitimately return an empty list even for an entity owner. Design your UI for partial consent. ## Framework quickstarts [#framework-quickstarts] * [NextAuth.js / Auth.js](/oauth-nextauth) — custom OIDC provider in \~20 lines * [Firebase Authentication](/oauth-firebase) — e-Próspera as an OpenID Connect provider ## What this API does not do [#what-this-api-does-not-do] * No implicit or password grants — authorization-code + PKCE only. * No user data without consent; scopes are enforced per token. * Users can revoke your app anytime from their portal's Connected Apps — handle `invalid_grant` on refresh gracefully. ## Next steps [#next-steps] * [OAuth overview](/oauth-overview) — scopes, consent, PKCE, token lifetimes * [Conventions](/conventions) — error envelope and status codes --- # Verify residents and entities as a compliance vendor (/use-cases/verify-residents) Confirm Resident Permit Numbers and look up registry records in real time for KYC, AML, and background-check workflows. You run a KYC/AML product, a background-check service, or a compliance desk, and you need to confirm that a Próspera resident or legal entity is real and in good standing. **Credential:** a standard API key (`sk-`) is enough for registry-level checks. Person-level reads (residency status, ID verification) additionally require an [Agent Key](/agent-keys) (`ak-`) delegated by the person, or an [OAuth](/oauth-overview) token with their consent. ## 1. Verify an RPN [#1-verify-an-rpn] Given a 14-digit Resident Permit Number (entities start with `8`, natural persons with `9`), confirm it exists and is active: ```bash curl -s -X POST https://portal.eprospera.com/api/v1/verify_rpn \ -H "Authorization: Bearer sk-..." \ -H "Content-Type: application/json" \ -d '{"rpn": "80000000000012"}' ``` ```json { "result": "found_legal_entity", "active": true } ``` `result` is one of `found_legal_entity`, `found_natural_person`, or `not_found`. This endpoint is rate-limited to 5,000/day and 50/minute per key — cache results where your compliance policy allows. See [POST verify\_rpn](/reference/post-verify-rpn). ## 2. Resolve a name to a registry record [#2-resolve-a-name-to-a-registry-record] When you have a company name instead of an RPN, search the public legal-entity registry: ```bash curl -s -X POST https://portal.eprospera.com/api/v1/registries/legal_entities/search \ -H "Authorization: Bearer sk-..." \ -H "Content-Type: application/json" \ -d '{"query": "Acme Holdings"}' ``` Each match includes the entity `id`, `name`, `extension`, and `residentPermitNumber`. See [POST registries/legal\_entities/search](/reference/post-search-entities). ## 3. Pull entity details and documents [#3-pull-entity-details-and-documents] With the entity `id`, fetch the full record and its certificates and filings: * [GET legal\_entities/\{id}](/reference/get-legal-entities-id) * [GET legal\_entities/\{id}/documents](/reference/get-legal-entities-id-documents) With an Agent Key, `GET /legal_entities/{id}` only returns entities created via the API. Registry **search** is the broad lookup across all registered entities — resolve through search first. ## 4. Person-level KYC (requires delegation) [#4-person-level-kyc-requires-delegation] To read a natural person's residency status or ID-verification state, the person must delegate access — there is no vendor-wide lookup of personal data. Two options: * **Agent Key** issued by the person with `agent:person.details.read`, `agent:person.residency.read`, `agent:person.id_verification.read` — see [Agent recipes → account-holder profile](/agent-recipes). * **OAuth** consent flow with the `eprospera:person.*` scopes — see [Sign in with e-Próspera](/use-cases/sign-in-with-eprospera). Endpoints: [natural person](/reference/oauth-get-natural-person) · [residency](/reference/oauth-get-natural-person-residency) · [ID verification](/reference/oauth-get-id-verification). ## What this API does not do [#what-this-api-does-not-do] * No public webhooks — re-verify on your own schedule instead of waiting for pushes. * No bulk export of the registry; query per entity. * No personal-data lookup without the person's delegation or consent. ## Next steps [#next-steps] * [Getting started](/getting-started) — create your API key * [Conventions](/conventions) — error envelope, status codes, rate limits * [Testing in staging](/testing-in-staging) --- # Verify whether an RPN exists and is active (/reference/post-verify-rpn) Look up a Resident Permit Number and report whether it belongs to a legal entity, a natural person, or is unknown — and whether the resident currently has an active residency. Rate-limited to 5,000 requests per 24 hours and 50 per minute, per API key. Exceeding either bound returns `429`. Accepts standard API keys (`sk-`) and Agent Keys (`ak-`) holding the `agent:verify_rpn` scope. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Look up a Resident Permit Number and report whether it belongs to a legal entity, a natural person, or is unknown — and whether the resident currently has an active residency. Rate-limited to 5,000 requests per 24 hours and 50 per minute, per API key. Exceeding either bound returns `429`. Accepts standard API keys (`sk-`) and Agent Keys (`ak-`) holding the `agent:verify_rpn` scope. --- # Search the legal-entity registry (/reference/post-search-entities) Performs a case-insensitive name search and partial RPN match. Accepts standard and appropriately scoped Agent Keys. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Performs a case-insensitive name search and partial RPN match. Accepts standard and appropriately scoped Agent Keys. --- # Get a legal entity (/reference/get-legal-entities-id) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # List documents for a legal entity (/reference/get-legal-entities-id-documents) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # List legal-entity applications (/reference/get-legal-entity-applications) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Create a legal-entity application (/reference/post-legal-entity-applications) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get a legal-entity application (/reference/get-legal-entity-applications-id) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Pay a legal-entity application with a voucher (/reference/post-legal-entity-applications-id-pay-voucher) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Create a hosted checkout session (/reference/post-legal-entity-applications-id-checkout-session) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # List partner residency applications (/reference/get-residency-applications) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Create a partner residency application (/reference/post-residency-applications) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get a partner residency application (/reference/get-residency-applications-id) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Update a draft partner residency application (/reference/patch-residency-applications-id) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Upload proof of address (/reference/post-uploads-proof-of-address) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Download proof of address (/reference/get-uploads-proof-of-address-id) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Create a partner hosted-checkout session (/reference/post-residency-applications-id-checkout-session) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Pay a partner application with a voucher (/reference/post-residency-applications-id-pay-voucher) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Submit a partner residency application (/reference/post-residency-applications-id-submit) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get the authenticated natural person (/reference/oauth-get-natural-person) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get ID-verification artifacts (/reference/oauth-get-id-verification) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get natural-person residency status (/reference/oauth-get-natural-person-residency) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # List consented legal entities (/reference/oauth-get-legal-entities) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get a consented legal entity (/reference/oauth-get-legal-entities-id) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # List documents for a consented legal entity (/reference/oauth-get-legal-entities-id-documents) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get tax obligations and lump-sum election status (/reference/oauth-get-tax-summary) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # List submitted tax filings (/reference/oauth-list-tax-filings) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get a submitted tax filing (/reference/oauth-get-tax-filing) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Download a tax assessment or filed income return (/reference/oauth-download-tax-document) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # List referrals for a referral code (/reference/get-referral-codes-code-referrals) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Create a public Visitor Pass application (/reference/post-visitor-pass-applications) This endpoint is intentionally unauthenticated. The applicant must provide consent and a signature. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml This endpoint is intentionally unauthenticated. The applicant must provide consent and a signature. --- # Get OpenID Provider metadata (/reference/oauth-openid-configuration) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get OAuth signing keys (/reference/oauth-jwks) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Start the OAuth authorization-code flow (/reference/oauth-authorize) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Start an OAuth device authorization (/reference/oauth-device-authorization) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Exchange an authorization code, device code, or refresh token (/reference/oauth-token) Use HTTP Basic client authentication when possible. client_secret_post remains supported for compatibility. Public device clients send client_id without a secret. Repeated parameters and multiple client authentication methods are rejected. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Use HTTP Basic client authentication when possible. client_secret_post remains supported for compatibility. Public device clients send client_id without a secret. Repeated parameters and multiple client authentication methods are rejected. --- # Get OpenID Connect user claims (/reference/oauth-userinfo) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Get OpenID Connect user claims (/reference/oauth-userinfo-post) POST variant of the OpenID Connect UserInfo endpoint. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml POST variant of the OpenID Connect UserInfo endpoint. --- # Revoke an OAuth token (/reference/oauth-revoke) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Introspect an OAuth token (/reference/oauth-introspect) Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml --- # Deprecated legal-entity coupon-payment alias (/reference/post-legal-entity-applications-id-pay-coupon) Use `/api/v1/legal_entity_applications/{id}/pay/voucher` with `voucherCode` instead. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Use `/api/v1/legal_entity_applications/{id}/pay/voucher` with `voucherCode` instead. --- # Deprecated partner coupon-payment alias (/reference/post-residency-applications-id-pay-coupon) Use `/api/v1/partner/residency_applications/{id}/pay/voucher` with `voucherCode` instead. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Use `/api/v1/partner/residency_applications/{id}/pay/voucher` with `voucherCode` instead. --- # Deprecated ID-verification underscore alias (/reference/oauth-get-id-verification-legacy) Use `/api/v1/me/natural-person/id-verification` instead. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Use `/api/v1/me/natural-person/id-verification` instead. --- # Deprecated OpenID-configuration alias (/reference/oauth-openid-configuration-legacy) Use `/.well-known/openid-configuration` instead. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Use `/.well-known/openid-configuration` instead. --- # Deprecated root JWKS alias (/reference/oauth-jwks-legacy) Use `/api/oauth/.well-known/jwks.json` instead. Full request/response schemas for this operation: https://docs.eprospera.com/openapi.yaml Use `/api/oauth/.well-known/jwks.json` instead.