Tizondocs
Guides

Selling without a float

No prefunding. The quote carries its own payment instruction, so your customer pays at the point of sale.

The wallet is not a prerequisite. Quote with a payment rail instead of wallet and the quote waits in awaiting_funds, carrying everything needed to pay it. This is the model for a partner who takes money from a customer at the moment of sale and has nothing sitting in a float.

Lightning: an invoice per purchase

curl https://api.tizon.mobile/v1/quotes \
  -H "Authorization: Bearer $TIZON_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "offer_id": "off_jp_5gb_30d", "payment_source": "lightning" }'

payment.lightning.bolt11 is the whole instruction — an invoice for exactly this quote's price, minted for this quote alone, which expires and cannot be reused. Render it as a QR code and let the customer pay.

{
  "status": "awaiting_funds",
  "price": { "amount": 1450, "currency": "USD" },
  "payment": {
    "rail": "lightning",
    "amount": { "amount": 1450, "currency": "USD" },
    "asset": null,
    "asset_amount": null,
    "destinations": [],
    "lightning": {
      "bolt11": "lnbc144u1p...",
      "payment_hash": "9f2a...",
      "amount_sats": 22656
    }
  },
  "expires_at": "2026-10-02T12:15:00Z",
  "order_id": null
}

Paying it credits the wallet in USD and settles the quote in one move, so no funding step is needed. The payer sends satoshis; you are credited the USD amount whatever the rate does in between.

Stablecoins and bank transfer

With usdt, usdc or bank_transfer, payment.destinations holds the account's standing destinations for that rail — the same addresses as funding, not a per-quote address:

{
  "payment": {
    "rail": "usdt",
    "amount": { "amount": 1450, "currency": "USD" },
    "asset": "USDT",
    "asset_amount": "14.50",
    "destinations": [
      {
        "type": "crypto_address",
        "asset": "USDT",
        "network": "base",
        "address": "0x5f1c9a3e7b424d189e650c7a2d4b8e31f0a9c6d2",
        "memo": null,
        "status": "active"
      }
    ],
    "lightning": null
  }
}

Read rail to know which fields matter: on Lightning, destinations is empty and the invoice is everything; on the others, lightning is null and you send amount to one of the destinations.

Because the destinations are standing, what arrives is credited to the wallet, not to the quote. There is no per-quote address to match a payment against.

How waiting quotes get paid

Every payment credits the wallet, and waiting quotes are then paid from the balance. The matching rule is deliberate and worth knowing:

  1. The quote priced exactly at what arrived goes first.
  2. Then the oldest quote that the balance can cover.

Money already in the wallet counts, so a quote may come back fulfilled immediately rather than awaiting_funds.

Waiting quotes are paid from the balance only — never from an overdraft. An overdraft is for payment_source: wallet.

Expiry

An unpaid quote expires at expires_at and becomes expired. Money that arrives after that stays in the wallet; it is not lost, and it will pay the next thing that fits.

You can stop one early:

curl -X POST https://api.tizon.mobile/v1/quotes/{quote_id}/cancel \
  -H "Authorization: Bearer $TIZON_KEY"

Only awaiting_funds ever changes state. fulfilled, expired and cancelled are final.

What to listen for

EventMeans
quote.awaiting_fundsThe quote is waiting; the payment instruction is live.
wallet.creditedMoney arrived. A quote may settle on the back of it.
quote.fulfilledPaid and handed to fulfillment. An order now exists.
quote.expiredNobody paid in time.
order.fulfilledThe eSIM or top-up is ready — read deliverable.

Take order.fulfilled as the signal to hand something to your customer, not quote.fulfilled: a fulfilled quote means paid, while the order carries the delivery outcome.

Testing the whole flow

# Quote with lightning, then pretend the customer paid it:
curl -X POST \
  https://api.tizon.mobile/v1/test_helpers/lightning_invoices/{invoice_id}/pay \
  -H "Authorization: Bearer $TIZON_KEY"

On this page