Error code catalog
Every code the /v1 API can return, one section each. code is stable and safe
to branch on; the message accompanying it is not.
Retryable means retrying the identical request may succeed without any other change. Where it says not retryable, retrying will fail identically — fix the request, the state, or the credential.
doc_url links to the code
Every error carries a doc_url pointing at its own section on this page:
{
"error": {
"type": "validation_error",
"code": "kyc_not_approved",
"message": "Cardholder chd_01HX8ZQ2K4M7P9RSTV is not verified (status not_started).",
"param": "card_id",
"doc_url": "https://developer.aletaplanet.com/api-reference/errors/error-code-catalog#kyc_not_approved",
"request_id": "req_01HX8ZQ2K4M7P9RSTV"
}
}
The fragment is always the code itself, so you can build the link for any code
here without waiting for an error to hand you one. Surfacing doc_url in your
own logs and support tooling turns a code into a page an engineer can read.
type is the broad category — decide how to handle a failure from it, and
what happened from code. See the error object for the
envelope and HTTP status mapping for what each status
means on its own.
Token endpoint — RFC 6749 shape
POST /oauth/token does not use the ErrorObject envelope. It answers with
the flat body OAuth client libraries expect, and carries no code or doc_url:
{ "error": "invalid_client", "error_description": "…" }
| Status | error | Meaning and fix |
|---|---|---|
401 | invalid_client | The client is unknown or revoked, the assertion's signature did not verify, it was signed for the other environment, or the source address is not on the allowlist. The description says which — but only once the signature is proven; before that, every refusal reads the same on purpose |
400 | invalid_grant | This assertion's jti was already redeemed. Sign a fresh one |
400 | invalid_scope | A requested scope is not held by the client, or is not a scope at all |
400 | invalid_request | The assertion is not a well-formed JWT, or a required form field is missing |
400 | unsupported_grant_type | grant_type was not client_credentials |
500 | server_error | Not the request's fault — an unexpected failure on our side. Log the request and retry once; treat a second server_error as a real outage, not a mistaken assertion |
An assertion that has expired, or is more than five minutes from expiring, is
just invalid_client with the same uninformative description every other
pre-signature failure gets — the clock skew is not named, on purpose. A clock
more than sixty seconds off is the most common cause, so check the signing
host's time before anything else, even though the error will not point you
there.
Request
Malformed or unacceptable input, refused before anything was done with it.
invalid_request_body
400 · invalid_request_error · not retryable
Body is not valid JSON, or not an object where one was required.
missing_parameter
400 · invalid_request_error · not retryable
A required field is absent. param names it.
program_id on POST /v1/accounts is the one to watch: it is required even if your organization holds a single program, because defaulting to your only one would be right until the day a second product went live. GET /v1/programs lists the ids you may send, for the environment your token names.
invalid_parameter
400 · invalid_request_error · not retryable
Wrong type, format, or out of range. param names it. This is also the code a 422 falls back to when several fields fail at once — errors[] then carries one entry per field.
unknown_parameter
400 · invalid_request_error · not retryable
A field in the body is not one this endpoint accepts. param names it. Unknown fields are refused rather than ignored, so a typo cannot silently do nothing.
invalid_public_key
400 · invalid_request_error · not retryable
The RSA key supplied for card details is malformed, or weaker than 2048-bit.
Authentication
The credential itself. See authentication for how tokens are obtained.
missing_credentials
401 · authentication_error · not retryable
No Authorization header. Send Bearer <access token>.
invalid_access_token
401 · authentication_error · not retryable
The token is expired, unknown, or its client has been revoked. Get a new one from the token endpoint; if that is refused too, the client itself is the problem. Tokens live fifteen minutes — treat this as "fetch a new token, then retry once", and a second 401 as final.
Permission
The credential is valid and is not allowed to do this.
insufficient_scope
403 · permission_error · not retryable
The client does not hold the scope this endpoint needs. Scopes are frozen at token issue, so add it to the client in Cockpit and get a new token.
ip_not_allowed
403 · permission_error · not retryable
The source address is not on the allowlist. Two lists apply: your organization's and the client's own. A client can only ever be more restricted than its organization.
environment_mismatch
403 · permission_error · not retryable
This token was issued for the other environment. Sandbox tokens start at_test_, production at_live_; both use the same base URL.
Not found
A resource that exists but belongs to another organization answers exactly as one that does not exist. The two are indistinguishable by design.
not_found
404 · invalid_request_error · not retryable
No route matches this path. Simulator endpoints answer this way in production, where they do not exist.
cardholder_not_found
404 · invalid_request_error · not retryable
No cardholder with this id in this environment.
account_not_found
404 · invalid_request_error · not retryable
No account with this id in this environment.
card_not_found
404 · invalid_request_error · not retryable
No card with this id in this environment.
authorization_not_found
404 · invalid_request_error · not retryable
No authorization with this id in this environment.
transaction_not_found
404 · invalid_request_error · not retryable
No transaction with this id in this environment.
dispute_not_found
404 · invalid_request_error · not retryable
No dispute with this id in this environment.
esim_package_not_found
404 · invalid_request_error · not retryable
No eSIM package with this id in this environment.
esim_order_not_found
404 · invalid_request_error · not retryable
No eSIM order with this id in this environment. If you are recovering from a timed-out create and never saw an id, look the order up by your own reference instead.
esim_not_found
404 · invalid_request_error · not retryable
No eSIM with this id in this environment.
token_not_found
404 · invalid_request_error · not retryable
No network token with this id in this environment.
A key minted under one program answers this way when presented against a card in another — from that card's side the key genuinely does not exist, and saying so is the same answer as for an id that was never issued. If you run more than one program, mint the key with the card's own program_id.
Idempotency
See idempotency for how keys are matched.
idempotency_key_reuse
409 · invalid_request_error · not retryable
Same Idempotency-Key, different body. Almost always a bug in your retry logic.
idempotency_request_in_progress
409 · invalid_request_error · retryable
The original request is still running. Retry after a short backoff. Also
returned when a credit or debit carrying the same client_transaction_id is
still in flight.
adjustment_already_applied
409 · invalid_request_error · not retryable
A credit or debit with this client_transaction_id was already applied to the
account with a different amount or direction. The message says what was
applied. A repeat with the same amount is not an error — it returns 200 with
Idempotent-Replay: true and moves nothing.
Cardholders
identity_document_required
422 · validation_error · not retryable
A card cannot be issued to a cardholder with no identity_document. Set it when creating the cardholder; only the number and type are held, and neither ever comes back out of the API.
address_required
422 · validation_error · not retryable
The cardholder has no address, and the card is registered to it. Add one with PATCH /v1/cardholders/{id}. Not the same as delivery_address_required, which is about the address on the issuance request.
kyc_not_approved
422 · validation_error · not retryable
kyc_status is not approved. Report an approved attestation before issuing a card.
cardholder_already_exists
409 · invalid_request_error · not retryable
Another cardholder in your organization already has this email or phone. param names which.
address_change_requires_kyc
422 · validation_error · not retryable
This program's processor cannot take an address change through PATCH /v1/cardholders/{id}. Report a KYC attestation that carries the new address instead.
kyc_identity_required
422 · validation_error · not retryable
The program's processor runs its own identity verification, and the cardholder's current attestation carries no identity. Report one through POST /v1/cardholders/{cardholder_id}/kyc before opening the account — an attestation reporting only an outcome is a valid record, and not enough here.
The same code answers an attestation whose supporting documents are no longer held. Report a fresh one with the documents attached.
Accounts
insufficient_funds
402 · validation_error · not retryable
available_balance is too low for this debit. Credit the account, then retry. Note the 402: retrying after funding is correct, where retrying a 422 never is.
account_blocked
422 · validation_error · not retryable
The account is blocked and cannot fund a card or take this operation. Unblock it first.
currency_mismatch
422 · validation_error · not retryable
Currencies differ across the operation. Nothing is converted implicitly — a cardholder needing two currencies needs two accounts.
account_cardholder_mismatch
422 · validation_error · not retryable
The account belongs to a different cardholder than the one named. Both objects exist and both are yours, so this is a genuine mismatch rather than a tenancy failure.
account_not_provisioned
422 · validation_error · not retryable
The account does not exist at the processor yet, so it cannot hold a card. has_upstream_reference reports this on the account.
account_not_fundable
422 · validation_error · not retryable
This account cannot take a credit in its current state.
Cards
card_invalid_state
422 · validation_error · not retryable
The card's status does not permit this operation: not yet issued or activated, frozen, expired, or already in the state asked for.
card_already_activated
422 · validation_error · not retryable
Activate card was called on a card that is already active. The card is usable;
there is nothing to repeat.
card_closed
422 · validation_error · not retryable
Closure is not reversible, by any call. Issue a new card.
card_not_provisioned
422 · validation_error · not retryable
The processor has not issued the card yet, so the operation cannot reach it. Wait for card.issued, then try again.
card_limit_reached
422 · validation_error · not retryable
The cardholder already has a card with the processor behind this program, which holds one card per cardholder.
unsupported_form_factor
422 · validation_error · not retryable
The program does not issue the form factor asked for. message lists the ones it does issue.
embossed_name_required
422 · validation_error · not retryable
embossed_name is required for every card, virtual or physical. It is fixed when the card is issued.
delivery_address_required
422 · validation_error · not retryable
Every card needs a complete delivery_address on the request, virtual or physical. It is fixed when the card is issued. Not the same as address_required, which is the cardholder having no address at all.
card_type_not_configured
422 · validation_error · not retryable
Your program has no card product for the card_type asked for — most often credit on a debit-only program. Nothing was sent to the processor. A configuration change on our side, so raise it with your account contact.
PIN
pin_invalid
422 · validation_error · not retryable
The PIN is unusable, and message says why: it is not the program's PIN length, it is not all digits, or it was not encrypted to the key you were given. Nothing was sent to the processor.
Transactions and tokens
transaction_not_refundable
422 · validation_error · not retryable
The transaction's state does not permit a refund: not settled, or already fully refunded.
refund_exceeds_original
422 · validation_error · not retryable
The refund is larger than what remains of the transaction.
token_invalid_state
422 · validation_error · not retryable
The token's status does not permit this operation.
token_deleted
422 · validation_error · not retryable
Deletion is terminal. The cardholder must add the card to the wallet again.
Program and controls
program_not_provisioned
422 · validation_error · not retryable
No program is attached to your organization in this environment, or the one you named cannot be served by the deployment that answered you. A configuration matter on our side — raise it with your account contact rather than retrying.
program_not_configured
422 · validation_error · not retryable
Your program's processor configuration does not cover the operation you asked for — a PIN operation on a program with no PIN key, for example. Nothing was sent to the processor. A configuration matter on our side; raise it with your account contact rather than retrying. Card issuance reports its own case as card_type_not_configured.
Most endpoints reach this without you naming a program at all. A program is named once, on POST /v1/accounts, and every card and account operation afterwards resolves it through the account — so a program that has stopped being serviceable by the deployment answering you surfaces here rather than at the call that named it.
spend_control_unsupported
422 · validation_error · not retryable
A control in the request is one no upstream operation can enforce. Accepting it would tell you the card is restricted when nothing is restricting it.
operation_unsupported
422 · validation_error · not retryable
The processor behind your program has no such operation. This is a fact about which program you are pointed at rather than something failing, so repeating the request returns the identical answer.
It appears in the simulator: some events cannot be injected because they originate outside the platform — a chargeback begins with a cardholder at another bank, and arrives here only as a notification — and no request of yours causes one. The simulator route itself is mounted because your program's processor offers simulation generally; this is one event its sandbox has no injector for.
eSIM
esim_package_unavailable
422 · validation_error · not retryable
The package exists but is not on sale — we have frozen or withdrawn it. Read the package to see its status; a frozen one may return, a withdrawn one will not.
esim_top_up_unavailable
422 · validation_error · not retryable
This add-on cannot be bought on this eSIM. Either it has stopped being sold, or the package it extends is not running — a package that has never reached a network has nothing under way to add to. List the eSIM's top-ups for what it can take right now.
esim_inventory_exhausted
422 · validation_error · retryable once stock returns
The package is on sale and your request is valid — we have no eSIM left to provision it onto. Nothing was charged.
This is about our inventory, not about the package, which is why it is a distinct code: reading the package will show it perfectly healthy, and ordering a different one will not help, because the shortage is upstream of the catalog. Retry later. If it persists, raise it with us rather than working around it — a pool that stays empty is ours to refill.
esim_order_reference_exists
409 · invalid_request_error · not retryable
An order in your organization already carries this reference — package orders and top-ups share one ledger, so a reference spent on either is spent. Either the purchase went through and you are seeing your own earlier order, or the id was reused by mistake — check before sending a different one. Retrying an ambiguous request belongs to Idempotency-Key, not to a new reference.
Rate limits
rate_limited
429 · rate_limit_error · retryable
Too many requests. Wait for Retry-After, then retry with jitter.
Server
None of these are your request's fault, and all three are safe to retry. A write that timed out must be retried with the same Idempotency-Key — see retrying 504 and network timeouts.
processor_unavailable
502 · api_error · retryable
A system we depend on failed or timed out. Its own error is never passed through; the request_id on the response is the reference to quote.
processor_permission_denied
502 · api_error · retryable
We were refused by a system we depend on. Not something you can fix from your side — send us the request_id.
internal_error
500 · api_error · retryable
An unexpected failure on our side. Retry with backoff; if it persists, send us the request_id.
Codes not on this page
Cockpit's own API — sign-in, team management, credential management — has its
own codes, which a /v1 client never sees. They are not published here because
nothing you integrate against can raise them.