IntegrationsCustom Webhooks
Custom Webhooks
SilentAuth sends webhook events to your endpoint when an intent is approved, denied, or expires. Use webhooks to build fully asynchronous approval flows without polling.
Event Types
| Event | Description |
|---|---|
| intent.created | A new intent has been created and is pending approval |
| intent.approved | An approver approved the intent; permit is included in payload |
| intent.denied | An approver denied the intent |
| intent.expired | The intent reached its expiry time without resolution |
Example Webhook Payload
// POST to your endpoint
// Headers:
// sa-signature: sha256=xxx
// content-type: application/json
{
"id": "evt_abc123",
"type": "intent.approved",
"created_at": "2024-01-15T10:30:00Z",
"intent": {
"id": "int_xK9mNpQ2",
"action": "deploy_production",
"params": { "env": "prod", "version": "2.1.0" },
"approved_by": "jane@acme.io",
"approved_at": "2024-01-15T10:30:00Z"
},
"permit": {
"token": "eyJhbGciOiJSUzI1NiIs...",
"expires_at": "2024-01-15T10:35:00Z"
}
}Verifying Webhook Signatures
Always verify the sa-signature header to ensure the request is from SilentAuth:
import { SilentAuth } from '@silentauth/sdk';
const sa = new SilentAuth({ projectId: '...', secretKey: '...' });
// Express example
app.post('/webhooks/silentauth', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['sa-signature'];
let event;
try {
event = sa.verifyWebhook(req.body, sig);
} catch (err) {
return res.status(400).send('Webhook signature invalid');
}
switch (event.type) {
case 'intent.approved':
await handleApproval(event.intent, event.permit);
break;
case 'intent.denied':
await handleDenial(event.intent);
break;
}
res.json({ received: true });
});Configuring Your Endpoint
- Go to your project in the SilentAuth dashboard
- Navigate to Settings → Webhooks
- Click Add Endpoint and enter your HTTPS URL
- Select the event types you want to receive
- Copy the signing secret and store it securely