Ir al contenido

Webhooks

Webhooks

Receive real-time notifications when transactions occur on your monitored addresses. Webhooks are HTTP callbacks that notify your application when events occur. Instead of polling our API, we push updates directly to your server.

Event Types

Event Description
transaction.detectedTransaction seen in mempool (0 confirmations)
transaction.confirmedTransaction confirmed (configurable threshold)
address.createdNew address generated
wallet.updatedWallet settings changed

Setting Up Webhooks

  1. Create Webhook Endpoint

    Create a POST endpoint on your server to receive webhooks:

    app.post('/webhooks/sanpay', (req, res) => {
      const event = req.body;
      
      switch (event.type) {
        case 'transaction.confirmed':
          handleConfirmedTransaction(event.data);
          break;
        case 'transaction.detected':
          handlePendingTransaction(event.data);
          break;
      }
      
      res.status(200).send('OK');
    });
  2. Register Webhook

    Register your endpoint with SanPay:

    curl -X POST https://api.sanpay.io/v1/webhooks \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "url": "https://your-app.com/webhooks/sanpay",
        "events": ["transaction.detected", "transaction.confirmed"],
        "secret": "your-webhook-secret"
      }'
  3. Verify Signatures

    Verify webhook authenticity using the signature header:

    const crypto = require('crypto');
    
    function verifyWebhook(payload, signature, secret) {
      const expected = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');
      
      return crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expected)
      );
    }
    
    app.post('/webhooks/sanpay', (req, res) => {
      const signature = req.headers['x-sanpay-signature'];
      const isValid = verifyWebhook(
        JSON.stringify(req.body),
        signature,
        process.env.WEBHOOK_SECRET
      );
      
      if (!isValid) {
        return res.status(401).send('Invalid signature');
      }
      
      // Process webhook...
    });

Webhook Payload

Transaction Confirmed

{
  "id": "evt_abc123",
  "type": "transaction.confirmed",
  "timestamp": "2024-01-15T10:45:00Z",
  "data": {
    "id": "tx_def456",
    "txHash": "abc123def456789...",
    "walletId": "wal_abc123",
    "address": "bc1qxy2kgdygjrsqvzq3rj...",
    "amount": "0.00150000",
    "direction": "incoming",
    "confirmations": 6,
    "blockHeight": 823456,
    "metadata": {
      "orderId": "order_12345"
    }
  }
}

Transaction Detected

{
  "id": "evt_xyz789",
  "type": "transaction.detected",
  "timestamp": "2024-01-15T10:40:00Z",
  "data": {
    "id": "tx_def456",
    "txHash": "abc123def456789...",
    "walletId": "wal_abc123",
    "address": "bc1qxy2kgdygjrsqvzq3rj...",
    "amount": "0.00150000",
    "direction": "incoming",
    "confirmations": 0,
    "status": "pending"
  }
}

Retry Policy

Attempt Delay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
624 hours
  • Your endpoint returns a non-2xx status code
  • The request times out (30 second limit)
  • The connection fails

Best Practices

  1. Respond quickly – Return 200 immediately, process asynchronously
  2. Handle duplicates – Use the event `id` to deduplicate
  3. Verify signatures – Always validate the `x-sanpay-signature` header
  4. Use HTTPS – We only deliver webhooks to secure endpoints
  5. Monitor failures – Set up alerts for failed deliveries