Quitanza

Errors

Every error the API returns carries one envelope, whatever the route:

{
  "error": {
    "code": "not_found",
    "message": "escrow esc_1234 not found",
    "docsUrl": "https://quitanza.com/docs/errors.html#not_found"
  }
}

The code is stable and machine-matchable; the message is for humans and may change; docsUrl points at the section below that explains the code. Match on the code, never on the message.

The codes

bad_request (HTTP 400)

The request body is malformed: missing required fields, invalid JSON, or values of the wrong shape. Fix the request; retrying unchanged will fail the same way.

unauthorized (HTTP 401)

The deployment requires Authorization: Bearer <api key> on /v1 routes and the header is missing or wrong.

forbidden (HTTP 403)

The operation is admin-only and this deployment cannot perform it, e.g. issuer rotation on an open sandbox with no API key configured.

mandate_violation (HTTP 403)

The escrow would exceed the mandate the payer acts under: per-escrow cap, cumulative cap, asset allowlist, counterparty allowlist, or expiry. The mandate's usage is inspectable at GET /v1/mandates/{id}.

unauthorized_ruling (HTTP 403)

A dispute ruling lacked the required signatures: both parties (co-signature) or the named arbiter. Also returned for malformed split shares: shares that do not sum to 10000 basis points, are not integers, or appear on a non-split ruling. The platform never rules.

not_found (HTTP 404)

No such resource: an unknown id, or a route that does not exist.

invalid_state (HTTP 409)

The escrow cannot make that transition from its current state, e.g. delivering before funding, or disputing a settled matter. Fetch the escrow to see where it stands.

rate_limited (HTTP 429)

Too many requests in the current window. Back off and retry; idempotency keys make retries safe on create and fund.

unprocessable (HTTP 422)

The request was well-formed but the operation could not proceed, e.g. a dispute opened by a key that is not a party.

custody_failed (HTTP 502)

Custody could not settle: the chain was unreachable or the transaction did not confirm. Nothing is lost: the settlement is journaled, the escrow carries custody.status: "settle-failed", a custody.failed event fired, and POST /v1/escrows/{id}/custody/retry resumes it. A quitanza is never issued without a confirmed settle.

x402 payment errors (HTTP 402)

The x402 handshake refuses a payment with the same envelope and one of these codes: malformed_header, version_mismatch, scheme_mismatch, wrong_resource, wrong_payee, wrong_asset, bad_signature. Each names exactly what disagreed between the offer and the signed payment authorization.

Retry guidance

Code Retry?
bad_request, unprocessable, x402 codes No. Fix the request first
unauthorized, forbidden No. Fix credentials or use a capable deployment
mandate_violation, unauthorized_ruling No. Authority is missing, not luck
invalid_state No. Re-read the escrow state
not_found No, unless you created the resource a moment ago
rate_limited Yes, after backing off
custody_failed Yes, via the custody retry route

This page as markdown