Troubleshooting HTTP Integrations
Start with the response status, stable error code, and request correlation id. Do not start by rotating credentials or resubmitting an uncertain order.
Fast decision path
- Record the UTC time, method, path template, status,
X-Request-Id, bodyrequestId, stablecode, and whether a response body arrived. - For 401/403, verify the credential type, account binding, scope, clock, and request-signing inputs. Create a fresh transport-auth tuple for a new HTTP attempt, but keep the action body and idempotency identity unchanged.
- For 409, reconcile the nonce or idempotency key. Do not parse prose when a structured code or nonce window is available.
- For 429/503, honor
Retry-Afterwhen present. When absent, use capped exponential backoff with jitter. A 503 does not prove that a mutating request was rejected. - For a timeout or lost response, query receipts, order state, private execution events, and the authoritative account bootstrap before resending.
- After HTTP 200
accepted: true, continue until a terminal receipt, fill, cancel, or rejection resolves the action.
Common symptoms
| Symptom | Check | Safe action |
|---|---|---|
| 401 | Expiry, clock skew, key id, bearer type, canonical method/path/query/body hash | Refresh or correct authentication, then sign a new transport attempt. |
| 403 | Scope, wallet/account binding, app channel, allowed market/IP/policy | Correct permission or identity; repeating identical credentials will not help. |
| 409 nonce conflict | nonceFloor, nonceWindow, nonceHoles, nextUsableNonce | Select an unused allowed nonce only after reconciliation, then re-sign. |
| 409 idempotency conflict | Key, canonical endpoint, request hash, prior response | Replay only the identical operation or allocate a new key for a deliberately new operation. |
| 429 | Retry-After, X-RateLimit-*, body retryAfterMs, live BSL limits | Pace the correct scope; do not interpret missing headers as zero capacity. |
| 503 / timeout | Readiness, receipt, private stream, order id, idempotency state | Preserve identity and reconcile before retrying. |
| Balance/order view appears old | asOf, projection versions, receipt/event cursor | Use /accounts/{account}/bootstrap?fresh=true; follow the freshness procedure below. |
Sanitized diagnostic bundle
Send this through the integration access channel provided during onboarding, or
email [email protected]:
Environment/host:
UTC time window:
HTTP method + path template:
HTTP status or "no response":
X-Request-Id:
Body requestId:
Stable error code:
Retriable/details (sanitized):
Admission ACK observed? yes/no/unknown:
Terminal receipt/event observed? yes/no/unknown:
Last receipt/event cursor:
Idempotency correlation label or fingerprint:
Client/SDK name and version:
Never attach API secrets, passphrases, private/session keys, seed phrases, raw authentication headers, signatures, cookies, or private request bodies. Redact wallet, account, order, and IP identifiers unless support explicitly needs one to locate the correlated server log.
Account-read workaround during freshness rollout
The explicit freshness fields are not yet available on production. Until the server returns them and public readback is verified, use this workflow:
- Keep the terminal receipt or private execution event for the write.
- Request
GET /api/v1/accounts/{account}/bootstrap?fresh=trueusing the 20-byte engine account. - Compare
asOf, nonce, balances, open orders, and available projection metadata with the event being reconciled. - If the view has not caught up, wait with jitter and repeat the read. Do not place from the older view and do not manufacture a new nonce from it.
- Escalate with both request ids and the receipt/event cursor if the view does not advance.
See Account freshness and reconciliation for the full boundary.