> ## Documentation Index
> Fetch the complete documentation index at: https://docs.layer3x.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

Layer3x sends HMAC-signed webhook notifications to your systems when payment events occur — so your ops team gets alerted in real time, not after a manual dashboard check.

## Events

| Event                     | Trigger                          |
| ------------------------- | -------------------------------- |
| `payment.blocked`         | Agent payment denied by policy   |
| `payment.escalated`       | Payment requires human approval  |
| `payment.reauth_required` | Step-up authentication triggered |
| `agent.deactivated`       | An agent was disabled            |

## Setup

1. Go to **Integrations** → **Webhooks** tab
2. Click **Add Webhook**
3. Enter your endpoint URL
4. Select the events to listen for
5. Copy the signing secret shown — it is displayed only once

## Payload format

```json theme={null}
{
  "event_type": "payment.escalated",
  "timestamp": "2026-03-28T22:51:18.715Z",
  "data": {
    "request_id": "uuid",
    "agent_id": "uuid",
    "agent_name": "Payment Bot",
    "action_key": "payments.release",
    "amount": 6200,
    "vendor": "TechVendor Inc",
    "decision": "ESCALATE",
    "reason": "Approval required by policy",
    "matched_policy": "Escalate large payments",
    "risk_score": 51,
    "timestamp": "2026-03-28T22:51:17.670Z"
  }
}
```

## Verify signatures

Every webhook payload is signed with HMAC-SHA256. Always verify the signature before processing:

```javascript theme={null}
const crypto = require('crypto')

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

// In your webhook handler:
const signature = req.headers['x-layer3x-signature']
const isValid = verifyWebhook(
  JSON.stringify(req.body), 
  signature, 
  YOUR_WEBHOOK_SECRET
)

if (!isValid) {
  return res.status(401).send('Invalid signature')
}
```

## Retry logic

If your endpoint returns a non-2xx response, Layer3x retries automatically with exponential backoff:

* Attempt 1: immediately
* Attempt 2: after 5 seconds
* Attempt 3: after 25 seconds
* Attempt 4: after 125 seconds

After 4 failed attempts the delivery is marked as failed and logged in your webhook delivery log.

## Target integrations

Layer3x webhooks work with any REST endpoint. Common integrations: Slack, PagerDuty, Microsoft Teams, custom REST endpoints.
