# Webhooks

INFRA sends webhook events to your registered endpoint when key actions occur. Configure your webhook URL in the developer portal.

## Event types

| Event | Description |
|---|---|
| `kyc.verified` | User completed KYC successfully |
| `kyc.rejected` | KYC verification was rejected |
| `consent.granted` | User approved your app's access request |
| `consent.revoked` | User revoked your app's access |
| `claim.issued` | A new verification claim was issued to a user |
| `claim.revoked` | A verification claim was revoked |
| `data.deletion_requested` | User requested data deletion (GDPR) |

## Webhook payload

```javascript
// Example: kyc.verified event
{
  "event_type": "kyc.verified",
  "event_id": "evt_01HXYZ...",
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "user_id": "usr_01HXYZ...",
    "kyc_level": "level_1",
    "status": "verified",
    "provider": "persona"
  }
}
```

## Verifying signatures

Every webhook request includes an `x-webhook-signature` header. Always verify this before processing the event.

```javascript
const crypto = require('crypto');

function verifyWebhook(req, webhookSecret) {
  const signature = req.headers['x-webhook-signature'];
  const expectedSig = crypto
    .createHmac('sha256', webhookSecret)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (signature !== expectedSig) {
    throw new Error('Invalid webhook signature');
  }
  return true;
}

// In your Express route:
app.post('/webhooks/infra', (req, res) => {
  verifyWebhook(req, process.env.INFRA_WEBHOOK_SECRET);
  const { event_type, data } = req.body;

  switch (event_type) {
    case 'kyc.verified':
      // Update user KYC status in your DB
      break;
    case 'consent.revoked':
      // Remove user access tokens
      break;
  }
  res.json({ received: true });
});
```

---

Source: https://docs.infraidentity.com/webhooks/ · Full docs: https://docs.infraidentity.com/llms-full.txt
