0Bit Documentation

Reject a 0Pools quote

POST /pools/quotes/{quoteId}/reject - Decline a quote so it cannot be transacted.

0Pools API pages are for approved headless partners. They cover the partner-visible quote, transact, status, trade, and balance lifecycle only.

Endpoint

FieldValue
MethodPOST
Path/pools/quotes/{quoteId}/reject
AreaQuotes
Operation idrejectQuote
Auth boundarySecret key from your server.

Use it for

Explicitly decline a locked quote so it can never be transacted. Call this when the user dismisses the offer, lets your accept window lapse, or chooses a different route, and you want the quote put into a terminal rejected state rather than left to expire on its own.

Rejecting is money-free: nothing is reserved, debited, or delivered. It is a small piece of hygiene that makes reconciliation unambiguous, because the quote ends in a clear partner-visible state instead of an open lock that later silently expires.

Rejected is its own terminal state

A rejected quote is distinct from a consumed (transacted) quote. Reject sets the quote to rejected; transact moves it to a consumed trade. When a quote's derived status is read back, rejected takes precedence over consumed, expired, and active.

Production rules

  • Keep secret keys on your server.
  • Reject from your backend only; never expose this call or the quote id to the browser.
  • Reject is not idempotent: a second reject of an already consumed, rejected, or expired quote returns 409 conflict. Read state back before retrying.
  • Branch on machine-readable status, error code, object id, and request id.
  • Treat examples and placeholder ids as fake data only.

Request

No request body is required. Authenticate with your secret key and address the quote by its id in the path. No Idempotency-Key is used: reject is a compare-and-swap that succeeds exactly once, so a repeat against a quote that is already consumed, rejected, or expired returns 409 conflict rather than re-confirming the prior state.

curl -X POST https://pools-api.0bit.app/v1/pools/quotes/quote_test_123/reject \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ParameterInRequiredDescription
quoteIdpathyesThe quote id returned by POST /pools/{id}/quote (firm only).

Indicative quotes are price-only and are never persisted, so they have no quoteId and cannot be rejected. Only firm quotes can be rejected.

Response

A successful call returns the full partner-visible quote object, identical to GET /pools/quotes/{quoteId}, with status now rejected and rejectedAt set to the time of the reject. Money and rate values are decimal strings; *Bps fields are integers. Store the status, the object id, and the X-Request-Id response header alongside your own reference for reconciliation.

{
  "quoteId": "quote_test_123",
  "poolId": "pool_test_123",
  "pair": "EUR-USDT",
  "side": "on_ramp",
  "cryptoNetwork": "tron",
  "fiatAmount": "100.00",
  "cryptoAmount": "108.20",
  "rate": "1.0820",
  "spreadBps": 25,
  "feeBps": 10,
  "status": "rejected",
  "expiresAt": "2026-06-28T12:00:15Z",
  "consumedAt": null,
  "rejectedAt": "2026-06-28T12:00:05Z",
  "createdAt": "2026-06-28T12:00:00Z"
}

Conflict on repeat

Reject is a one-shot compare-and-swap, not an idempotent operation. The first call sets the quote to rejected (and stamps rejectedAt); a second reject of a quote that is already consumed, rejected, or expired returns 409 conflict. Treat the conflict as authoritative: the quote already reached a terminal state, so refresh it with GET /pools/quotes/{quoteId} instead of retrying blindly.

Because rejected is terminal, a quote in this state cannot be transacted. A POST /pools/{id}/transact against a rejected quote also returns 409 conflict; refresh state instead of retrying blindly.

Status precedence

When you read a quote back with GET /pools/quotes/{quoteId}, its status is derived. If more than one terminal condition could apply, the resolved status follows this order:

PrecedenceStatusMeaning
1 (highest)rejectedThe quote was explicitly declined.
2consumedThe quote was transacted into a trade.
3expiredThe quote's short TTL elapsed without being used.
4 (lowest)activeThe quote is still live and within its TTL.

Errors

All errors use 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.

StatustypeWhen it happens
401unauthorizedMissing or invalid secret key.
403forbiddenWrong key mode. This route is secret-key only and runs no entitlement check, so the only code here is key_mode_mismatch (for example, a publishable key was used). The pool-access denial codes do not apply.
404not_foundThe quote id is unknown, or belongs to another partner. Cross-tenant access returns 404, never 403.
409conflictThe quote is already terminal — consumed, rejected, or expired — so it cannot be rejected again. This is this endpoint's defining error.
429rate_limitedRequest throttle exceeded.
{
  "type": "conflict",
  "code": "conflict",
  "message": "Quote is no longer active and cannot be rejected.",
  "request_id": "req_test_abc123",
  "doc_url": null,
  "statusCode": 409
}

There is no quote.rejected webhook. Rejection is observed through this response and through GET /pools/quotes/{quoteId}. Webhooks fire only for terminal trade events.

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.

On this page