Core concepts
The 0Pools object model: pools, entitlements, sides, networks, quotes, trades, balances, statuses, and webhooks.
0Pools has a small set of concepts, but they must stay separate. Mixing them is how integrations accidentally create stale prices, duplicate executions, or unreconciled balances.
Concept map
Pool
A pool is a partner-visible liquidity lane, normally expressed as a fiat/stablecoin pair such as EUR-USDT. A pool id is only meaningful inside the authenticated partner context.
| Pool property | Meaning |
|---|---|
id | Stable id used in quote and transact paths. |
pair | Human label such as EUR/USDT. |
fiatCurrency | Fiat side of the lane. |
cryptoCurrency | Stablecoin/crypto side. |
available | Runtime availability signal, not a permanent entitlement promise. |
Entitlement
Entitlement is the account-level right to see or draw from a pool. It includes status, KYC/KYB, tier, and allowedPools.
If a partner is not entitled, the API denies closed. Do not build fallback logic that tries random pool ids.
Side
side controls direction and amount semantics.
| Side | User language | Input amount | Output amount |
|---|---|---|---|
on_ramp | Buy stablecoin/crypto with fiat. | Fiat. | Crypto. |
off_ramp | Sell stablecoin/crypto for fiat. | Crypto. | Fiat. |
The buy path is the primary public path. The sell path is account-gated and should be hidden unless explicitly enabled for the partner, pool, and environment. When sell is enabled, the integration still depends on a crypto-receipt gate: the partner sends the crypto leg to the dedicated address returned by capabilities, 0Pools credits the partner-scoped crypto balance, and fiat payout can only proceed to the approved payout destination attached to that partner.
Network
0Pools separates the network used for the pool leg from the delivery network used for a customer's wallet.
| Field | Chosen when | Why it matters |
|---|---|---|
cryptoNetwork | Quote request. | Locked onto the quote and copied to the trade. |
destAddress | On-ramp firm quote. | Customer delivery wallet, locked before execution. |
destNetwork | On-ramp firm quote. | Optional delivery network for the destination address. |
No network or delivery fields belong in transact. The quote is the authority.
Quote
Quotes price a conversion.
| Quote type | Persisted | Executable | Returns |
|---|---|---|---|
| Indicative | No | No | Price only. |
| Firm | Yes | Once | quoteId, expiry, rate, spread, fee, limits. |
Firm quote status is derived:
| Status | Meaning |
|---|---|
active | Not expired and not consumed. |
consumed | Bound to a trade. |
expired | Past TTL. |
rejected | Explicitly declined when supported. |
Trade
Executing a firm quote creates a trade. A trade is the thing your support and finance systems should reconcile, not just the quote.
Balance ledger
When prefunding is enabled, balances protect against delivering crypto before fiat is received. Ledger entries should be treated like financial audit records: immutable, tied to references, and reconciled against trades.
Webhook
Terminal webhooks can notify settled, failed, or released trades. Polling is still useful for user refresh, support, and returned-state detection.
Internal vs public concepts
| Public to partner | Internal to 0Bit |
|---|---|
| Pool id, pair, side, amount, network. | Venue account, route choice, treasury wallet. |
| Quote id, rate, spread bps, fee bps. | Market maker terms, reserve allocation. |
| Trade id, status, timestamps. | Worker internals and settlement adapters. |
| Balance and ledger entries. | Private treasury balances and rebalancing thresholds. |
Canonical object contract
Treat these objects as the vocabulary of the entire 0Pools integration. A production system should not invent parallel state names unless they map cleanly back to these records.
| Object | Created by | Mutable? | Store in partner system? | Common mistake |
|---|---|---|---|---|
| Pool | 0Pools discovery. | Yes, availability and capabilities can change. | Store id and last-seen capability snapshot. | Hard-coding a pool that later becomes unavailable. |
| Quote | Quote request. | No, terms expire instead of mutating. | Store full accepted quote response. | Repricing after the user accepted. |
| Trade | Transact call. | Status changes until terminal. | Store transact id and every status change. | Treating reserved as delivered. |
| Event | Webhook delivery. | No, process idempotently. | Store event id and signature result. | Updating ledger from unsigned events. |
| Ledger entry | Balance movement. | Append-only. | Store ledger id and linked trade id. | Rebuilding finance state from UI status. |
State transition rules
Naming discipline
Your UI may use friendly labels, but your database should keep the original 0Pools state. For example, "Processing transfer" can map to reserved, but the stored state should remain reserved so reconciliation and support do not lose precision.
Implementation depth
This page is about keeping the 0Pools object model precise. For developers, the durable boundary is simple: your product should depend on pool, entitlement, side, network, quote, trade, balance, webhook, and ledger concepts; it should not depend on implementation-specific workers, venues, adapters, and reserve mechanics. That boundary is what lets 0Pools improve liquidity operations without forcing every partner to rebuild product code.
Product scenario
A developer is designing database tables before integration. They separate quotes from trades, trades from ledger entries, and partner orders from 0Pools ids so retries and webhooks cannot corrupt accounting.
Before and after in practice
| Before 0Pools | With 0Pools |
|---|---|
| A single order row tries to represent quote preview, quote lock, execution, delivery, and finance state, making every retry ambiguous. | Each lifecycle object has a separate durable id and maps cleanly to API responses, webhooks, and finance records. |
| 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
| Record | Why it matters | Example |
|---|---|---|
quote_id | Short-lived pricing contract. | pq_test_123 |
quote_status | Shows active, consumed, or expired. | active |
trade_status | Controls UX and accounting. | reserved |
webhook_event_id | Dedupes async notifications. | evt_123 |
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": "concepts",
"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 mode | Product response |
|---|---|
| Quote treated as final trade | Only credit after trade state reaches a terminal outcome. |
| Network changed after quote | Lock destination fields on the firm quote. |
| Webhook processed twice | Dedupe by event id and trade id. |
| Pool id hard-coded | Read entitlement discovery at runtime. |
Use-case patterns
| Pattern | How 0Pools helps |
|---|---|
| Schema design | Build durable tables before coding API calls. |
| Support tooling | Give agents the exact id to search. |
| SDK wrapper | Model each concept as a separate type. |
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.