Quote Lifecycle & Expiry
When you're moving value converting Bitcoin to Naira, sending USDT to fund airtime, or off-ramping to mobile money, every transaction starts with a quote. That quote includes the exchange rate, the expected amount to send, and a limited time to act.
This guide covers how quotes work, how to treat them as stateful objects, how to handle expiry, and what to do when users miss the window or underpay. It’s especially important for swaps, payouts, and anything with real-time asset pricing.
What is a Quote?
A quote is a temporary pricing contract. It defines the exchange rate, expected amounts, payment method, and expiration window for a transaction. It’s how Bitnob locks in a price between crypto and fiat (or service delivery) for a short period.
Quotes exist because:
Bitcoin and stablecoin prices fluctuate
FX rates between currencies change constantly
Services (like telcos) price airtime in fiat, not crypto
Sample Quote Flow

Quote Structure (Simplified)
How Quotes Are Used in Bitnob
Bitnob uses quotes in all value conversion or delivery flows, including:
Offramps (e.g., USDT to bank account)
Airtime and data purchases
Card funding
BTC to USDT swaps
Every quote is a stateful object. You create it, reference it when initiating the transaction, and monitor what happens next. Anyone taking their Bitnob integration to production
Best Practices for Handling Quotes
Display the Expiry Window Clearly
Let users know how long they have. Always show a countdown timer in the UI.
const expiry = new Date(quote.expiresAt)
const timeLeft = Math.max(0, expiry - Date.now())
showCountdown(Math.floor(timeLeft / 1000)) // in seconds
If the quote expires before the user acts, you must fetch a new one.
Monitor for Underpayment
If the user sends less than the quoted amount:
Bitnob emits payouts.asset.underpayment
The transaction is paused or canceled
You must decide how to resolve it (refund or retry)
Always monitor for this event in your webhook handler.
Handle Quote Expiry Gracefully
If a user tries to use an expired quote:
Do not initiate the transaction
Display a “quote expired” message
Refresh the quote automatically or prompt them to do so
Never reuse old quotes. Pricing is no longer valid.
Store Quotes with Transaction State
Every time you create a quote, store it alongside your transaction or UI session.
reference | quoteId | rate | expiresAt | userId | status |
---|---|---|---|---|---|
payout_txn_abc123 | QT_123456 | 1530 | 2025-04-08T14:45:00 | user_1 | pending |
This lets you trace which quote was used, what rate was shown, and whether it expired before execution.
Handle Quote Expiry Gracefully
If a user:
Pays the wrong asset (e.g., sends BTC instead of USDT)
Sends after expiry
Overpays by mistake
You should:
Reject or refund (depending on risk and config)
Trigger a support alert
Display a UI message with what happened
These happen in the wild — especially on mobile.
Simulate in Sandbox
Use sandbox endpoints to:
Create quotes for BTC or USDT
Test payment simulation
Trigger webhooks manually
This lets you build a full quote-expiry test flow without sending real crypto.
Advanced: Pre-warming Quotes
If your UI always starts with a fixed amount (e.g., $10 airtime), you can pre-fetch quotes in advance. Just be sure to refresh if the user takes too long.
Summary
Quotes are more than price lookups. They’re short-lived contracts that power every transaction in your app. Respecting their lifecycle prevents delivery errors, financial mismatches, and user frustration.
Always:
Track expiry and show timers Store quote references per transaction React to webhook events like underpayment Never trust expired quotes Simulate quote flows early in dev
Once your app treats quotes as real state, your payments feel consistent even when the world’s prices move second by second.
Ready to continue? We can go into Error Handling, Retries, and Fallbacks next. It’s where you make your app resilient under real-world failure conditions.