Tizondocs
Concepts

Idempotency

Every write that moves money takes a key, so a retry cannot buy twice.

Every POST that moves money requires an Idempotency-Key header. Send a fresh unique value per logical operation — a UUID is fine:

curl https://api.tizon.mobile/v1/quotes \
  -H "Authorization: Bearer $TIZON_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5f1c9a3e-7b42-4d18-9e65-0c7a2d4b8e31" \
  -d '{ "offer_id": "off_jp_5gb_30d", "payment_source": "wallet" }'

Retrying is safe

Retry with the same key and you get the original response back, marked Idempotent-Replayed: true. The effect is not repeated: one quote, one debit, one order, however many times the request arrives.

This is what makes a timeout survivable. If a request dies in flight and you do not know whether it landed, send it again with the same key rather than guessing.

Reusing a key for different content

A key is bound to the request that first used it. Sending the same key with a different body is rejected:

{
  "error": {
    "type": "conflict",
    "code": "idempotency_key_reuse_mismatch",
    "message": "This Idempotency-Key was used for a different request.",
    "request_id": "req_4b1c0d8e9f2a3b4c5d6e7f8091a2b3c4"
  }
}

So scope a key to one logical purchase. Do not reuse last hour's key for this hour's order, and do not share one key across a batch.

Failures that recorded nothing

A request that failed without effect records nothing, so the key stays usable. The clearest case is 402 insufficient_funds: nothing was charged, nothing was created, so once the wallet is funded you may retry the identical request with the same key and it will go through.

The rule of thumb: if the API changed nothing, the key is still free. If it changed anything, the key is now bound to that outcome and replaying returns it.

Where keys are required

Any write that moves money or mints a payment instruction, including:

  • POST /v1/quotes — buying an offer
  • POST /v1/wallet/lightning_invoices — minting a funding invoice
  • POST /v1/revenue/transfers and POST /v1/revenue/payouts

Reads never need one. The reference marks the header on each operation that takes it.

On this page