Get 0Pools transaction status
GET /pools/transactions/{quoteId} - Poll a trade by quote id; this poll advances settlement and surfaces the post-settlement returned state.
0Pools API pages are for approved headless partners. They cover the partner-visible quote, transact, status, trade, and balance lifecycle only.
Endpoint
| Field | Value |
|---|---|
| Method | GET |
| Path | /pools/transactions/{quoteId} |
| Area | Trades |
| Operation id | getTransactionByQuote |
| Auth boundary | Secret key from your server. |
Use it for
Poll a reserved trade by quote id and drive it to a terminal state.
Use this endpoint only for the partner-scoped resource it describes. Store your own reference id, the returned 0Bit object id, the request id, timestamps, and the current status so support and reconciliation do not depend on browser callbacks alone.
This poll moves the trade forward
This is the intended, idempotent way to progress a reserved trade. Each poll advances settlement — it is safe to call repeatedly, and it never double-settles. After POST /pools/{id}/transact returns reserved, keep polling this endpoint until the trade reaches a terminal state.
This poll advances settlement
A reserved trade does not progress on its own. Calling GET /pools/transactions/{quoteId} is the mechanism that advances a reserved trade toward settled, failed, or released. The operation is idempotent: a trade that is already terminal stays terminal, and concurrent polls converge on the same state.
This is the key distinction from the trade read endpoints:
| Endpoint | Behavior | Use it to |
|---|---|---|
GET /pools/transactions/{quoteId} | Advances settlement. Idempotent driver of a reserved trade. | Progress a reserved trade and detect its terminal state. |
GET /pools/trades/{transactId} | Pure read. Returns current state, does not advance. | Display or reconcile a trade you already have an id for. |
GET /pools/trades | Pure read. Cursor-paginated list, does not advance. | Backfill and reconcile across many trades. |
Transaction status values
status is the machine-readable field to branch on. PoolTxnStatus has five lifecycle values plus the post-settlement returned terminal state.
| Status | Terminal | Meaning |
|---|---|---|
quoted | No | A quote is locked but has not been executed into a trade yet. |
reserved | No | The trade is executing. Balance is reserved and settlement is in progress. Keep polling to advance it. |
settled | Yes* | Settlement completed. On-ramp crypto was delivered to the locked destination, or the off-ramp payout was issued. |
released | Yes | The reservation was released without settling and any reserved value returns to your balance. |
failed | Yes | The trade did not settle. No delivery or payout occurred. |
returned | Yes | A previously settled trade was reversed downstream and auto-refunded. See below. |
* settled is terminal for the settlement lifecycle, but a settled trade can still flip to returned afterward. Do not treat settled as the end of reconciliation.
Branch on status. Do not parse the free-form message or infer state from HTTP status alone.
The returned state
After a trade reports settled, it can later transition to returned when the delivered value is rejected downstream:
- a SEPA payout returned by the receiving bank, or
- a crypto delivery that failed downstream after settlement.
When this happens, 0Pools performs an automatic, idempotent refund of the trade value back to your partner balance. The refund appears as a credit in GET /pools/ledger, and the trade's status becomes returned on this poll.
Poll and reconcile for returned — there is no webhook
The returned state is surfaced through this status poll only. There is no pool.transaction.returned webhook. The three terminal webhook events (pool.transaction.settled, .failed, .released) fire before a return can occur, so a webhook-only integration will miss returns and the matching refunds. After a trade settles, keep polling this endpoint (or reconcile against GET /pools/ledger) so you catch a returned flip and its auto-refund.
Request
curl https://pools-api.0bit.app/v1/pools/transactions/quote_test_123 \
-H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"No request body. The quoteId path parameter is the id returned by POST /pools/{id}/quote and echoed by POST /pools/{id}/transact. The lookup is partner-scoped: a quoteId that belongs to another partner returns 404, never 403.
Every response carries an X-Request-Id header. Capture it for support and reconciliation.
Response
{
"transactId": "txn_test_456",
"quoteId": "quote_test_123",
"status": "reserved",
"poolId": "pool_test_123",
"side": "on_ramp",
"createdAt": "2026-01-01T12:00:00Z",
"settledAt": null
}Keep polling. The trade is still executing.
{
"transactId": "txn_test_456",
"quoteId": "quote_test_123",
"status": "settled",
"poolId": "pool_test_123",
"side": "on_ramp",
"createdAt": "2026-01-01T12:00:00Z",
"settledAt": "2026-01-01T12:02:00Z"
}Settlement completed. Continue to reconcile in case the trade later flips to returned.
{
"transactId": "txn_test_456",
"quoteId": "quote_test_123",
"status": "returned",
"poolId": "pool_test_123",
"side": "on_ramp",
"createdAt": "2026-01-01T12:00:00Z",
"settledAt": "2026-01-01T12:02:00Z"
}The settled value was reversed downstream. An idempotent refund has been credited to your balance — confirm it as a credit entry in GET /pools/ledger.
This status poll is lean: it returns the trade's identity, side, machine-readable status, and timestamps only. Money and rate values (fiatAmount, cryptoAmount, quotedRate, feeBps, spreadBps) live on the trade view — read them from GET /pools/trades/{transactId}, not here. Examples use fake placeholder ids.
Errors
Errors use the unified envelope { type, code, message, request_id, doc_url, statusCode }, and every response includes an X-Request-Id header that mirrors request_id. Branch on type and code, not on message.
| Status | type | When | Handling |
|---|---|---|---|
401 | unauthorized | Missing or invalid key. | Fix credentials. |
403 | forbidden | Wrong key mode: code is key_mode_mismatch. This is a secret-key-only route, so a pk_* is rejected here as 403, not 401. The pool-access denial codes do not apply. | Call with your sk_*; do not retry until the key mode is fixed. |
404 | not_found | Unknown quoteId, or a quoteId outside your tenant. | Check the id and ownership; do not expose foreign ids. |
429 | rate_limited | Throttle reached. | Back off and retry with jitter. Poll on a steady interval, not a tight loop. |
5xx | server_error | Transient upstream failure. | Retry the poll with backoff; the operation is idempotent. |
Cross-tenant lookups return 404, not 403
A poll for a quoteId that belongs to another partner returns 404. The API never confirms the existence of objects outside your own scope. Do not infer ownership from the status code, and do not surface foreign ids.
Common mistakes
| Ref | Mistake | Do instead |
|---|---|---|
WRONG-004 | Polling GET /pools/trades/{transactId} (a pure read) and expecting a reserved trade to move forward. It never advances settlement, so the trade appears stuck. | Poll GET /pools/transactions/{quoteId} to advance a reserved trade. Use the trade read endpoints only for display and reconciliation. |
MISS-004 | Relying on webhooks to learn about returned. There is no returned webhook, so the reversal and its auto-refund are silently missed. | Keep polling this endpoint after settled, and reconcile credits from GET /pools/ledger, so you catch a returned flip. |
Production rules
- Keep secret keys on your server.
- Validate environment, mode, entitlement, asset, network, and amount before the call.
- Drive reserved trades with this poll; treat the trade read endpoints as non-advancing.
- Keep polling after
settledand reconcile the ledger so areturnedflip is never missed. - Branch on machine-readable status, error code, object id, and request id.
- Treat examples and placeholder ids as fake data only.
Public boundary
This reference covers partner-visible discovery, quote, transact, status, trade, and balance behavior. Liquidity operations, routing internals, provider details, reserve logic, and runbooks are outside the public API contract.