# Amendments and certificates (/entity-filings)

Prepare entity amendments, complete representative signing and payment, track review, and retrieve certificates and applicant documents.



Use this guide to take an existing entity from a proposed change through signing,
payment, review, and document retrieval. For personal or applicant agreements, use
the separate [Personal and applicant documents guide](/personal-and-applicant-documents).

## Choose a workflow [#choose-a-workflow]

| You want to…                                                      | Start here                                                                                      | Completion signal                                                       |
| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| Change a legal name, legal extension, or principal-office address | [Amend an entity](#amend-an-entity)                                                             | Filing `Approved`, then the resulting document is available             |
| Obtain a Certificate of Good Standing                             | [Request a certificate](#request-a-certificate-of-good-standing)                                | Request `Issued` with a non-null `documentUrl`                          |
| Retrieve a person's signed residency agreement                    | [Personal documents](/personal-and-applicant-documents#read-a-persons-own-documents)            | The active residency has a non-null `signedDocumentUrl`                 |
| Retrieve agreements for an applicant your integration onboarded   | [Applicant documents](/personal-and-applicant-documents#read-your-partners-applicant-documents) | Accepted agreement metadata and, separately, generated signed documents |

## Credentials and boundaries [#credentials-and-boundaries]

| Workflow                            | Credential and scopes                                                                | Ownership rule                                                                  |
| ----------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
| Read filings                        | `sk-`, or `ak-` with `agent:entity.filing.read`                                      | Active representation; Agent Keys are also limited to API-incorporated entities |
| Prepare amendments and certificates | `sk-`, or `ak-` with `agent:entity.filing.create`                                    | Same entity rule; Agent Key writes require an active Manifestation of Will      |
| Pay and submit filings              | `sk-`, or `ak-` with `agent:entity.filing.pay`                                       | Same entity rule; the linked invoice must belong to the filing                  |
| Personal documents                  | OAuth `eprospera:person.documents.read`, or `ak-` with `agent:person.documents.read` | The authenticated person's documents                                            |
| Partner applicant documents         | `pk-` with `partner:person.application.read`                                         | Applications belonging to that partner integration                              |

OAuth entity consent currently supports [entity and document reads](/tax-and-entity-data).
It does not authorize these filing writes. Partner Keys are for natural-person onboarding;
they do not authorize entity filings. Removing representation or revoking a credential
removes access on subsequent requests. A valid credential and its scopes alone are insufficient.

Amendments cover legal names, extensions, and principal office addresses. Corporate
board/officer appointments, share issuances, and option-pool changes are separate workflows.
Staff review and approval remain internal. Use REST for this guide; it does not assume
new filing commands exist in the released CLI.

### Set up access before building the workflow [#set-up-access-before-building-the-workflow]

For your own organization, create a [standard key](/standard-keys) in the key owner's
**Developer → API keys**. The owner must actively represent the entity. Do not ask clients
to share their personal standard keys with your service.

For delegated service access, the represented account owner creates an [Agent Key](/agent-keys)
under **Developer → Agents** and grants these scopes for the complete filing workflow:

```text
agent:entity.filing.read
agent:entity.filing.create
agent:entity.filing.pay
agent:entity.documents.read
```

Also request `agent:registry.search` if your integration needs to find entity IDs, and
`agent:entity.read` if it displays current entity details. Read permission does not imply
write or payment permission. The owner must sign an active Manifestation of Will for Agent
Key writes; this delegation does not replace the amendment's own representative signature.

Agent Keys cannot amend portal-incorporated entities in this release, even when the owner
represents them. Finding an entity in the public registry or selecting it during OAuth
consent does not remove that restriction. OAuth filing writes and a general delegated-write
flow for those existing entities are not provided by these endpoints.

### Endpoint map [#endpoint-map]

All paths below follow `/api/v1/legal_entities/{id}`. `{id}` is the legal-entity UUID,
not its RPN, original application ID, invoice ID, or filing ID.

| Method | Suffix                                          | Purpose                                                | Agent scope                   |
| ------ | ----------------------------------------------- | ------------------------------------------------------ | ----------------------------- |
| GET    | `/amendments`                                   | List filings, newest first                             | `agent:entity.filing.read`    |
| POST   | `/amendments`                                   | Create/reuse a draft and replace its proposals         | `agent:entity.filing.create`  |
| GET    | `/amendments/{filingId}`                        | Read state and next steps                              | `agent:entity.filing.read`    |
| PATCH  | `/amendments/{filingId}`                        | Revise a Draft                                         | `agent:entity.filing.create`  |
| POST   | `/amendments/{filingId}/pay/voucher`            | Prepare invoice, pay, and submit                       | `agent:entity.filing.pay`     |
| POST   | `/amendments/{filingId}/submit`                 | Submit a signed, paid filing; recover pending dispatch | `agent:entity.filing.pay`     |
| GET    | `/certificate_requests`                         | List requests and current eligibility                  | `agent:entity.filing.read`    |
| POST   | `/certificate_requests`                         | Create/reuse a request and its invoice                 | `agent:entity.filing.create`  |
| GET    | `/certificate_requests/{requestId}`             | Read review/issuance progress                          | `agent:entity.filing.read`    |
| POST   | `/certificate_requests/{requestId}/pay/voucher` | Pay; issuance proceeds asynchronously                  | `agent:entity.filing.pay`     |
| GET    | `/documents`                                    | Retrieve generated entity documents                    | `agent:entity.documents.read` |

The OpenAPI [amendment reference](/reference/post-legal-entities-id-amendments) and
[certificate reference](/reference/post-legal-entities-id-certificate-requests) contain the
field-level contracts. These filing routes have no cancellation, deletion, signature-upload,
standalone invoice-preparation, or public approval endpoint.

## Prepare a staging client [#prepare-a-staging-client]

All names and IDs below are fictional. Substitute your own authorized staging entity,
credential, and returned filing IDs. For production, change `BASE_URL` and use production
credentials. Accounts and keys are separate between environments.

```bash
export BASE_URL='https://stg.portal.eprospera.com'
export API_KEY='<your-staging-standard-or-agent-key>'
export ENTITY_ID='11111111-1111-4111-8111-111111111111'
```

See [Testing in staging](/testing-in-staging) for the legacy hostname transition and
test vouchers. Never put a key in browser code. These examples use backend cURL calls.

You can obtain the entity UUID from a previously approved incorporation, or search the
registry using a name or the entity's 14-digit RPN:

```bash
curl -sS -X POST "$BASE_URL/api/v1/registries/legal_entities/search" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"query":"Example Harbor"}'
```

Read the matching entry's `id` in `results`, verify its RPN, and replace `ENTITY_ID` above.
A search match does not grant access. Use `GET /api/v1/legal_entities/{id}` to confirm
visibility if you have the entity-read scope. There is no general entity-list route at
`GET /api/v1/legal_entities`.

The examples use fictional IDs to show the request structure. Always save and reuse the
IDs returned by your own requests. Check the HTTP status before consuming a response; a
JSON body alone does not mean success. Add `--fail-with-body` to cURL when you need a nonzero
exit code on HTTP errors, while retaining the error body for the [recovery steps](#recover-from-failures).

## Amend an entity [#amend-an-entity]

The lifecycle is `Draft` → `Pending Payment` → `Pending Review` → `Approved` or `Rejected`.
The filing can be signed while still `Draft`; preparing its invoice moves it to
`Pending Payment`. After that, its proposed changes are read-only.

| State             | What your client should do                                                                       |
| ----------------- | ------------------------------------------------------------------------------------------------ |
| `Draft`           | Save proposed changes, then open the returned signing URL. A Draft can already be signed.        |
| `Pending Payment` | Proposals are locked. Complete payment; call `/submit` when `nextSteps.submitReady` is true.     |
| `Pending Review`  | Stop editing/paying. Poll; retry `/submit` only if `reviewDispatchPending` is true.              |
| `Approved`        | Review is complete. Fetch the entity and wait for generated documents.                           |
| `Rejected`        | Show `rejectedReason`. Retrying submit returns the same decision; it does not reopen the filing. |

### 1. Create or revise a draft [#1-create-or-revise-a-draft]

```bash
curl -sS -X POST "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/amendments" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"updatedName":"Example Harbor","updatedExtension":"LLC"}'
```

The response is `200`. This is a complete illustrative create response; see also the
[field reference](/reference/post-legal-entities-id-amendments).

```json
{
  "data": {
    "id": "22222222-2222-4222-8222-222222222222",
    "legalEntityId": "11111111-1111-4111-8111-111111111111",
    "statusId": "Draft",
    "proposedChanges": {
      "name": "Example Harbor",
      "extension": "LLC",
      "nameStartsWithExtension": null,
      "principalOfficeAddress": null
    },
    "signed": false,
    "signedAt": null,
    "invoice": null,
    "submittedAt": null,
    "approvedAt": null,
    "rejectedAt": null,
    "rejectedReason": null,
    "createdAt": "2026-09-17T14:00:00.000Z",
    "updatedAt": "2026-09-17T14:00:00.000Z",
    "nextSteps": {
      "changesRequired": false,
      "signatureUrl": "https://stg.portal.eprospera.com/en/business/11111111-1111-4111-8111-111111111111/amendment/22222222-2222-4222-8222-222222222222",
      "paymentRequired": true,
      "submitReady": false,
      "reviewDispatchPending": false
    }
  },
  "nextSteps": {
    "changesRequired": false,
    "signatureUrl": "https://stg.portal.eprospera.com/en/business/11111111-1111-4111-8111-111111111111/amendment/22222222-2222-4222-8222-222222222222",
    "paymentRequired": true,
    "submitReady": false,
    "reviewDispatchPending": false
  }
}
```

There is one open draft per entity. POST reuses an existing Draft and replaces its
proposed changes; omitted fields are cleared. A pending-review filing or an existing
invoiced filing causes `409`; complete that filing first.

### Input rules and PATCH behavior [#input-rules-and-patch-behavior]

| Input                            | Accepted value                                                                            | Response field under `data.proposedChanges` |
| -------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------- |
| `updatedName`                    | Trimmed string, 1–200 characters, or null                                                 | `name`                                      |
| `updatedExtension`               | Trimmed string, 1–50 characters, or null; keep it appropriate to the existing entity type | `extension`                                 |
| `updatedNameStartsWithExtension` | Boolean or null; `false` is a valid proposal                                              | `nameStartsWithExtension`                   |
| `updatedAddress`                 | Complete principal-office address object or null                                          | `principalOfficeAddress`                    |

An address requires `line1` (1–200 characters), `city` (1–100), `postalCode` (1–20), and
`country` (1–100). `line2` (up to 200) and `state` (up to 100) are optional and nullable.
Strings are trimmed. The address country is a text field here, for example `Honduras`;
do not infer a two-letter country requirement from other API workflows.

POST needs at least one non-null proposal. PATCH needs at least one supplied field and
can clear the last proposal. Top-level unknown properties and empty string names are
rejected. `updatedAddress` replaces the whole proposed address; a city-only nested patch
is not supported. Explicit null removes a **proposed change**, not the entity's current
registered value. Null response proposals mean that field will remain unchanged.

For example, after POST proposes both a new name and extension, PATCH with only
`updatedName` keeps the extension proposal. A second POST with only `updatedName` clears
the extension proposal. Prefer PATCH after receiving a filing ID. There is no version or
ETag precondition: coordinate concurrent edits in your own application.

PATCH preserves omitted fields, and explicit `null` clears a proposed change:

```bash
export FILING_ID='22222222-2222-4222-8222-222222222222'
curl -sS -X PATCH "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/amendments/$FILING_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"updatedExtension":null,"updatedAddress":{"line1":"45 Example Street","city":"Roatan","postalCode":"34101","country":"Honduras"}}'
```

Every draft revision invalidates its earlier signature. Fetch the updated filing and
use its new signing step before paying. A draft with all changes cleared cannot be invoiced.

POST/PATCH return `{ "data": { ... }, "nextSteps": { ... } }`; the top-level `nextSteps`
duplicates `data.nextSteps`. GET detail returns only `{ "data": { ... } }`. List returns
`{ "data": [ ... ] }`. Read `data.nextSteps` in a shared detail-response handler.

Other useful fields are `legalEntityId`, `proposedChanges`, `signed`, `signedAt`,
`invoice` (`null` or `{ "id", "statusId" }`), `submittedAt`, `approvedAt`, `rejectedAt`,
`rejectedReason`, `createdAt`, and `updatedAt`. Dates are UTC strings or null.
The proposal fields are not a copy of the current entity record.

### 2. Complete hosted representative signing [#2-complete-hosted-representative-signing]

Send the active representative to the returned `nextSteps.signatureUrl`. They sign in,
review the exact proposed changes, and sign. Neither uploaded signatures nor a reused
Manifestation of Will satisfy this step. The API never returns signature images.

```bash
curl -sS "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/amendments/$FILING_ID" \
  -H "Authorization: Bearer $API_KEY"
```

Wait for `data.signed: true`. The signature URL becomes null. Review remains a
separate step after payment.

Use the returned URL rather than constructing one. It is a portal navigation link, not
an API callback or a substitute for login. Your frontend should offer an **Open signing
page** action and a way to resume the flow. Poll GET after the representative returns;
there is no signing-completion webhook in this release. A null signing URL can also mean
the filing is no longer open, so check `statusId` and `signed` together.

### 3. Pay and submit [#3-pay-and-submit]

A full-coverage voucher prepares the invoice, applies payment, and submits:

```bash
curl -sS -X POST "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/amendments/$FILING_ID/pay/voucher" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"voucherCode":"API1234"}'
```

`API1234` is a staging voucher. On success, the response includes
`success: true`, `data.invoice.statusId: "paid"`, and
`data.statusId: "Pending Review"`. Payment and event delivery are separate operations;
see the recovery table below if the response fails after settlement.

The pay route can create and link the invoice **before** rejecting an invalid, expired,
inapplicable, or insufficient voucher. A failed payment can therefore leave the filing in
`Pending Payment`, with locked proposals and an unpaid invoice. Read the existing filing
and correct the payment; do not create another draft to work around it.

The voucher must cover the full invoice. Partial-voucher-plus-card payment is not a
workflow provided here. These filing responses expose invoice ID and status, not amount,
currency, line items, or a checkout URL. Review pricing/payment in the portal; do not
hard-code a fee or assume the API has quoted one. General billing APIs are separate work.

If the representative pays through the portal, fetch the filing and make its first
submission only when `data.nextSteps.submitReady` is `true`. This means the filing is
signed, paid, and unsubmitted in `Pending Payment`; a paid invoice alone is insufficient.
Then submit it explicitly:

```bash
curl -sS -X POST "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/amendments/$FILING_ID/submit" \
  -H "Authorization: Bearer $API_KEY"
```

Submitting again preserves the first submission time and returns the current state.
A pending review-dispatch event is retried. Repeating voucher payment after a submitted,
paid filing returns its state without another redemption.

Pay and submit success responses use `{ "success": true, "data": { ... } }`. A replay
can return an already `Approved` or `Rejected` filing; always read the returned status.
`nextSteps.paymentRequired: false` means no payment step is offered in the current state;
use `invoice.statusId === "paid"` to establish recorded settlement.

### 4. Poll review and retrieve documents [#4-poll-review-and-retrieve-documents]

Continue GET requests to the filing URL with a delay between polls. `Approved` means
the registry changes were applied; document generation is asynchronous. `Rejected`
includes `rejectedReason`. No approval deadline is guaranteed by the API.

```bash
curl -sS "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/documents" \
  -H "Authorization: Bearer $API_KEY"
```

Use `agent:entity.documents.read` for an Agent Key. Wait for the Certificate of Amendment
to appear; an LLC name amendment also regenerates its Certificate of Organization.
Responses include document IDs, slugs, versions, and `fileUrl`. Do not treat a successful
payment or submission as evidence that the document exists.

There is no public amendment-to-document ID field. Take a snapshot of existing document
IDs/versions before submission and refresh the list after approval. Do not assume the first
document is this filing's result or that `Approved` contains a PDF URL. If you cannot
identify the expected document, report the filing ID rather than submitting another filing.

## Request a Certificate of Good Standing [#request-a-certificate-of-good-standing]

LLCs and for-profit corporations need active residency and no dissolution on record.
Start by reading current eligibility:

```bash
curl -sS "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/certificate_requests" \
  -H "Authorization: Bearer $API_KEY"
```

The GET response includes both history and a current eligibility check, for example:

```json
{
  "data": [],
  "eligibility": {
    "eligible": true,
    "reason": null,
    "taxCompliant": true
  }
}
```

`eligible: true` covers entity type/residency/dissolution checks; it does **not** mean tax
compliance is clear. `taxCompliant: false` requires resolving the overdue obligations or
submitting a supported contest. Null means the tax result is unavailable or not evaluated;
do not treat it as true. `eligible: false` includes `reason: "not_eligible_entity_type"`
or `"not_in_good_standing"`. An inaccessible entity returns HTTP 404 instead of eligibility.

When eligible with no tax contest required, create the request:

```bash
curl -sS -X POST "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/certificate_requests" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' -d '{}'
```

The POST response contains `data.id`, `data.statusId: "Pending Payment"`, and an open
`data.invoice`. POST returns an existing open or issued request instead of charging
again. Reusing an issued request does not make a new assertion about current eligibility.
There is no force-reissue option on this endpoint.

Certificate creation accepts `{}` (or an empty body); it returns HTTP 200 for both creation
and reuse. Save `data.id` as `REQUEST_ID` and `data.invoice.id` separately. There is no
separate certificate `/submit` call and no additional certificate-signature API step.

If creation returns `certificate.tax_overdue`, provide a contest note and an allowed
proof-of-payment upload URL. The URL must come from an approved portal upload; arbitrary
external URLs are rejected. This release does not add a public certificate-proof upload API.

```bash
curl -sS -X POST "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/certificate_requests" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"contest":{"note":"Please review the attached payment confirmation.","proofUrl":"<URL returned by the portal upload>"}}'
```

An already-contested unpaid request can be retried without resupplying its evidence.
Use the returned request ID to pay:

```bash
export REQUEST_ID='33333333-3333-4333-8333-333333333333'
curl -sS -X POST "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/certificate_requests/$REQUEST_ID/pay/voucher" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' -d '{"voucherCode":"API1234"}'
curl -sS "$BASE_URL/api/v1/legal_entities/$ENTITY_ID/certificate_requests/$REQUEST_ID" \
  -H "Authorization: Bearer $API_KEY"
```

Tax-current requests proceed through `Approved` to `Issued`; contested requests enter
`Pending Review` for a registrar. Completion means `statusId: "Issued"` and a non-null
`documentUrl`. Rejected requests include `rejectionReason`. The certificate also appears
in the entity's document list.

Stop polling when the request reaches &#x2A;*`Issued`, `Rejected`, or `Cancelled`**. Only
`Issued` delivers a certificate at `documentUrl`. For `Rejected`, show `rejectionReason`;
for `Cancelled`, show the cancellation state. Neither state should trigger automatic
repayment or a replacement request. Contact support if the request needs intervention.

After successful payment, `invoice.statusId` may already be `paid` while the request still
says `Pending Payment`. This is an intermediate asynchronous state, not an instruction to
pay again. Poll the same request. A contested request goes to review; a change in tax
compliance or an unavailable compliance result can also route a request to review.

An issued GET response looks like this (URLs and IDs are fictional):

```json
{
  "data": {
    "id": "33333333-3333-4333-8333-333333333333",
    "legalEntityId": "11111111-1111-4111-8111-111111111111",
    "type": "certificate_of_good_standing",
    "statusId": "Issued",
    "contested": false,
    "taxContestNote": null,
    "taxPaymentProofUrl": null,
    "contestedAt": null,
    "rejectionReason": null,
    "reviewedAt": "2026-09-17T14:02:00.000Z",
    "issuedAt": "2026-09-17T14:03:00.000Z",
    "documentId": "55555555-5555-4555-8555-555555555555",
    "documentUrl": "https://documents.example.test/good-standing.pdf",
    "invoice": {
      "id": "66666666-6666-4666-8666-666666666666",
      "statusId": "paid"
    },
    "createdAt": "2026-09-17T14:00:00.000Z",
    "updatedAt": "2026-09-17T14:03:00.000Z",
    "nextSteps": {
      "paymentRequired": false,
      "awaitingReview": false,
      "issued": true
    }
  }
}
```

The create response adds a top-level copy of `nextSteps`; the payment response adds
`success` and `message`. List responses include all requests, including historical
rejections, while POST reuses the latest open or fulfilled request. A rejection is not
reopened by retrying payment. There is no public cancel/refund or forced-reissue operation;
contact support if the existing request needs intervention.

### Certificate errors you can handle directly [#certificate-errors-you-can-handle-directly]

These are certificate **creation** responses; payment has its own voucher errors below.
Use the HTTP status and `code` together.

| HTTP | `code`                          | Next action                                                                                    |
| ---- | ------------------------------- | ---------------------------------------------------------------------------------------------- |
| 404  | `entity_not_found`              | Confirm the entity UUID, representation, and Agent Key visibility.                             |
| 400  | `not_eligible_entity_type`      | Certificates here support LLCs and for-profit corporations only.                               |
| 400  | `not_in_good_standing`          | Resolve the entity's residency/dissolution state through the portal.                           |
| 409  | `certificate.tax_overdue`       | Resolve tax obligations or provide a contest note and payment proof.                           |
| 409  | `certificate.contest_required`  | POST a contest for the existing unpaid request.                                                |
| 409  | `certificate.invalid_proof_url` | Use the actual URL from an approved portal upload; a generic file-sharing URL is not accepted. |

A contest note must contain 1–2,000 characters after trimming, and `proofUrl` must be a
valid URL no longer than 2,048 characters. Once a contest is recorded, retrying does not
replace its note/proof. Use the portal/support for an evidence correction. Do not attach
arbitrary proof when no tax obligation is disputed.

## Recover from failures [#recover-from-failures]

Not every failure includes `code`. Some return just `{ "error": "..." }`; validation
may also return `details`, and a state conflict can include `data` or `nextSteps`.
Handle the status first, use `code` when present, and retain the message for the user.

| Response or state                                                                   | Next action                                                                                                                                                                |
| ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` validation, malformed JSON, or voucher error                                  | Correct the request. Vouchers must cover the full invoice; `couponCode` remains a deprecated alias of `voucherCode`.                                                       |
| `401` credential expired or revoked                                                 | Obtain a valid credential in the same environment.                                                                                                                         |
| `403` missing scope or inactive delegation                                          | Have the owner grant the required permission and active delegation.                                                                                                        |
| `404` resource unavailable                                                          | Check entity/filing IDs, current representation, and Agent Key API-created-entity restrictions.                                                                            |
| `409` non-editable, review in progress, missing signature, or contested eligibility | GET the existing resource and follow its current state. Do not create a second filing to bypass it.                                                                        |
| `402` on amendment submit                                                           | The invoice is not paid; finish payment and retry submit.                                                                                                                  |
| `503` with `code: "submission_not_queued"`                                          | Submission was saved. Retry the same `/submit`, or poll. `nextSteps.reviewDispatchPending` identifies pending event delivery; background recovery runs every five minutes. |
| Payment request times out or returns `500`                                          | GET the filing and inspect its invoice before retrying the same resource. If paid, retry submit or poll issuance.                                                          |
| `Approved`, document missing                                                        | Continue polling documents; approval and PDF generation are separate. Report a persistently stuck resource through support.                                                |

These filing endpoints use resource-level duplicate protection and settlement checks.
They do not implement an `Idempotency-Key` response cache. Store returned IDs and use
PATCH for draft revisions. The [Partner API](/partner-keys) has a separate durable
idempotency contract; do not assume it applies to these endpoints.

Filing and certificate list endpoints return complete arrays, newest first; they have
no pagination parameters. Use bounded polling and observe [rate limits](/conventions).

### Voucher failures versus submission failures [#voucher-failures-versus-submission-failures]

Both filing voucher endpoints return 400 with one of these `error` messages for expected
voucher failures. They do not guarantee a machine-readable voucher `code` in the body:

| `error`                                               | Action                                                                                            |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `Voucher code is invalid`                             | Check the code and environment.                                                                   |
| `Voucher code has expired`                            | Obtain a valid replacement voucher.                                                               |
| `Voucher code has already been redeemed`              | GET this resource to check whether an earlier attempt paid it; otherwise obtain a usable voucher. |
| `Voucher code does not apply to this invoice`         | Use a voucher covering the requested product.                                                     |
| `Voucher code does not cover the full invoice amount` | Use full coverage or complete payment through the portal.                                         |

For amendments, a failure **after** successful payment can instead return 409 or 503 and
include `invoiceId`, `filingId`, and `code`. For example:

```json
{
  "error": "Voucher payment was applied. Fetch the filing and retry submission; do not create a replacement filing.",
  "code": "submission_not_queued",
  "invoiceId": "66666666-6666-4666-8666-666666666666",
  "filingId": "22222222-2222-4222-8222-222222222222"
}
```

On this 503, GET the same filing. Its recorded submission remains pending review and the
invoice remains paid. Retry `/submit`, not a new POST `/amendments`. A 503 from `/submit`
itself can contain only `error` and `code`; retain your existing IDs. If it is already
`Approved` or `Rejected`, show that state instead of continuing submission retries.

For an unrecognized 500 or network timeout, the outcome is unknown. Read state first. If
you cannot read it yet, wait and retry the read; do not switch to a new resource or invoice.

### Polling and support [#polling-and-support]

As a client recommendation, poll every 5–30 seconds while the user is actively completing
signing/payment, with jitter. Back off for background review and document generation;
there is no guaranteed processing time. Honor `Retry-After` when supplied, and use
exponential backoff when it is absent. Stop polling terminal rejected or cancelled states. For approval,
stop only after your required document is available. There are no outbound filing webhooks.

If a paid filing remains stuck, contact the [Help Center](https://help.eprospera.com/en/chat)
with the environment, HTTP method/path/status, UTC timestamps, entity ID, filing/request
ID, invoice ID, and a redacted response. Never include raw API keys, vouchers, signatures,
personal documents, or document download URLs in a support transcript.

## Frequently asked integration questions [#frequently-asked-integration-questions]

| Question                                                           | Answer                                                                                                                                      |
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Is a principal-office amendment a registered-agent/address update? | No. This route changes `principalOfficeAddress`; registered-agent changes are a separate workflow.                                          |
| Can I change directors, officers, shares, or an option pool here?  | No. Those operations and their governance documents are not supplied by these filing routes.                                                |
| Does changing the extension convert an entity type?                | No. The amendment does not change `optionId`; conversion is a separate lifecycle operation.                                                 |
| Does draft creation reserve the proposed name?                     | No name reservation or availability guarantee is provided by this endpoint.                                                                 |
| Can I edit a signed Draft?                                         | Yes, while `statusId` is still `Draft`; the revision removes the signature and requires signing again. Once invoiced, proposals are locked. |
| How do I fix an invoiced or submitted amendment?                   | It cannot be patched through this API. Use the portal/support for the existing filing.                                                      |
| Does retrying an issued certificate buy a fresh certificate?       | No. POST returns the existing fulfilled request, including its original issue date.                                                         |
| Does paying renew the business or residency?                       | No. These invoices cover the filing/certificate. Renewal and annual company reports are separate workflows.                                 |
| Are tax submission and email suppression included?                 | No. VAT/annual income-tax writes and partner notification controls are not provided by this release.                                        |

## Integration acceptance checklist [#integration-acceptance-checklist]

Before enabling production writes, exercise this sequence with authorized staging records:

1. Confirm access with the intended key type; verify missing scopes and unrelated entities fail.
2. Create a draft, PATCH one field, and verify omitted proposals remain. Clear a proposal with null.
3. Sign in the portal, edit the Draft, and verify it needs a new signature before payment.
4. Pay with a staging voucher, record the invoice and filing IDs, and retry the same resource.
5. Poll review and retrieve the resulting document; handle rejection and delayed PDF generation separately.
6. Read certificate eligibility, create/pay a request, and wait for both `Issued` and `documentUrl`; also verify that `Rejected` and `Cancelled` stop polling without another payment.
7. Retry the completed certificate request and verify it returns the existing certificate.
8. Test timeout/503 handling against a mocked response so your client reads and resumes the same filing.

Treat the steps requiring review/issuance as complete only after the deployed staging flow
has produced the expected records and PDFs. Successful schema validation alone does not
establish end-to-end availability.

## Personal and applicant documents [#personal-and-applicant-documents]

The [dedicated document guide](/personal-and-applicant-documents) provides full response
examples, active-residency matching rules, empty-result troubleshooting, and download handling.

For a person's own documents, use an OAuth token consented for
`eprospera:person.documents.read` or an Agent Key with `agent:person.documents.read`:

```bash
curl -sS "$BASE_URL/api/v1/me/natural-person/documents" \
  -H 'Authorization: Bearer <personal-oauth-token-or-agent-key>'
```

The response contains `data` document records and `agreementOfCoexistence`. Standard
API keys are not accepted on this endpoint. For consented entity reads, use the existing
OAuth `/api/v1/me/legal-entities/{id}/documents` with
`eprospera:entity.documents.read`; unselected entities remain unavailable.

A partner can read only agreements and policy documents for its own applicant:

```bash
curl -sS "$BASE_URL/api/v1/partner/residency_applications/44444444-4444-4444-8444-444444444444/documents" \
  -H 'Authorization: Bearer <partner-key>'
```

This returns the accepted agreement version and, after approval and generation, signed
agreement/policy documents. Identity documents, tax records, and admin-only documents
are excluded. Document URLs in this release have no advertised expiry guarantee;
handle them as sensitive links. See the [applicant document reference](/reference/get-residency-applications-id-documents).
