Guides
Webhooks
Get a signed POST request whenever a payment, credit or transfer happens.
Set a webhook URL in the dashboard and we'll POST an event to it whenever something happens in your account.
Events
| Event | When |
|---|---|
payment.successful | A customer paid. Verify, then fulfil the order. |
payment.failed | A payment attempt failed. |
virtual_account.credited | Money landed in a virtual account. |
transfer.successful | A transfer reached the recipient. |
transfer.failed | A transfer failed and the money is back in your balance. |
Check the signature
Each request carries an X-CSwitch-Signature header: an HMAC-SHA512 of the raw request body, using your secret key. Check it before you trust the event.
webhook.js
import crypto from "node:crypto";
export async function POST(request) {
const raw = await request.text();
const expected = crypto
.createHmac("sha512", process.env.CSWITCH_SECRET_KEY)
.update(raw)
.digest("hex");
if (expected !== request.headers.get("x-cswitch-signature")) {
return new Response("invalid signature", { status: 401 });
}
const event = JSON.parse(raw);
// queue the work, then answer straight away
return new Response("ok");
}webhook.py
import hmac, hashlib, os
def is_from_cswitch(raw_body: bytes, signature: str) -> bool:
expected = hmac.new(os.environ["CSWITCH_SECRET_KEY"].encode(), raw_body, hashlib.sha512).hexdigest()
return hmac.compare_digest(expected, signature or "")Retries
Reply with a 200 as soon as you've received the event. Events that don't get a 200 are retried, so make your handler safe to run twice for the same event.