status is false, data is null, code is a stable machine-readable error code, and meta.next_steps carries an action and a docs_url that links straight to this page at the matching anchor.
message is for developers and logs — do not show it to end users. Quote meta.request_id when contacting support.failure_reason field instead — see Failure reasons.
Bad request
HTTP 400 ·bad_request
The request failed validation — a required field is missing, or a value has the wrong type or format.
Common causes
- A required field was omitted from the request body.
- A field has the wrong type (e.g. a string where a number is expected).
- A value fails a format or enum constraint. The
meta.errorsarray lists the offending fields.
Invalid input
HTTP 400 ·invalid_input
A field passed schema validation but failed a semantic check the API applies before processing.
Common causes
- A value is individually valid but invalid in context (e.g. an amount below the minimum, or mismatched currency pair).
- A referenced field combination isn’t permitted.
- A South African
account_numberthat cannot belong to the chosen bank — wrong number of digits, or any character that isn’t a digit. See South African account numbers below.
message is specific and safe to show to the person who entered the value.
South African account numbers
ZAR bank account numbers are checked structurally before a beneficiary is saved and again when an offramp quote is created. The check is local — it answers “could this number belong to this bank?” and nothing more. It cannot tell you whether the account exists, is open, or accepts credits. Digits only. Spaces, dashes and every other separator are rejected rather than stripped.6200-4626-662 and " 62004626662 " are both invalid, even though removing the punctuation would leave a valid number — we never alter what you send, so a number we accept is exactly the number we pay.
Length depends on the bank, taken from the account_provider on the beneficiary:
Any other South African bank is checked against the general range of 8 to 11 digits.
The
message names the bank and both counts — FNB accounts are 11 digits; this account number has 10. — so it can be surfaced directly to whoever is entering the details.
Two cases worth knowing about:
- PayShap beneficiaries are not affected. On the
payshaprail,account_numberis a proxy — a mobile number in E.164 form, or a ShapName such asacme@nedbank— so none of the rules above apply to it. - An existing beneficiary can fail at quote time. Beneficiaries saved before this check existed are validated the first time you quote against them, so
POST /v1/quotescan return this error for a beneficiary that saved cleanly months ago. Update the beneficiary’saccount_numberand quote again.
Invalid amount precision
HTTP 400 ·invalid_amount_precision
The amount carries more decimal places than the currency can settle. USDC settles in whole US cents, so USDC amounts support at most 2 significant decimal places. Trailing zeros are fine — 2.980000 is accepted, 2.980228 is rejected.
Common causes
- A high-precision USDC
source_amountoramounton an offramp quote, conversion quote, or transfer — for example a 6-decimal value taken directly from a balance or a destination-anchored price calculation.
Prohibited country
HTTP 400 ·prohibited_country
The country_code supplied is on GlobalStack’s compliance prohibited list, so the merchant or customer cannot be onboarded from it. Onboarding is open to all other countries; this is a presence restriction only — it does not limit which currencies or corridors an onboarded merchant can transact in.
Common causes
- Registering a merchant or creating a customer with a
country_codeon the prohibited list. - A typo producing a prohibited ISO code. (A value that isn’t a valid ISO-3166-1 alpha-2 code at all returns
invalid_inputinstead.)
Account resolution failed
HTTP 400 ·account_resolution_failed
The bank account could not be verified with the provider.
Common causes
- The
account_numberis wrong or doesn’t exist at the named institution. - The
provider_id(bank/institution) doesn’t match the account.
Authentication failed
HTTP 401 ·authentication_failed
The request was not authenticated.
Common causes
- Missing
Authorizationheader. - An invalid, revoked, or malformed API key / bearer token.
- Using a key from the wrong environment.
Merchant inactive
HTTP 401 ·merchant_inactive
The merchant account is authenticated but not yet active.
Common causes
- KYC/KYB verification is not complete.
- The account is pending review.
Forbidden
HTTP 403 ·forbidden
The credentials are valid but don’t grant access to this resource.
Common causes
- The API key or user lacks permission for the resource.
- Accessing a resource that belongs to another merchant.
Forbidden key role
HTTP 403 ·forbidden_key_role
The requested API-key role isn’t permitted for this caller.
Common causes
- Creating or granting a key with a role above the caller’s own grant.
Resource access required
HTTP 403 ·resource_access_required
The resource requires an explicit access grant the caller doesn’t have yet.
Common causes
- Using a resource (e.g. a currency) that is gated behind an access request.
Not found
HTTP 404 ·not_found
The referenced resource doesn’t exist.
Common causes
- A wrong, mistyped, or already-deleted resource id in the path.
- The resource belongs to a different merchant account.
Invalid status
HTTP 409 ·invalid_status
The action isn’t allowed while the resource is in its current state.
Common causes
- Acting on a resource whose lifecycle has moved past the point the action is valid (e.g. cancelling an already-settled transfer).
Conflict
HTTP 409 ·conflict
The request conflicts with the current state of the resource.
Common causes
- A concurrent update changed the resource since you last read it.
Duplicate resource
HTTP 409 ·duplicate_resource
A resource with the same unique value already exists.
Common causes
- Re-using a value that must be unique (e.g. a
referenceor a beneficiary already on file).
Idempotency conflict
HTTP 409 ·idempotency_conflict
The Idempotency-Key was already used with a different request body.
Common causes
- Reusing an idempotency key for a request whose body differs from the original.
Idempotency in progress
HTTP 409 ·idempotency_in_progress
A request with the same Idempotency-Key is still being processed.
Common causes
- A retry fired while the original request with that key is still in flight.
API key limit exceeded
HTTP 409 ·api_key_limit_exceeded
The account has reached its maximum number of active API keys.
Common causes
- Creating a new key while at the active-key cap.
Access already granted
HTTP 409 ·access_already_granted
The merchant already has an active grant for the resource.
Common causes
- Submitting an access request for a resource that’s already granted.
Ledger insufficient funds
HTTP 422 ·ledger_insufficient_funds
The source balance doesn’t have enough available funds.
Common causes
- The wallet’s available balance is below the requested amount (funds may be held/pending).
Rate limited
HTTP 429 ·rate_limited
You’ve exceeded the request rate limit.
Common causes
- Too many requests in a short window.
Internal error
HTTP 500 ·internal_error
An unexpected server error occurred.
Common causes
- An unhandled condition on the server.
Upstream service unavailable
HTTP 500 ·external_service_unavailable
An upstream service required to complete the request was unavailable or rejected the request. The failure detail is recorded on our side and never returned in the response.
Common causes
- A transient upstream outage, timeout, or rejection while fulfilling the request (for example, while creating a deposit credential).
Configuration error
HTTP 500 ·configuration_error
The service is misconfigured for the requested operation. This is a deploy-time issue on our side, not something the caller can fix.
Common causes
- A required server-side configuration value is missing or invalid in the current environment.
request_id if it persists.