Skip to main content
v1 sunsets December 31, 2026. Migrate to v2 — see the migration guide.
What this is. Every non-2xx response from the v1 API wrapped in a single, flat error envelope, plus the exact message strings v1 servers return today. When it matters. Anywhere your client branches on error responses. v1 has no machine-readable code field — clients that need to react to specific failures have to string-match against message, so knowing the exact strings matters. What you’ll learn. The v1 envelope shape, the three errors you’ll see on essentially every endpoint, the handful of endpoint-specific messages on writes, why a few endpoints surface 409/422 in the spec that no v1 server ever returns, and where to go for a stable code catalog.

Response shape

v1 wraps every error — regardless of HTTP status — in a flat two-field envelope:
There is no error.code, no error.type, no details, and no nested error object. Those are v2 / v3 features. If your v1 client needs to branch on a specific failure mode, you have to compare message against the exact strings catalogued below. The other consequence is that message is the only signal — status is always the literal "error" on failure, so it only tells you “this isn’t a 2xx body.”
Switching on message is brittle by design. Any copy edit to the underlying string will silently break your client. v3 introduces a stable error.code field for exactly this reason — see Migrating off these messages.

Common errors

Almost every v1 endpoint returns the same three failures. If you handle these and nothing else, you cover the majority of real-world cases.

Endpoint-specific errors

A small set of v1 write endpoints return more specific 400 messages on top of the common three. These are the only deviations from the table above. Strings are verbatim from the v1 OpenAPI spec, including the punctuation and the "withdraw." typo that has shipped in production since the v1 GA.

POST /v1/brokerage/{orgId}/withdrawal — Initiate stablecoin withdrawal

POST /v1/brokerage/{orgId}/fiat_withdrawal — Initiate fiat withdrawal

POST /v1/brokerage/{orgId}/generate_quote — Generate quote

POST /v1/brokerage/{orgId}/trade/reverseReverse a trade

POST /v1/brokerage/{orgId}/trade/reverse-quoteGenerate a reverse quote

POST /v1/brokerage/{orgId}/trade/settleSettle a trade

Why v1 lacks idempotency error codes

v1 does not support Idempotency-Key. Callers will never see IDEMPOTENCY_IN_FLIGHT (409), IDEMPOTENCY_MISMATCH (422), or IDEMPOTENCY_KEY_REQUIRED (400) responses from a v1 server, regardless of whether the request supplies an Idempotency-Key header. The v1 OpenAPI spec lists 409 and 422 responses — and, on the trade-reversal endpoints, a nested error.code on some example bodies — as leftover boilerplate from a shared error schema also used by v2 and v3 (GET /balances, POST /trade, POST /trade/reverse, POST /trade/reverse-quote, POST /trade/settle). None of that is enforced by the v1 server: real v1 responses stay in the flat {status, message} envelope described above, and you can ignore both the idempotency status codes and any error.code the spec shows for these operations. To get real idempotency semantics and structured error codes, migrate to v2 or v3 — see Migration from v1 to v2.

Migrating off these messages

Because v1 has no error.code, every branch in your v1 client has to string-match message. That string is the API contract today, but it’s not part of any stability guarantee — a future v1 copy edit could rephrase any of the messages above. v3 fixes this by wrapping every error in a stable, machine-readable envelope:
Clients switch on error.code and treat message as human-readable copy. Codes are namespaced (<PRODUCT>_<ERROR>) and never renamed within a major version. The full v3 code catalog — including the codes that map back to each v1 message above — is at /v3/errors.