Skip to main content

checkout.pending

Fires once, right after Minisend first sees a deposit on-chain and starts processing it. Not a confirmation, just an early signal so your customer isn’t staring at a blank screen while conversion or bridging happens in the background.
string
required
Always checkout.pending.
string
The chain the deposit was seen on.
string
The on-chain transaction that carried it.
string
USDC or USDT, whichever the customer paid with.
string
required
Always deposit_received.
This is not checkout.completed. The deposit could still fail to settle. Show the customer “we’ve seen it, hang on”, never release goods on this alone.

checkout.completed

The payment settled and the money is yours, whether that means it arrived as local currency or it’s sitting as USDC in your Minisend wallet.
string
required
Always checkout.completed.
string
required
Use alongside event as your idempotency key. See dedupe for why the id in the headers isn’t enough on its own.
string
Your reference, if set.
number
required
The amount the session asked for. Not necessarily the amount that arrived — see amount_received_usdc.
number
required
Same value as amount_usdc, named explicitly so the pair reads unambiguously alongside amount_received_usdc.
number
What actually landed on-chain. Reconcile on this field, not amount_usdc.A customer who sends slightly more or less than the session asked for is still settled, for the amount they actually sent. The alternative would strand their funds. So a completed session can carry an amount_usdc that was never received.
boolean
false when the received amount fell outside ±$0.01 of the expected one. Treat false as needing review: the payout is real, but it isn’t the figure you quoted.
string
The chain the deposit was seen on.
string
The on-chain transaction that carried the deposit.
string
USDC or USDT, whichever the customer actually paid with.
string
required
fiat or usdc. Present on every payload so you can branch on it unconditionally. A usdc payload carries fee_usdc, amount_usdc_net, settlement_chain, and forward_required in place of amount_local and exchange_rate.
number
USDC mode only. The platform fee taken from the deposit.
number
USDC mode only. What was actually credited to you: received minus fee.
string
USDC mode only. The chain this settlement is, or will be, delivered on.
boolean
USDC mode only. true when your money still has to cross chains to reach settlement_chain.This field exists because checkout.completed fires before any bridging is attempted, deliberately, so forwarding never delays your payment confirmation. That makes status: "completed" a statement about the payment, not about where the money currently sits. When this is true, wait for checkout.forwarded before treating the funds as landed on their destination chain.
number
Fiat mode only. Net local currency after the platform fee.
string
required
Fiat mode: KES, NGN, GHS, or UGX. USDC mode: USDC.
number
Fiat mode only. Local currency per 1 USDC at settlement.
string
required
Fiat mode: the payout provider’s receipt. USDC mode: the customer’s own deposit transaction, since there’s no second leg to receipt.
string
required
Always completed.
string
required
ISO 8601.
string
required
ISO 8601.
This fires at a different point depending on your setup, and it’s the thing most integrations get wrong by assuming it’s uniform. On the USDC rail it’s seconds, the instant Circle confirms the deposit. On the fiat rail it’s minutes, once the local payout actually lands, a stronger guarantee. On USDT, add 30 to 60 seconds for the conversion first, then the same two paths. Whichever it is, by the time this event reaches you the deposit is irrevocably yours, safe to treat as a real, final payment.

checkout.failed

Deposit received but settlement could not complete. Rare.
string
required
Always checkout.failed.
string
required
string
number
required
The amount the session asked for. amount_received_usdc carries what was actually deposited, when a deposit was attributed before the failure.
string
required
string
required
Always failed.
string
required
Contact support with the session_id. Customer funds are not lost.

checkout.expired

Session opened but no deposit arrived in the 30-minute window. Use this to mark abandoned orders.
string
required
Always checkout.expired.
string
required
string
Use this to mark the corresponding order as abandoned.
number
required
The amount the customer never sent.
string
required
string
required
Always expired.
string
required
Expired sessions cost nothing. The platform fee is only charged on completed payments.

checkout.forwarded

USDC mode only, and only for sessions settling off Base. The bridge finished, and your USDC landed on the chain you picked.
string
required
Always checkout.forwarded.
string
required
string
string
required
Where the USDC landed.
string
required
The destination-chain transaction.
A failed bridge sends nothing here, see settlement.forward_failed below. Your USDC stays safe on Base either way, so poll forward.status on the checkout session if you need to know for sure without waiting on an event.

settlement.forward_failed

USDC mode only. Your money didn’t make it to your chosen chain, and won’t without help. The customer’s payment is not in question here, they already paid and you were credited. This is purely about a transfer of your own funds between chains that got stuck partway.
string
required
Always settlement.forward_failed.
string
required
Where the money was supposed to land.
string
required
Where it actually is right now. Always Base, the origin chain, since a failed forward simply never leaves.
Only fires once the forward is definitively dead, never on a first hiccup. Before that, the correct reading is still “in flight.” Contact support with the session_id to get it moving again.

settlement.swap_failed

USDC-mode merchants only, and only reachable through the USDT rails. Your customer paid in USDT, but converting it to USDC didn’t go through and won’t without help, so you’re holding the original token on the chain they paid on instead of the USDC you expected.
string
required
Always settlement.swap_failed.
string
required
The chain your customer originally paid on. That’s where the unconverted funds are sitting.
string
required
The token you’re actually holding, USDT rather than the USDC you expected. Without this field, funds_on_chain alone would leave you to discover the token yourself.
Always fires after a truthful checkout.completed, the customer’s payment already succeeded. A fiat merchant can’t be paid local currency out of an unconverted token, so their session is quoted again automatically instead of erroring out. Contact support with the session_id.

Best practices

Respond fast, process async

Dedupe on (session_id, event), not on the delivery header

X-Minisend-Event-Id identifies one delivery attempt. The same logical event can be sent from more than one internal path with a different id each time, so key your own idempotency check on the payload instead:

Branch on settlement_mode before reading fiat fields

amount_local and exchange_rate only exist in fiat mode. A USDC-mode payload has fee_usdc, amount_usdc_net, and forward_required instead, so check the mode before assuming either shape:

Reconcile on what arrived, not what you asked for

amount_usdc is the figure the session was created with. If you book revenue from it, an underpayment records money you never received.

Correlate via external_id