# Partner onboarding (/partner-onboarding)

How an approved organization is provisioned for the Partner API: what to send e-Próspera, how origins and keys work, what to test before production, and how to report problems.



Partner Keys are issued by the e-Próspera team, not from the portal. This page covers the
operational side of an integration. The API contract is in [Partner Keys](/partner-keys) and
the applicant-facing iframe is in [Embedded agreement and identity verification](/partner-embed).

## Who can be a partner [#who-can-be-a-partner]

A Partner Integration belongs to exactly one legal entity registered in e-Próspera. The entity
must exist and must not be dissolved. Each legal entity can hold one integration, and the
integration is the ownership boundary: applications, uploads, keys, approved origins, and
idempotency records all belong to it. Two companies never share an integration.

Request an integration through the
[e-Próspera Help Center chat](https://help.eprospera.com/en/chat). Staging and production are
separate environments with separate integrations and keys.

## What to send e-Próspera [#what-to-send-e-próspera]

| Item                      | Details                                                                                                                                                           |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Legal entity              | The name or RPN of the entity that will own the integration                                                                                                       |
| Label                     | A short name for the integration, for example `Acme Relocation`                                                                                                   |
| Approved redirect origins | One to ten HTTPS origins. Every `redirectUrl` you send on application creation, update, and hosted checkout must match one of them exactly                        |
| Approved embed origins    | Zero to ten HTTPS origins that may frame the e-Próspera embed. Required only for the [embedded flow](/partner-embed). This list is separate from redirect origins |
| Scopes per key            | The subset of [scopes](/partner-keys#scopes) each key needs                                                                                                       |
| Key label                 | Who or what will hold the key, for example `Acme — backend — production`                                                                                          |
| Environment               | `staging` or `production`                                                                                                                                         |

### Origin format [#origin-format]

An origin is scheme, host, and optional port only.

```text
https://apply.partner.example
https://apply.partner.example:8443
```

An origin is rejected when it contains a path, query string, fragment, credentials, or a
wildcard. Production origins must use HTTPS. Staging additionally accepts loopback HTTP
origins (`http://127.0.0.1:<port>`, `http://[::1]:<port>`, `http://localhost:<port>`) for
local development.

## Environments [#environments]

| Environment | API base URL                       | Embed origin                          |
| ----------- | ---------------------------------- | ------------------------------------- |
| Production  | `https://portal.eprospera.com`     | `https://embed.eprospera.com`         |
| Staging     | `https://stg.portal.eprospera.com` | `https://staging-embed.eprospera.com` |

## Key lifecycle [#key-lifecycle]

* The raw `pk-...` value is shown once at issuance. e-Próspera stores only its SHA-256 hash.
  If the value is lost, the key is revoked and a new one is issued.
* Keys expire 90 days after issuance. Plan rotation in your operations calendar.
* Issuing a replacement key shortens every older active key on the integration to a maximum
  seven-day overlap. Deploy the new key within that window.
* Scopes are fixed at issuance. To change scopes, request a new key with the new scope set;
  the change becomes part of the audited rotation.
* Any key can be revoked immediately. Revoked keys return `401` on every request.
* An integration can be **suspended**, which makes every key return `401` until it is
  reactivated, or **revoked**, which is permanent. Existing applications keep their history.
* Authentication is also refused while the owning legal entity is dissolved.

### Several engineers or systems [#several-engineers-or-systems]

Issue one key per holder rather than sharing a key. Each key has its own label, last-used
timestamp, and audit trail, and revoking one holder does not interrupt the others. Keep
staging and production keys in separate secret stores.

## Security responsibilities [#security-responsibilities]

* Send the key only from your backend. Never ship it to a browser or a mobile app.
* Treat `nextSteps.agreementUrl` and `embedUrl` as short-lived bearer secrets. Deliver them only
  to the intended applicant and keep them out of logs, analytics, and support tickets.
* In the embedded flow, the PKCE verifier stays in the applicant's browser. Never send it to
  your backend, put it in a URL, or record it.
* Authorize your own signed-in user before creating or reading an application on their behalf,
  and verify in your system that the application belongs to that user.
* Applicant data you send is personal data. Minimize what you retain.

## What e-Próspera records [#what-e-próspera-records]

Every Partner API call is audited with the method, path, response status, key, and
integration, without the raw credential. Denied scopes, throttling, and inactive-key attempts
are recorded too. The e-Próspera team can see every application created under an integration,
the audit log, and each key's last-used timestamp. Partners do not have a self-service view of
this data today; ask through the Help Center when you need an export.

## Before a production key is issued [#before-a-production-key-is-issued]

Complete this checklist in staging with your staging key. Use applicant email addresses you
control. See [Testing in staging](/testing-in-staging#partner-keys-in-staging) for
staging-specific behavior such as the reusable voucher and automatic approval.

**Happy path**

1. Create a Draft with an `Idempotency-Key`; confirm `applicantPortalAccess.claimLinkSent` is
   `true` for a fresh applicant email.
2. Repeat the identical request; confirm `Idempotency-Replayed: true` and the same `id`.
3. Reuse the key with a changed body; confirm `409`.
4. Upload a proof-of-address document; confirm the response carries an opaque `id` and no URL.
5. PATCH the full application with `expectedVersion` and the upload ID; confirm `version`
   increments.
6. Repeat the PATCH with the old version; confirm `409` with `currentVersion`.
7. Pay with the staging voucher or hosted checkout using a new `Idempotency-Key`; confirm the
   application stays in `Draft`.
8. Complete either the hosted agreement path or the embedded flow with a real browser.
9. Hosted path only: call `/submit` once `nextSteps.submitReady` is `true`.
10. Poll `GET /partner/residency_applications/{id}` until `statusId` leaves `Pending Review`.
11. After approval, read `/documents` and wait for the signed agreement file. Check its
    download separately from agreement acceptance; follow the
    [document integration checklist](/personal-and-applicant-documents#integration-acceptance-checklist).

**Failure cases**

* A `redirectUrl` on an unapproved origin returns `400`.
* A key without the required scope returns `403`.
* Another integration's application returns `404` on read, update, download, pay, and submit.
* An expired or revoked key returns `401`.
* Embedded flow: an unpaid or incomplete application returns `409` on session creation, a
  frame loaded from an unapproved origin is denied, and messages from the wrong origin or
  window are ignored by your listener.
* No response body or `postMessage` event exposed a signature, identity document, Veriff URL,
  or decision detail.

## Reporting a problem [#reporting-a-problem]

Send the approximate timestamp in UTC, the HTTP status, the endpoint path, and the application
or session ID. Do not include the Partner Key, the PKCE verifier, an `embedUrl` or
`agreementUrl`, applicant personal data, signatures, or identity documents.

## Limits [#limits]

* Restricted-country applicants: the Partner API cannot currently attach the reference letters
  and exemption that e-Próspera requires for applicants born in, or citizens of, restricted
  jurisdictions. Onboard those applicants through the portal instead. Ask the Help Center for
  the current list.
* There are no outbound webhooks. Poll application status; see
  [Conventions](/conventions#webhooks).
* Partner Keys are not supported by the `eprospera` CLI. Use direct HTTP.
