Retrieve a 0Pools quote
GET /pools/quotes/{quoteId} - Read a quote and its derived status without consuming or extending it.
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/quotes/{quoteId} |
| Area | Quotes |
| Operation id | getQuote |
| Auth boundary | Secret key from your server. |
Use it for
Retrieve a previously created firm quote and read its current derived status without consuming, extending, or re-pricing it.
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.
Firm quotes only
Only firm quotes are persisted and addressable by quoteId. Indicative quotes are price-only, are never assigned a
quoteId, and are not retrievable here. A quoteId that is unknown to your partner scope returns 404.
Path parameters
| Parameter | In | Type | Description |
|---|---|---|---|
quoteId | path | string | The id returned by POST /pools/{id}/quote for a firm quote. |
This call is a pure read
Retrieving a quote does not change it. It does not consume the quote, extend its expiry, re-price it, or move any money. Use it to confirm whether a stored quote is still actionable before you transact, or to reconcile a quote after the fact.
To execute a quote, call POST /pools/{id}/transact. To explicitly decline one, call POST /pools/quotes/{quoteId}/reject.
Derived status
The response carries a status that 0Pools derives from the quote's lifecycle at read time. A freshly created firm quote is active. It then resolves into exactly one terminal state.
| Status | Meaning | How it is reached |
|---|---|---|
active | Still locked and executable until expiresAt. | Created and not yet transacted, rejected, or expired. |
consumed | Already executed; a trade was created against this quote. | POST /pools/{id}/transact succeeded for the quote. |
expired | The short time-to-live elapsed before any transact or reject. | Read happens after expiresAt with no transact or reject. |
rejected | Explicitly declined and permanently unusable. Distinct from consumed. | POST /pools/quotes/{quoteId}/reject was called. |
Status precedence
When more than one condition applies, the highest-precedence state wins:
rejected > consumed > expired > active. A quote that was rejected reads as rejected even if its
expiresAt has since passed, and a quote that was transacted reads as consumed even if it is now past expiry. Branch
on status, not on the wall clock.
Response fields
Money and rate values are decimal strings. Basis-point fields are integers. fiatAmount and cryptoAmount are the two legs of the quote: for on_ramp the customer pays fiatAmount to receive cryptoAmount; for off_ramp the customer sells cryptoAmount to receive fiatAmount.
| Field | Type | Description |
|---|---|---|
quoteId | string | Stable id that joins quote, trade, status, and reconciliation records. |
poolId | string | The pool this quote was priced against, for example EUR-USDT. |
pair | string | The pool pair, for example EUR/USDT. |
side | string | on_ramp or off_ramp. |
cryptoNetwork | string | The chain the trade transacts on, locked on the quote (tron, ethereum, bsc, polygon, or solana). |
fiatAmount | string | Fiat leg of the quote (decimal string). |
cryptoAmount | string | Crypto leg of the quote (decimal string). |
rate | string | Locked rate as output-per-input (decimal string). |
spreadBps | integer | Spread component, in basis points. |
feeBps | integer | Fee component, in basis points. |
status | string | Derived status: active, consumed, expired, or rejected. |
expiresAt | string | RFC 3339 timestamp when the lock ends (firm quotes are short-lived, roughly 15 seconds). |
consumedAt | string | null | RFC 3339 timestamp when the quote was transacted, or null if it was not consumed. |
rejectedAt | string | null | RFC 3339 timestamp when the quote was rejected, or null if it was not rejected. |
createdAt | string | RFC 3339 timestamp when the quote was created. |
The crypto network is locked on the quote
cryptoNetwork is fixed when the quote is created and selects the pool the trade transacts on. It is never re-read from
the transact body. Branch on status to decide whether the quote is still actionable; there is no executable flag on
this response.
Request
curl -X GET https://pools-api.0bit.app/v1/pools/quotes/quote_test_abc123 \
-H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"Response examples
{
"quoteId": "quote_test_abc123",
"poolId": "EUR-USDT",
"pair": "EUR/USDT",
"side": "on_ramp",
"cryptoNetwork": "tron",
"fiatAmount": "100.00",
"cryptoAmount": "93.09",
"rate": "1.0742",
"spreadBps": 45,
"feeBps": 20,
"status": "active",
"expiresAt": "2026-06-28T14:32:15Z",
"consumedAt": null,
"rejectedAt": null,
"createdAt": "2026-06-28T14:32:00Z"
}{
"quoteId": "quote_test_abc123",
"poolId": "EUR-USDT",
"pair": "EUR/USDT",
"side": "on_ramp",
"cryptoNetwork": "tron",
"fiatAmount": "100.00",
"cryptoAmount": "93.09",
"rate": "1.0742",
"spreadBps": 45,
"feeBps": 20,
"status": "consumed",
"expiresAt": "2026-06-28T14:32:15Z",
"consumedAt": "2026-06-28T14:32:08Z",
"rejectedAt": null,
"createdAt": "2026-06-28T14:32:00Z"
}{
"quoteId": "quote_test_abc123",
"poolId": "EUR-USDT",
"pair": "EUR/USDT",
"side": "on_ramp",
"cryptoNetwork": "tron",
"fiatAmount": "100.00",
"cryptoAmount": "93.09",
"rate": "1.0742",
"spreadBps": 45,
"feeBps": 20,
"status": "expired",
"expiresAt": "2026-06-28T14:32:15Z",
"consumedAt": null,
"rejectedAt": null,
"createdAt": "2026-06-28T14:32:00Z"
}{
"quoteId": "quote_test_abc123",
"poolId": "EUR-USDT",
"pair": "EUR/USDT",
"side": "on_ramp",
"cryptoNetwork": "tron",
"fiatAmount": "100.00",
"cryptoAmount": "93.09",
"rate": "1.0742",
"spreadBps": 45,
"feeBps": 20,
"status": "rejected",
"expiresAt": "2026-06-28T14:32:15Z",
"consumedAt": null,
"rejectedAt": "2026-06-28T14:32:05Z",
"createdAt": "2026-06-28T14:32:00Z"
}Errors
Every error uses the unified envelope { type, code, message, request_id, doc_url, statusCode }, and every response carries an X-Request-Id header. Branch on type and code, not on the human-readable message.
| Status | type | When |
|---|---|---|
401 | unauthorized | Missing or invalid secret key. |
403 | forbidden | Wrong key mode (code is key_mode_mismatch). This is a secret-key-only route with no entitlement check, so the pool-access denial codes do not apply here. |
404 | not_found | Quote id is unknown, is indicative (never persisted), or belongs to another partner. |
Cross-tenant reads return 404, never 403
Quotes are partner-scoped. A quoteId that exists but belongs to a different partner is reported as 404 not_found,
identical to a quote id that never existed. 0Pools never confirms the existence of another partner's resource and never
returns 403 to signal ownership. Do not surface foreign or guessed quote ids to end users.
{
"type": "not_found",
"code": "not_found",
"message": "Quote not found.",
"request_id": "req_test_9f2c1a",
"doc_url": null,
"statusCode": 404
}Production rules
- Keep secret keys on your server.
- Validate environment, mode, entitlement, asset, network, and amount before the call.
- Branch on the machine-readable
status, errorcode, object id, and request id; never derive expiry from the clock whenstatusalready tells you. - Treat any non-
activestatus as final for that quote: request a fresh quote rather than retrying the same 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.