Skip to main content
A quote is a price held for a short time. It fixes an exchange rate and an amount so that you and your user both know the terms before any value moves. Every conversion starts with one: a payout or a trade. Card funding isn’t quoted: it debits your balance directly. This page explains why the window exists and how to handle it.

Why quotes expire

Bitnob quotes a rate it can honor. Between the moment you request a quote and the moment you execute it, the market moves. The expiry window sets who carries that risk. Inside the window, Bitnob carries it, because it committed to the rate. Outside the window, nobody does, so the quote is dead and you request a new one. A quote with no expiry would mean an open-ended commitment to a stale price. Any party that could wait would exercise it only when the market moved in their favor.

What a quote contains

A payout quote, as returned in data.payout by Create payout quote, trimmed to the fields that matter here:
Read expires_at from the response. Do not hard-code a window length, because it varies by product and by corridor.

The lifecycle

1

Create the quote

Call Create payout quote or Create trading quote. The response carries quote_id and expires_at.
2

Show the terms

Present settlement_amount and effective_rate to the user, with the time remaining.
3

Execute before expiry

Initialize and finalize the payout against the quote_id. See Initialize payout.
4

Confirm from the webhook

Wait for payouts.withdrawal.success before you tell the user the money arrived.
A quote you never execute simply lapses. It costs nothing and reserves nothing.

Handling expiry in your product

Show the remaining time

Users need to know they are on a clock. Derive the countdown from expires_at, not from a timer you start locally, because network latency has already consumed part of the window.

Separate looking from committing

Don’t hold a quote open while a person browses. A trading quote lasts about 10 seconds in production, so a quote created when the screen opens is usually dead by the time the user decides.
  1. While the user is browsing, show indicative rates. Use List all prices for crypto pairs and Get exchange rate for NGN pairs. They carry no commitment.
  2. Create the quote only when the user taps to commit. Show the locked amount with a countdown from expires_at, and disable Confirm when it passes.
  3. If it expires, fetch a new quote and ask the user to confirm the new rate. Don’t execute at a price they haven’t seen.
  4. Check your stored expires_at on your server before you submit the order.

Refuse to execute an expired quote

Check expires_at before you submit. Submitting an expired trading quote returns 422 with code PRECONDITION_FAILED, and the round trip wastes the user’s time. When a quote expires, request a new one and show the new terms. Never present old terms with a new quote behind them.

Re-quote rather than reuse

Prices move. A quote requested a minute ago is not a discount you can apply now, and the platform will not honor it. If your system converts a fixed amount without a person confirming each rate, for example a scheduled treasury job, you can fetch a quote in advance and refresh it as it approaches expiry:
Refresh slightly before expiry, so you never submit a dead quote. When a person is confirming, show them the refreshed terms before you execute.

Store the quote with your record

Storing the quote lets you answer the question that follows every pricing dispute: what rate did this user actually see, and when.

When a payment arrives late or short

On flows where a user sends crypto to fund a quote, the payment can arrive after expiry, or for the wrong amount, or in the wrong asset. These are normal in production, especially on mobile. Handle each case explicitly:
  • Detect the condition from the webhook event rather than from your own timer.
  • Alert your operations team, because most of these need a human decision.
  • Tell the user what happened and what you will do next.
Payout error handling covers expired quotes, underpayment, and delivery rejection case by case.

Test the window before you ship

Quote expiry is easy to get wrong and hard to notice, because it only appears when a user hesitates. In sandbox, create a quote, wait for expires_at to pass, then try to execute it. Confirm that your interface blocks the attempt and offers a fresh quote. See Test in sandbox.

Next

Continue to Errors and retries, which covers the status codes an expired quote returns and the retry rules around them.