Documentation

Errors

Every API error uses one JSON envelope. The HTTP status tells you the class of failure; the code tells you what to do. Do not branch on the human-readable message.

JSONCode
{ "error": { "code": "quote_expired", "message": "The quote expired.", "requestId": "3f4c1a8e-7b2d-4f0e-9a61-2d8c5b7e1f04" } }

requestId is also returned in X-Request-Id. Include it in a support request. Never include the API secret, LPA text, QR data or customer records.

Status classes

StatusMeaningRetry?
400Malformed request or unsupported valueFix the request first.
401Missing, invalid, expired or replayed credentialFix authentication. Do not retry unchanged.
402Wallet cannot cover the orderFund the wallet or reduce the order.
403Scope, allowlist, account or agent restrictionFix authority. Do not retry unchanged.
404Object absent or not owned by this partnerConfirm the id and environment.
405Method not allowed on this pathUse the documented method.
409Stock, price, quote, redemption or idempotency conflictRe-read state before retrying.
413Request body too largeReduce the body.
429Per-minute limit or daily quota exhaustedWait Retry-After.
500Unexpected server failureConfirm no effect, then retry an idempotent mutation with the same key.
501Capability deliberately gatedDo not retry. Use a supported path.
503Dependency unavailable (FX, payment provider)Retry later with backoff.

Error codes

HTTPCodeMeaningSafe action
400validation_errorMissing or malformed inputCorrect the body, query or header.
401missing_signatureOne or more signing headers absentSend all four signing headers.
401unauthorizedUnknown, revoked or wrong-environment keyCheck the API ID and environment.
401signature_invalidHMAC mismatchRecompute over the exact path and raw body.
401request_expiredTimestamp outside five minutesSync the clock and use a fresh timestamp.
401replayedNonce already usedGenerate a fresh nonce.
401key_expiredKey passed its expiryRotate or issue a new key.
401agent_inactiveAgent suspended, revoked or expiredAsk the owner to reactivate or reissue.
402insufficient_fundsAvailable wallet credit is below the totalFund the wallet or reduce the order.
402payment_requiredTarget payment envelope with a funding URLSurface the funding URL to the principal. Planned.
403forbiddenKey lacks the required scope, or the agent tried a principal-only actionRequest the scope or use a principal key.
403ip_not_allowedSource IP is outside the key allowlistUse an allowed egress address.
403account_not_activeAccount review is incompleteFinish onboarding before ordering.
404order_not_foundPurchase absent or not ownedCheck the purchase id and environment.
404quote_not_foundQuote absent, closed or not ownedCreate a new quote.
404agent_not_foundAgent absent or not ownedCheck the agent id.
404key_not_foundKey absent or not ownedCheck the key id.
404error_not_foundError group absentCheck the error group id.
405method_not_allowedWrong methodUse the documented method.
409out_of_stockNo sellable stock for at least one offerRefresh the catalogue or reduce quantity.
409price_changedQuote no longer matches the current priceRe-quote or retry the one-call order with a fresh expected total.
409quote_expiredQuote lifetime endedCreate a new quote.
409not_redeemablePurchase not fulfilled or no credentialsPoll the purchase before redeeming.
409idempotency_conflictKey already used for a different or paid operationReuse the original request or use a new key for a new operation.
409approval_requiredOrder exceeds an approval thresholdStop and request human approval. No charge is made.
413validation_errorStripe receiver payload over 256 KBReduce the payload.
429rate_limitedPer-minute or burst limit exceededWait Retry-After, then retry with jitter.
429quota_exceededDaily quota exhaustedWait for the UTC reset or use another call class.
500internal_errorUnexpected failureConfirm no effect, then retry with the same idempotency key.
501capability_unavailableFeature is gatedDo not retry. Use a supported path.
503fx_unavailableEUR or GBP rate missing or staleRetry later or use USD.
503payment_pendingStripe is not configuredFunding is unavailable. Do not retry.

approval_required and payment_required are part of the target agent contract and are not returned by every deployment yet. Handle them if you receive them, and handle the current 402 insufficient_funds shape as well.

Retry rules

Reads

Retry 429, 500 and 503 with exponential backoff and jitter. Use a fresh nonce for every attempt. A read is safe to repeat.

Mutations

Order, redeem and funding calls are idempotent only when you reuse the same Idempotency-Key and the same body. A new key creates a new logical operation.

SituationAction
402 insufficient_fundsDo not retry. Fund the wallet.
402 payment_requiredDo not retry. Surface funding_url.
409 price_changedRe-quote or retry one-call with the returned total and a new decision.
409 quote_expiredCreate a new quote.
409 idempotency_conflictResolve the original operation. Do not generate a new key to bypass it.
429Wait Retry-After, then retry with the same key.
500Poll the purchase or wallet first, then retry with the same key.
503 payment_pendingDo not retry. Funding is not configured.

Unknown outcomes

If a timeout or connection reset leaves the outcome unknown, do not create a second order. Call GET /v1/orders/{purchaseId} if you have the id, or GET /v1/orders to find the reference. Only create a new attempt after confirming the original did not exist.

What never appears in an error

  • The API secret or any part of it.
  • LPA strings or QR payloads.
  • Upstream store, product or cost identifiers.
  • Customer personal data.
  • Stack traces or internal SQL.

Support

Send the X-Request-Id, UTC time, method, path, status and error code to [email protected]. For a suspected credential leak, use [email protected] and revoke the key first.