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 Flow

Quote Structure (Simplified)

JSON (Quote Example)

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

1.

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.

2.

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.

3.

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.

4.

Store Quotes with Transaction State

Every time you create a quote, store it alongside your transaction or UI session.

referencequoteIdrateexpiresAtuserIdstatus
payout_txn_abc123QT_12345615302025-04-08T14:45:00user_1pending

This lets you trace which quote was used, what rate was shown, and whether it expired before execution.

5.

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.

6.

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.

Node.js (Pre-warming Example)

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.