Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.minisend.xyz/llms.txt

Use this file to discover all available pages before exploring further.

EventFires whenTerminal status
checkout.completedPayout delivered to your accountcompleted
checkout.failedSettlement failed post-depositfailed
checkout.expiredNo deposit within 30 minutesexpired

checkout.completed

Deposit received, normalised to USDC on Base, converted, and paid out.
{
  "event": "checkout.completed",
  "session_id": "cs_7f8a9b2c-...",
  "external_id": "order-4821",
  "amount_usdc": 25.00,
  "amount_local": 3225.00,
  "currency": "KES",
  "exchange_rate": 129.00,
  "receipt": "SHQ1234ABC",
  "status": "completed",
  "completed_at": "2026-04-13T14:32:00Z",
  "created_at": "2026-04-13T14:00:00Z"
}
event
string
required
Always checkout.completed.
session_id
string
required
Use as an idempotency key.
external_id
string
Your reference, if set.
amount_usdc
number
required
amount_local
number
required
Net local currency after the 1% fee.
currency
string
required
KES, NGN, GHS, or UGX.
exchange_rate
number
required
Local currency per 1 USDC at settlement.
receipt
string
required
Payout provider receipt.
status
string
required
Always completed.
completed_at
string
required
ISO 8601.
created_at
string
required
ISO 8601.

checkout.failed

Deposit received but settlement could not complete. Rare.
{
  "event": "checkout.failed",
  "session_id": "cs_7f8a9b2c-...",
  "external_id": "order-4821",
  "amount_usdc": 25.00,
  "currency": "KES",
  "status": "failed",
  "created_at": "2026-04-13T14:00:00Z"
}
event
string
required
Always checkout.failed.
session_id
string
required
external_id
string
amount_usdc
number
required
The amount that was deposited but couldn’t be settled.
currency
string
required
status
string
required
Always failed.
created_at
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.
{
  "event": "checkout.expired",
  "session_id": "cs_7f8a9b2c-...",
  "external_id": "order-4821",
  "amount_usdc": 25.00,
  "currency": "KES",
  "status": "expired",
  "created_at": "2026-04-13T14:00:00Z"
}
event
string
required
Always checkout.expired.
session_id
string
required
external_id
string
Use this to mark the corresponding order as abandoned.
amount_usdc
number
required
The amount the customer never sent.
currency
string
required
status
string
required
Always expired.
created_at
string
required
Expired sessions cost nothing — the 1% fee is only charged on completed payments.

Best practices

Respond fast, process async

app.post('/webhooks/minisend', (req, res) => {
  res.status(200).send('OK');
  processWebhookAsync(req.body);
});

Idempotency

Use session_id as the key — Minisend may redeliver if your server timed out.
async function processWebhookAsync(payload) {
  const seen = await db.events.findOne({ session_id: payload.session_id });
  if (seen) return;

  await db.events.insert({ session_id: payload.session_id, processed_at: new Date() });
  // ...handle event
}

Correlate via external_id

if (payload.event === 'checkout.completed') {
  await orders.markPaid(payload.external_id, {
    receipt: payload.receipt,
    payout_amount: payload.amount_local,
    currency: payload.currency,
  });
} else if (payload.event === 'checkout.expired') {
  await orders.markAbandoned(payload.external_id);
}