Webhooks

Receive real-time notifications when your records are anchored to the blockchain. Configure webhook endpoints to automate your workflows.

Overview

When you anchor a record with Anchora, it takes 30-60 seconds to be confirmed on the Polygon blockchain. Instead of polling for status, configure webhooks to receive instant notifications when:

  • anchor.confirmed - Record successfully anchored to blockchain
  • anchor.failed - Anchoring failed (rare, usually network issues)
  • record.updated - Mutable fields were updated
  • record.deleted - Record was soft or hard deleted

Configuring Webhooks

You can configure webhooks in two ways: globally via your dashboard, or per-request using the webhookUrl parameter.

Per-Request Webhook

Include webhook URL in your request
curl -X POST https://api.anchora.co.in/v1/anchor/encrypted \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "name": "Alice Smith",
      "certificateId": "CERT-2024-001"
    },
    "encryptionKey": "your-32-character-encryption-key!!",
    "webhookUrl": "https://your-app.com/webhooks/anchora"
  }'

Webhook Payload

When an event occurs, Anchora sends a POST request to your webhook URL with the following payload:

Webhook payload example
{
  "event": "anchor.confirmed",
  "timestamp": "2024-01-31T10:30:00Z",
  "data": {
    "recordId": "507f1f77bcf86cd799439011",
    "hash": "a1b2c3d4e5f6...64chars",
    "txHash": "0x3f8a9c2e1b4d7f6a...",
    "blockNumber": 45678901,
    "status": "ANCHORED"
  },
  "signature": "sha256=abc123..."
}

Multi-Chain Headers NEW

Webhooks now carry chain provenance headers so receivers can branch on chain type without re-querying the API. Old EVM-only receivers continue to work — the new headers are additive.

HTTP headers (multi-chain)
X-Anchora-Event: ANCHORED
X-Anchora-Hash: <full hash>
X-Anchora-Package: SEPARATED | IN_PLACE | MANAGED
X-Anchora-Chain: evm | fabric                       // NEW
X-Anchora-Network: polygon-amoy | fabric-byo | ...  // NEW
X-Anchora-Retry-Attempt: 0..5

Fabric body example

For Fabric records, note: blockNumber is explicit null (fabric-gateway doesn't expose block heights), transactionHash is the raw Fabric txID (no 0x prefix), and batchId is a string.

Fabric webhook body
{
  "type": "ANCHORED",
  "hash": "63e33ef9...",
  "recordId": "507f1f77bcf86cd799439012",
  "chainType": "fabric",
  "networkId": "fabric-byo",
  "blockNumber": null,
  "transactionHash": "95cfed3ad9d5c49a...",
  "batchId": "7",
  "anchoredAt": "2026-05-12T11:21:10.736Z",
  "merkleProof": ["0x70bdd5..."],
  "metadata": {}
}

Hybrid body example

A Hybrid record's webhook carries BOTH chain anchors in a single delivery — primary fields at top level, secondary inside dualAnchor.

Hybrid webhook body
{
  "type": "ANCHORED",
  "hash": "e90e818fbf...",
  "chainType": "fabric",
  "networkId": "fabric-byo",
  "batchId": "4",
  "transactionHash": "aea1e2167553e7e3...",
  "blockNumber": null,
  "merkleProof": [],
  "dualAnchor": {
    "chainType": "evm",
    "networkId": "polygon-amoy",
    "batchId": 114,
    "blockNumber": 38228377,
    "transactionHash": "0x6bc51454f711...",
    "merkleProof": [],
    "anchoredAt": "..."
  }
}

See Multi-Chain Anchoring for the complete payload reference, or Hybrid Mode Guide for end-to-end setup.

Verifying Webhook Signatures

All webhook requests include a signature header to verify authenticity. Always verify signatures before processing webhooks.

Verify webhook signature (Node.js)
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expectedSignature = 'sha256=' +
    crypto.createHmac('sha256', secret)
      .update(payload)
      .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/anchora', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    signature,
    process.env.WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook
  console.log('Received event:', req.body.event);
  res.status(200).json({ received: true });
});
Security: Always verify webhook signatures. Never trust incoming webhooks without validation, as attackers could send fake events.

Retry Policy

If your endpoint returns a non-2xx response, Anchora will retry the webhook with exponential backoff:

Attempt Delay Total Time
1st retry 1 minute 1 minute
2nd retry 5 minutes 6 minutes
3rd retry 30 minutes 36 minutes
4th retry 2 hours ~2.5 hours
5th retry (final) 24 hours ~26.5 hours

Best Practices

  • Respond quickly: Return a 200 response immediately, then process async
  • Handle duplicates: Use the recordId to deduplicate events
  • Verify signatures: Always validate the x-webhook-signature header
  • Use HTTPS: Webhook URLs must use HTTPS in production
  • Log everything: Keep logs of received webhooks for debugging
Tip: Use a webhook testing service like webhook.site during development to inspect payloads before implementing your handler.