Docs Webhooks
Guides

Webhooks

Get notified in real time when handoffs are confirmed, chains complete, or links expire. No polling required.

Registering a webhook

Email hello@tryswiftproof.com with your HTTPS endpoint URL and the events you want to receive. We will add it to your project configuration and send a test event to verify delivery.

Your endpoint must use HTTPS. HTTP endpoints are not supported. The endpoint must respond with a 200 status within 10 seconds or SwiftProof will retry.

Event payload

POST your-endpoint.com/webhook
{
  "event_type":  "handoff.confirmed",
  "event_id":    "evt_01j2k3m4n5p6q7r8",
  "created_at":  "2026-06-29T14:23:00Z",
  "chain_id":    "sp_ch_a96fec076ffd44f4",
  "handoff_id":  "sp_hf_002",
  "data": {
    "event":        "collected",
    "actor":        "Rider — Emeka",
    "confirmed_at": "2026-06-29T14:22:58Z",
    "location":     "Ogunlana Drive, Surulere, Lagos",
    "coordinates":  { "lat": 6.4969, "lng": 3.3515 }
  }
}

Verifying webhook signatures

Every webhook request includes a X-SwiftProof-Signature header. Verify it to ensure the request came from SwiftProof and was not tampered with in transit.

webhook-handler.js
import crypto from 'crypto';

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

app.post('/webhook', (req, res) => {
  const valid = verifyWebhook(
    req.rawBody,
    req.headers['x-swiftproof-signature'],
    process.env.SWIFTPROOF_WEBHOOK_SECRET
  );

  if (!valid) return res.status(401).end();

  const event = req.body;
  // Handle event...
  res.status(200).end();
});

Retry behaviour

If your endpoint does not return 200 within 10 seconds, SwiftProof retries the delivery with exponential backoff — at 1 minute, 5 minutes, 30 minutes, and 2 hours. After 4 failed attempts the event is marked as failed and logged in your audit log.

Available events