Errors cookbook

Per-code real-world remedies: symptom, cause, remedy for every numeric code in the envelope.

Every numeric code maps to a finite set of remedies. Use this when something is failing in integration testing or production. Reference table: Errors.

code: 1 — INVALID_REQUEST

Symptom

HTTP 400. Some endpoints also return HTTP 409 when an Idempotency-Key is reused with a different payload.

Common causes

  • The asset code (fromCcy / toCcy) is misspelled or disabled.
  • direction is not one of "from" / "to".
  • amount parses to zero or a negative number.
  • toAddress does not validate against the destination asset’s network.
  • type = "float" without refundAddress.
  • Idempotency-Key shorter than 8 chars or longer than 128.
  • Idempotency-Key reused with a different body (HTTP 409).

Remedy

Inspect the request body. There are no hidden hints; the wire body is exactly { "code": 1, "msg": "INVALID_REQUEST" }. If your logs show one cause repeatedly, add a pre-flight validation step before the POST.

code: 2 — AUTH_REQUIRED

Symptom

HTTP 401 on an endpoint that requires authentication.

Cause

You forgot to set X-API-KEY or X-API-SIGN.

Remedy

Check that your HTTP client sends all three headers: X-API-KEY, X-API-SIGN, X-API-NONCE. The third is the one most integrations forget. A missing X-API-NONCE collapses to code: 3 AUTH_INVALID, not code: 2. Those are different failure modes.

code: 3 — AUTH_INVALID

Symptom

HTTP 401, possibly on a request that looks fine at first glance.

Common causes (uniform on the wire, indistinguishable)

  • Unknown apiKey.
  • Bad HMAC: signature computed over a different byte stream than the body you sent (re-serialised, sorted keys, whitespace difference, or echo appending a trailing newline).
  • apiSecret wrong, typo, or from a different partner.
  • X-API-NONCE empty, shorter than 16, longer than 64, or already used in the last 5 minutes.

Remedy

  1. Print apiKey and the body bytes you signed; print the body bytes the HTTP client actually sent (after middleware). They must match byte-for-byte. The most common bug is middleware that pretty-prints JSON after the signature step.
  2. Use printf '%s' "$BODY" and --data "$BODY", never echo and --data-raw. echo appends a newline.
  3. Generate a fresh nonce on every request. Never reuse across retries.

code: 4 — AUTH_DISABLED

Symptom

HTTP 401, but the signature was valid (you can prove this because the same nonce + signature on a different second still returns AUTH_DISABLED, not AUTH_INVALID).

Cause

The operator has flipped enabled = false on your partner record. Reasons: planned maintenance, credential revocation, or a billing pause.

Remedy

Contact your operator. There is no API path to recover.

code: 5 — RATE_LIMIT

Symptom

HTTP 429 with a Retry-After: <seconds> header.

Cause

Your per-partner weight budget (default 2500 wu/min) is exhausted within the rolling 60-second window. POST /v1/create weighs 50, POST /v1/qr weighs 5, every other endpoint weighs 1.

Remedy

  • Sleep for Retry-After seconds (no less) before the next request.
  • For burst traffic, queue server-side and drain at ≤ budget/60 calls per second.
  • For sustained growth, send projected per-endpoint call rates to your operator and request a budget raise.

code: 6 — NOT_FOUND

Symptom

HTTP 404 on /v1/order, /v1/qr, or /v1/emergency.

Causes (collapsed into one envelope, no oracle)

  • The id does not exist.
  • The id belongs to another partner.
  • The token does not match the stored hash.
  • The order was soft-deleted by the user.

Remedy

Re-verify that id and token come from a successful /v1/create on this same partner record. If they do, the order was soft-deleted by the end user. Your aggregate counters remain accurate, but the underlying row is no longer queryable.

code: 7 — LIMIT_MIN

Symptom

HTTP 400 on /v1/create.

Cause

Your amount is below the per-pair USD minimum (default $1).

Remedy

Quote /v1/price first and respect the from.min and to.min fields in the response. /v1/price returns these bounds for pre-validation but does not reject out-of-range amounts. Only /v1/create enforces the gate.

code: 8 — LIMIT_MAX

Symptom

HTTP 400 on /v1/create.

Cause

Either the per-pair USD maximum is exceeded (default $5,000), or the daily payout cap on the operator side is exhausted.

Remedy

Lower the amount, split into multiple orders, or contact the operator for a higher per-order cap (operator-mediated).

code: 9 — RESERVE_EXCEEDED

Reserved for a future per-partner capacity control. No current route emits this code. Safe to omit from exhaustive switch statements until announced.

code: 10 — MAINTENANCE

Symptom

HTTP 503.

Cause

The site is in operator-toggled upgrade mode (rare).

Remedy

Retry with exponential backoff capped at 60 seconds. The window is usually short (< 5 min).

code: 11 — UPSTREAM_ERROR

Symptom

HTTP 503.

Cause

A required upstream is temporarily unavailable.

Remedy

Retry with exponential backoff: 1 s, 2 s, 5 s, 10 s, then bail and surface a partner-facing error.

code: 12 — EMERGENCY_INVALID_CHOICE

Symptom

HTTP 400 on /v1/emergency.

Cause

The choice field is not exactly "EXCHANGE" (case-sensitive).

Remedy

Send { "choice": "EXCHANGE" }. The "REFUND" choice is not exposed on the public surface — refunds are operator-mediated.

code: 13 — LIMIT_EXCEEDED

Symptom

HTTP 403 on POST /v1/codes.

Cause

Your partner record has already reached the per-partner cap on reference codes (default 50).

Remedy

Delete (soft-disable) unused codes via DELETE /v1/codes, or ask the operator to raise the cap.

code: 14 — ROTATION_CONFLICT

Symptom

HTTP 409 on /v1/keys/rotate.

Cause

Two concurrent rotation calls from different processes; the other one won. Your call did not rotate anything.

Remedy

The winning call already returned new secrets to someone. If your process was the loser and never saw the new values, request a fresh rotation through the operator (the only recovery path). Do not retry the losing rotation; the secret it would compete for has already changed.

code: 99 — INTERNAL

Symptom

HTTP 500.

Cause

Unexpected server-side condition. Already logged on our side; if it recurs, share the timestamp and the request body shape with your operator contact.

Remedy

Safe to retry once with the same Idempotency-Key for /v1/create. For other endpoints, retry with a fresh nonce.

Partner API.
Same engine as 0trace.

A private partner integration surface. Signed quotes, server-side pricing, webhook delivery, multiple reference codes, and a self-serve cabinet — all backed by the production exchange engine.

Support

Questions? Answers.

Get the latest updates

Follow us on X

The 0trace team will never ask for KYC or AML. We retain no logs, metadata, or tracking cookies.

Learn more