Skip to main content
A webhook is a message we send to your server when something happens, so you don’t have to keep asking. When a customer’s payment shows up, and again when you’ve been paid, we send a POST request to a URL you choose. Each one is signed, so you can check it really came from us.
Off-ramp orders, onramp orders, and the Wallet API send their own events (offramp.*, onramp.*, wallet.*) to the same URL, signed the same way. This page covers checkout, since that’s where most people start.

Getting started

1

Add your URL

Go to Dashboard → Webhooks, paste your HTTPS URL (something like https://yourbusiness.com/webhooks/minisend), and save.
2

Copy your secret

We create it the first time you open that page and show it once. You’ll use it to check every message is really from us. See Verification.
3

Send yourself a test

The same page has a Send test button, so you can make sure everything works before a real payment comes through.
Always check the X-Minisend-Signature header before acting on a message. See Verification.

What we send, and when

A checkout session can send you up to five events, in this order:
  1. checkout.pending when we first see the payment. This is a heads-up, not a confirmation.
  2. checkout.completed when you’ve been paid, or checkout.failed if we couldn’t finish. If nothing was paid at all, you get checkout.expired instead.
  3. checkout.forwarded, only if you keep USDC on a network other than Base, once it has arrived there.
Two more events cover the rare case where your customer’s payment went through but we need to step in on our side: settlement.forward_failed and settlement.swap_failed. In both cases the money is safe, it’s just stuck partway. Full details for all seven are on the Events page.
checkout.pending doesn’t mean you’ve been paid. Use it to tell your customer “we’ve seen your payment, hang on”, never to hand over goods.

Headers

Every message, for any event, comes with these three headers: Checkout and settlement messages (checkout.* and settlement.*) come with three more:
X-Minisend-Event-Id identifies one message, not one payment. We can occasionally send the same news twice, for example checkout.completed for one session, and each copy gets its own ID. To make sure you never fulfil an order twice, use session_id and event from the message body together as your check, not this header. See Events for an example.
Reply with any 2xx status within 10 seconds and we’ll treat the message as delivered. If we time out or get a 4xx or 5xx, we try again later, so a slow moment on your side doesn’t lose anything.

Retries

If a message doesn’t get through, we try again on this schedule: That’s eight tries over about 33 hours, so a short outage on your side won’t make you miss anything. If your server is still down after the last try, we mark the message as failed, and you can send it again once you’re back up.

Replay

Dashboard → Webhooks lists every message we’ve sent, with its status and your server’s response. You can resend any that failed. A resent message has exactly the same content and ID, with a fresh timestamp and signature, so your server treats it as a retry rather than something new.
After five failed messages in a row, we mark your URL as down, on that page and on our side. Once it’s fixed, resend what you missed instead of waiting for the next retry.