Skip to main content

Ids and correlation

Every v2 resource exposes an id, and that same value both re-fetches it and locates it in the ledger. This page is the whole contract: what id each resource returns, and how to hop between them.

The rule, in one line

A withdrawal's, deposit's or fill's id is exactly the value its ledger entry publishes as source.id.

Which is why you never scan the ledger looking for something — you filter by it.

Resources and their ids

ResourceidRe-fetch it with
Withdrawalwithdrawal idGET /v2/withdrawals/{id}
Depositdeposit idGET /v2/deposits/{id}
Orderorder id (your client order id)GET /v2/orders/{id}
Fillfill idGET /v2/fills?orderId=…
Ledger entryentry idGET /v2/ledger/{id}

The ledger points back

Every GET /v2/ledger entry carries a source object naming what caused it:

{
"id": "lm_998877",
"source": { "type": "withdrawal", "id": "wd_123" },
"type": "WITHDRAWAL",
"subType": "EXTERNAL_CRYPTO",
"assetSymbol": "USDT",
"amount": "150",
"fee": "0.5",
"total": "150.5",
"balance": "849.5",
"createdAt": "2026-07-09T14:11:05.501Z"
}

source.type is one of withdrawal, deposit, fill or other, and source.id is that resource's id. It is the same pattern as Stripe's balance_transaction.source.

The hops you will actually make

From a withdrawal or deposit to its ledger entries

GET /v2/ledger?assetSymbol=USDT&sourceId=wd_123

One call. sourceId filters on the same value the resource publishes as its id.

From an order to every entry it produced

An order is completed by 1..N fills, and each fill books ledger entries. Rather than chaining requests, the orderId filter resolves the whole chain for you:

GET /v2/ledger?assetSymbol=CLP&orderId=clord_01H…
An order settles in two assets

A conversion moves two assets (say BTC and CLP), and assetSymbol is required on the ledger: it selects which leg you are looking at. To see both, make one call per asset.

From an order to its fills

GET /v2/orders/{id}/fills # nested
GET /v2/fills?orderId={id} # equivalent, filtering the global collection

Both return the same resource. Both exist because Coinbase and Binance both have them and different clients reach for different ones. Both are cursor-paginated.

From a fill back to its order

A fill carries orderId, and also embeds the order's cumulative state so you do not have to re-read the order after every execution:

{
"id": "1096473",
"orderId": "clord_01H…",
"sequence": 2,
"side": "BUY",
"market": "BTC-CLP",
"baseAmount": "0.004",
"quoteAmount": "260000.00",
"rate": "65000000.00",
"multiplier": "1",
"onCredit": true,
"executedAt": "2026-07-09T14:07:11.000Z",
"order": {
"status": "PARTIALLY_FILLED",
"filledBaseAmount": "0.008",
"filledQuoteAmount": "520000.00"
}
}

sequence is the fill's position within its order, starting at 1.

Orders and fills

An order is what you create by confirming a quote. A fill is each execution against it.

  • A normal conversion → exactly one fill.
  • An on-credit order (onCredit: true) → several fills, as the debt is paid down.

That is why filledBaseAmount can sit below baseAmount for a while, and why the fill.created webhook can arrive more than once for the same orderId.

Amount conventions

ConventionWhat it means
Positive magnitudesamount, fee and total are always positive on every resource. Direction comes from the resource type or the entry's type, never from the sign.
balance IS signedIt is a state (the balance after the entry), not a movement, so it is not converted to a magnitude.
UPPERCASEstatus, type, subType and side are always uppercase: FILLED, WITHDRAWAL, EXTERNAL_CRYPTO, BUY.
Decimals as stringsAmounts travel as strings so no precision is lost. Parse them with a decimal type, never a float.