0Bit Documentation

Reconcile pool movements

How to join 0Pools quotes, trades, balances, webhooks, request ids, and partner orders into a finance-safe ledger.

Reconciliation is the production backbone of a 0Pools integration. A user flow is not complete until your system can explain the movement from internal order to quote, trade, terminal status, and ledger entry.

Reconciliation graph

Join keys

KeyPurpose
Partner order idYour product's source of truth.
Pool idShows which liquidity lane was used.
Quote idLinks quote, execution, status, and support.
Transact idIdentifies the trade.
Idempotency keyExplains duplicate accept/retry behavior.
Request idLets 0Bit trace API calls.
Webhook event idLets you dedupe terminal events.
Ledger refLinks balance movement to quote/trade.

State mapping

0Pools statusPartner ledger action
Quote activeNo final ledger movement.
ReservedPending hold or pending internal entry.
SettledFinalize debit/credit according to flow.
FailedReverse pending state or open support case.
ReleasedRemove hold and allow retry.
ReturnedReverse/review completed entry.

Webhook handler pattern

  1. Verify signature over raw body.
  2. Dedupe by event id.
  3. Load the trade/order by quote or transact id.
  4. Compare event status with current order state.
  5. Apply only legal forward state transitions.
  6. Store event payload reference and request metadata.
  7. Return 2xx quickly.

Example reconciliation table

ColumnExample
order_idorder_123
pool_idEUR-USDT
quote_idpq_test_123
transact_idtxn_test_456
statussettled
fiat_amount100.00
crypto_amount107.31
request_idreq_...
event_idevt_...

Anti-patterns

  • Reconciling by amount alone.
  • Treating browser success as settlement.
  • Dropping request ids.
  • Overwriting terminal states without audit.
  • Logging webhook secrets or secret keys.

Reconciliation close process

Do this as a batch/reporting process as well as in real-time product code. Real-time code keeps users informed; reconciliation proves the records agree after events, retries, and terminal statuses settle.

Example exception types

ExceptionMeaningFirst action
Missing quotePartner order never received or stored a quote id.Check server logs and request id.
Missing tradeUser may not have accepted, quote expired, or transact failed.Retrieve quote/trade by id if available.
Duplicate trade attemptRetry or double-click path may be wrong.Check idempotency key and conflict response.
Missing webhookDelivery issue or endpoint failure.Poll trusted read and inspect delivery logs.
Ledger mismatchBalance movement does not match expected trade state.Compare ledger ref, quote id, trade id, and amount strings.
Terminal state conflictProduct moved backward or overwrote a final state.Freeze order and review state transition audit.

Before and after

Before 0PoolsWith 0Pools reconciliation
Finance matches by amount and date.Finance matches by order, quote, trade, ledger, event, and request ids.
Browser success can be mistaken for settlement.Terminal status and ledger rows drive final accounting.
Support asks engineering to search provider dashboards.Support starts from structured support packets.
Returned or released funds are handled manually.Return/release states can be represented and reviewed.

Minimal database shape

{
  "order_id": "order_123",
  "environment": "live",
  "pool_id": "EUR-USDT",
  "quote_id": "pool_quote_123",
  "trade_id": "pool_trade_456",
  "idempotency_key": "order_123:accept:v1",
  "latest_status": "settled",
  "ledger_ref": "pool_trade_456",
  "last_event_id": "evt_789",
  "last_request_id": "req_abc"
}

Store enough to reconstruct the history. A single mutable status column without event and request references is not enough for production finance review.

Finance close artifacts

A finance-grade reconciliation process needs exportable artifacts, not only dashboard state.

ArtifactColumns
Order exportpartner_order_id, user reference, created time, product state.
Quote exportquote_id, pool id, source amount, target amount, expiry, accepted time.
Trade exporttransact_id, quote id, idempotency key, current status, terminal time.
Event exportevent id, transact id, status, received time, processed time.
Ledger exportledger id, trade id, entry type, asset, amount, effective time.

Sample exception query

select
  t.transact_id,
  t.quote_id,
  t.status,
  l.ledger_entry_id
from pool_trades t
left join ledger_entries l on l.transact_id = t.transact_id
where t.status in ('settled', 'returned', 'released')
  and l.ledger_entry_id is null;

Close checklist

  • Every terminal trade has a ledger entry or approved exception.
  • Every ledger entry joins to a trade, quote, and partner order.
  • Amounts are compared as exact decimal strings/minor units.
  • Webhook gaps are reconciled with trusted status reads.
  • Exceptions have owners and next review dates.

Implementation depth

This page is about joining quotes, trades, balances, webhooks, and partner ledger records. For developers, the durable boundary is simple: your product should depend on ids, statuses, event ids, amounts, timestamps, and ledger entries; it should not depend on internal settlement worker details and provider reconciliation files. That boundary is what lets 0Pools improve liquidity operations without forcing every partner to rebuild product code.

Product scenario

At daily close, finance joins partner orders to quote ids, trade ids, terminal events, and balance ledger entries. Anything unmatched becomes an exception with a clear next action.

Before and after in practice

Before 0PoolsWith 0Pools
Finance compares exports by amount and timestamp, which fails when retries or returns occur.Finance reconciles by durable ids and terminal state, with exceptions isolated by type.
Product teams infer liquidity behavior from provider-specific screens or manual notes.Product teams branch on 0Pools objects: pool, quote, trade, balance, webhook, and ledger.
Support asks engineering to reconstruct state from logs.Support starts from request id, quote id, trade id, event id, and ledger id.

System flow

Records to keep

RecordWhy it mattersExample
order_idYour product order.order_123
quote_idAccepted terms.pq_test_123
transact_idExecution record.pt_test_456
event_idWebhook event processed.evt_789
ledger_entry_idFinance posting.led_101

A useful implementation stores these records before adding optional analytics. Analytics can be rebuilt from durable state; missing ids usually cannot be reconstructed after a customer-impacting failure.

Example product record

{
  "product_area": "reconcile-pool-movements",
  "partner_reference": "partner_order_123",
  "pool_id": "EUR-USDT",
  "quote_id": "pq_test_123",
  "transact_id": "pt_test_456",
  "status": "reserved",
  "request_id": "req_01HZY0POOLS",
  "reconciliation_state": "open"
}

This record is intentionally partner-facing. It references 0Pools objects and your own product ids, but it does not include private liquidity routes, treasury balances, raw provider payloads, or customer secrets.

Failure modes and recovery

Failure modeProduct response
Amount-only matchingUse ids first, amounts second.
Webhook without ledger rowQueue an exception.
Ledger row without terminal tradeHold close until status resolves.
Returned trade ignoredPost return adjustment.

Use-case patterns

PatternHow 0Pools helps
Daily finance closeProduce a matched movement report.
Support investigationTrace one user order end to end.
Audit exportShow immutable ids and timestamps.

Developer checklist

  • Read runtime discovery and capabilities before rendering enabled actions.
  • Create firm quotes only when the user is ready to accept the terms.
  • Execute from your server with an idempotency key.
  • Treat webhooks and status reads as the source of truth for settlement state.
  • Reconcile by durable ids first, then by amount and timestamp.
  • Do not branch product behavior on provider names, route names, reserve balances, or treasury assumptions.

On this page