Appearance
Conventions
Shared rules that apply across every endpoint of the e-Próspera API. Most reference pages link here instead of restating these conventions.
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
Every authenticated request uses the Authorization header with a Bearer token:
text
Authorization: Bearer <token>The token can be one of three 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. |
| 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
- Request bodies on
POSTendpoints (other than OAuth/token) areapplication/json. - OAuth
/api/oauth/tokenisapplication/x-www-form-urlencodedper RFC 6749. - All responses are
application/jsonunless explicitly noted.
Response envelopes
Most endpoints wrap successful payloads:
| Endpoint shape | Envelope |
|---|---|
Single resource (GET /resource/{id}) | { "data": { ... } } |
Collection (GET /resource) | { "data": [ ... ] } (see Pagination) |
| Create flows | { "data": { ... }, "nextSteps": { ... } } |
| Coupon-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
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
| Status | Meaning in this API |
|---|---|
200 | Success. |
400 | Validation error or conflicting state (e.g. application already submitted). |
401 | Missing, malformed, or invalid credential. Re-authenticate. |
403 | Credential is valid but lacks the required scope (Agent Key) or insufficient 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 already taken). |
429 | Rate limit exceeded. See Rate limits. |
500 | Server error. Safe to retry with backoff for idempotent operations only. |
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
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
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 limiting is per-endpoint, not global, and is rolling out gradually. 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 |
| All other endpoints | No documented limit today. |
When throttled, the response is 429 with { "error": "Rate limit exceeded", ... }. No Retry-After header is currently emitted; back off exponentially. Expect rate limits to be added to more endpoints over time — design for retries.
Pagination
List endpoints other than /api/v1/nomadlayer/applications are not currently paginated. They return the full result set under a top-level data array in a single response. This is the current contract, but agents should design clients to tolerate a future pagination envelope being added without breaking. The pattern we will converge on is the one already shipped on /api/v1/nomadlayer/applications:
json
{
"data": [
/* ... */
],
"pagination": {
"page": 1,
"pageSize": 20,
"totalCount": 134,
"pageCount": 7
}
}When that ships, query parameters will be ?page=<int> (default 1, min 1) and ?pageSize=<int> (default 20, max 100). Until then, treat result sets as bounded by the underlying data — there are no current pagination parameters to send and no pagination field to read on these endpoints.
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
There is no Idempotency-Key header today. POST /legal_entity_applications is not idempotent: a repeated request creates a duplicate Draft application. Implement deduplication on the caller side until idempotency keys are added.
Webhooks
There are no public webhooks. Approval, payment, and signature events must be discovered by polling the relevant GET endpoint (e.g. GET /api/v1/legal_entity_applications/{id} for statusId changes). Recommended polling cadence is 5–30 seconds during an active flow, then exponential back-off.