The DEAF-FIRST Platform webhook system allows you to register and manage webhooks to receive real-time notifications about events in the platform. This replaces the functionality that was previously handled by Xano.
http://localhost:3000/api
Get a list of all registered webhooks.
Endpoint: GET /webhooks
Response:
{
"success": true,
"count": 2,
"webhooks": [
{
"id": "wh_1234567890_abc123",
"name": "Production Webhook",
"url": "https://example.com/webhook",
"events": ["user.created", "user.updated"],
"secret": "***",
"active": true,
"createdAt": "2025-12-05T07:00:00.000Z",
"updatedAt": "2025-12-05T07:00:00.000Z"
}
]
}Retrieve details of a specific webhook by ID.
Endpoint: GET /webhooks/:id
Response:
{
"success": true,
"webhook": {
"id": "wh_1234567890_abc123",
"name": "Production Webhook",
"url": "https://example.com/webhook",
"events": ["user.created"],
"secret": "***",
"active": true,
"createdAt": "2025-12-05T07:00:00.000Z",
"updatedAt": "2025-12-05T07:00:00.000Z"
}
}Create a new webhook registration.
Endpoint: POST /webhooks
Request Body:
{
"name": "My Webhook",
"url": "https://example.com/webhook",
"events": ["user.created", "user.updated"],
"secret": "optional-custom-secret"
}Response:
{
"success": true,
"message": "Webhook registered successfully",
"webhook": {
"id": "wh_1234567890_abc123",
"name": "My Webhook",
"url": "https://example.com/webhook",
"events": ["user.created", "user.updated"],
"secret": "generated-or-custom-secret",
"active": true,
"createdAt": "2025-12-05T07:00:00.000Z",
"updatedAt": "2025-12-05T07:00:00.000Z"
}
}Update an existing webhook.
Endpoint: PUT /webhooks/:id
Request Body:
{
"name": "Updated Webhook Name",
"url": "https://new-url.com/webhook",
"events": ["user.created", "user.deleted"],
"active": false
}Response:
{
"success": true,
"message": "Webhook updated successfully",
"webhook": {
"id": "wh_1234567890_abc123",
"name": "Updated Webhook Name",
"url": "https://new-url.com/webhook",
"events": ["user.created", "user.deleted"],
"secret": "***",
"active": false,
"createdAt": "2025-12-05T07:00:00.000Z",
"updatedAt": "2025-12-05T08:00:00.000Z"
}
}Delete a webhook registration.
Endpoint: DELETE /webhooks/:id
Response:
{
"success": true,
"message": "Webhook deleted successfully"
}View delivery history for a specific webhook.
Endpoint: GET /webhooks/:id/deliveries
Response:
{
"success": true,
"count": 5,
"deliveries": [
{
"id": "del_1234567890_xyz789",
"webhookId": "wh_1234567890_abc123",
"event": "user.created",
"payload": {
"event": "user.created",
"timestamp": "2025-12-05T07:00:00.000Z",
"data": { "userId": "123", "email": "user@example.com" }
},
"response": {
"status": 200,
"body": "OK"
},
"attempts": 1,
"status": "success",
"timestamp": "2025-12-05T07:00:00.000Z"
}
]
}Get a list of all available webhook event types.
Endpoint: GET /webhooks/events/types
Response:
{
"success": true,
"count": 12,
"events": [
"user.created",
"user.updated",
"user.deleted",
"auth.login",
"auth.logout",
"document.uploaded",
"document.processed",
"accessibility.request",
"sync.started",
"sync.completed",
"ai.process.started",
"ai.process.completed"
]
}Manually trigger a webhook event for testing purposes.
Endpoint: POST /webhooks/trigger
Request Body:
{
"event": "user.created",
"data": {
"userId": "123",
"email": "test@example.com",
"name": "Test User"
}
}Response:
{
"success": true,
"message": "Webhook event triggered successfully"
}These endpoints receive webhooks from external services like Xano.
Endpoint: POST /incoming-webhooks/:service
Where :service can be:
xano- For Xano webhooksstripe- For Stripe webhookscustom- For custom webhooks
Headers:
X-Webhook-Signature: HMAC signature for verificationX-Webhook-Event: Event type
Request Body: (varies by service)
{
"event": "record.created",
"data": {
"id": "123",
"table": "users",
"record": { "name": "John Doe" }
}
}Response:
{
"success": true,
"message": "Webhook received successfully",
"eventId": "evt_1234567890_xyz789"
}Endpoint: GET /incoming-webhooks/health
Response:
{
"success": true,
"message": "Incoming webhook endpoint is healthy",
"timestamp": "2025-12-05T07:00:00.000Z"
}All outgoing webhooks include an X-Webhook-Signature header containing an HMAC-SHA256 signature of the payload.
To verify a webhook:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}Every webhook delivery includes these headers:
Content-Type:application/jsonX-Webhook-Signature: HMAC signature for verificationX-Webhook-Event: The event type (e.g., "user.created")X-Webhook-Delivery: Unique delivery ID
user.created- Triggered when a new user is createduser.updated- Triggered when user information is updateduser.deleted- Triggered when a user is deleted
auth.login- Triggered when a user logs inauth.logout- Triggered when a user logs out
document.uploaded- Triggered when a document is uploadeddocument.processed- Triggered when document processing completes
accessibility.request- Triggered when accessibility features are requested
sync.started- Triggered when synchronization beginssync.completed- Triggered when synchronization completes
ai.process.started- Triggered when AI processing beginsai.process.completed- Triggered when AI processing completes
{
"event": "user.created",
"timestamp": "2025-12-05T07:00:00.000Z",
"data": {
"userId": "usr_1234567890",
"email": "user@example.com",
"name": "John Doe",
"preferences": {
"signLanguage": true,
"visualAccessibility": true
}
}
}If you were previously using Xano webhooks:
- Register your webhook endpoints using the
POST /webhooksendpoint - Configure incoming webhooks to receive events from Xano at
/incoming-webhooks/xano - Update your Xano configuration to point to your new webhook URL
- Test webhook delivery using the trigger endpoint
All endpoints return consistent error responses:
{
"success": false,
"error": "Error type",
"message": "Detailed error message"
}Common HTTP status codes:
200- Success201- Created400- Bad Request404- Not Found500- Internal Server Error
Currently, there are no rate limits applied to webhook endpoints. In production, consider implementing rate limiting based on your needs.
- Verify signatures - Always verify webhook signatures to ensure authenticity
- Handle idempotency - Webhook events may be delivered multiple times; handle duplicates gracefully
- Respond quickly - Return a 200 response as soon as possible; process webhooks asynchronously
- Log deliveries - Use the delivery history endpoint to monitor webhook health
- Use HTTPS - Always use HTTPS URLs for webhook endpoints in production
- Rotate secrets - Periodically rotate webhook secrets for security
For issues or questions about the webhook system, please refer to the main documentation or create an issue in the repository.