Payment Processor
Concepts

Webhooks

Receive HTTP callbacks when payment status changes.

Overview

Webhooks allow your backend to react to payment events in real time. When a charge is completed or expires, the processor sends an HTTP POST to your registered endpoint.

Registering a webhook

curl -X POST http://localhost:4000/v1/webhooks \
  -H "Authorization: Bearer $API_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-site.com/webhooks/crypto",
    "events": ["charge.completed", "charge.expired"],
    "secret": "your-webhook-secret"
  }'

Payload format

{
  "event": "charge.completed",
  "chargeId": "cm1abc123",
  "status": "COMPLETED",
  "expectedAmountUsd": "49.99",
  "receivedAmountUsd": "49.99",
  "receivedToken": "ETH",
  "chain": "eth-sepolia",
  "timestamp": "2026-03-08T12:04:37.000Z"
}

Signature verification

If you provided a secret when registering, every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 signature of the raw request body.

Verify it in your handler:

import { createHmac } from 'crypto';
 
function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return signature === `sha256=${expected}`;
}
 
// Express example
app.post('/webhooks/crypto', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-webhook-signature'] as string;
  if (!verifyWebhook(req.body.toString(), sig, process.env.WEBHOOK_SECRET!)) {
    return res.status(401).send('Invalid signature');
  }
  const payload = JSON.parse(req.body.toString());
  // handle payload
  res.sendStatus(200);
});

Retry behaviour

If your endpoint returns a non-2xx response or times out, the processor retries with exponential backoff. After several failed attempts the webhook delivery is marked as failed.

Your endpoint should respond within 5 seconds. For long-running tasks, acknowledge the webhook immediately and process it asynchronously.

Supported events

EventWhen
charge.completedFull USD amount received on-chain
charge.expiredCharge TTL elapsed without full payment

On this page