Quote, Trade, Deposit, Withdrawal, WithdrawalAccount, Account, FinancialAccount, PayoutAddress, PayoutQuote, Payout, AccountCapability) carries an id that the server assigns at creation, plus an object field naming the resource type. IDs are readable: a lowercase 3-to-6-letter prefix identifies the resource type, followed by a Base58 encoding of the underlying 128-bit UUID. Two fields in v3 reference these IDs across resources: quoteId on a trade points at a Quote.id, and withdrawalAccountId on a withdrawal points at a WithdrawalAccount.id.
v3 emits readable IDs on every response. Bare UUIDs never appear in a v3
response body; the readable ID is the public identifier. For backward
compatibility, v3 accepts either a readable ID or a bare UUID v4 wherever
an ID is expected on input (path parameters, query parameters, and
request-body foreign keys); both decode to the same underlying record. New
integrations should use the readable form returned by the API.
Format
<prefix>_<base58(uuid)>: a lowercase 3-to-6-letter type prefix, an underscore, and the Base58 encoding of the resource’s 128-bit UUID.
Pair and Balance have no resource UUID. A pair is identified by its (buyCurrency, sellCurrency) combination, and a balance by currency, not by an id field.
- The Base58 alphabet excludes
0,O,I, andlto avoid visual ambiguity:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz. - The encoded body is at most 22 characters and is not a fixed length: 21–22 characters for a typical random UUID, shorter only for near-zero values (the nil UUID encodes to 16 characters).
- Regex pre-filter:
^[a-z]{3,6}_[1-9A-HJ-NP-Za-km-z]{1,22}$. This is a loose shape check; the authoritative validation is a successful decode back to exactly 16 bytes. A value that matches the regex but doesn’t decode to 16 bytes is rejected the same as a malformed ID. The payments operations are stricter: their specification pins each ID to its own prefix (for examplepyt_oracc_) and a body of 21 or 22 characters, so a short body that passes the regex fails validation there. Use IDs exactly as the API returned them. - Base58 is case-sensitive. There is no case normalization: a mis-cased but otherwise well-formed ID decodes to a different value (or fails to decode) and is rejected.
400 VALIDATION_QUERY_FAILED (query and body) or 400 VALIDATION_PATH_FAILED (path parameters).
Stability
- IDs are permanent. Once issued, the underlying UUID never changes and never gets reused, so its readable encoding doesn’t either.
- Safe to store as foreign keys in your database. Index the readable ID, the underlying UUID, or both, depending on what your queries need.
- Safe to log in audit trails. IDs carry no PII: the prefix reveals only the resource type, and the body is an opaque, lossless encoding of the UUID.
- Safe to share in support tickets and idempotency-key collision reports.
Cross-resource references
Some fields are foreign keys pointing at IDs on other resources. The table below lists every such reference in v3:
Anything else that looks like an ID (a transaction hash, a currency code) is not a foreign key into another v3 resource.
ID vs Idempotency-Key
Two ID-shaped fields in v3 serve different purposes:
The two are complementary: you generate an idempotency key before the request, the server returns a resource ID in the response, and you persist both alongside each other. The idempotency key lets you safely retry the write; the resource ID lets you look up the result for the rest of time. See Idempotency → Crash recovery for the persist-both pattern.
Common mistakes
- Treating IDs as transient. They aren’t. Persist them.
- Parsing or decoding the readable ID yourself. The prefix tells you the resource type; don’t try to derive anything else from the body. Treat the body as an opaque string, even though it happens to be reversible server-side.
- Reading the
idfrom your own DB row instead of the API response on a write. If you assigned an identifier locally and sent it as the request body, that’s not the resource ID. The server generates its own. Always trust the response, not your draft. - Confusing
quoteIdwithIdempotency-Keyon the trade execution call.quoteIdgoes in the JSON body,Idempotency-Keygoes in the header. They’re unrelated. - Storing only the readable ID and losing the ability to index efficiently. Both the readable ID and its underlying UUID identify the same record. Store whichever shape fits your schema, or both.
- Assuming a hardcoded body length. The encoded body is at most 22 characters but isn’t fixed-width. Validate by prefix and successful decode, not by string length.
What’s next
Idempotency
Client-generated keys vs server-generated IDs.
Pagination
Opaque cursors, distinct from resource IDs. Pass them back verbatim.
Errors
When you’ll see
*_NOT_FOUND and how to handle it.