This guide will help you quickly set up and use the webhook system that replaces the Xano webhook functionality.
The webhook system provides:
npm run dev:backend
The server will start on port 3000 (or your configured BACKEND_PORT).
Register your webhook endpoint to receive events:
curl -X POST http://localhost:3000/api/webhooks \
-H "Content-Type: application/json" \
-d '{
"name": "My App Webhook",
"url": "https://your-app.com/webhook",
"events": ["user.created", "user.updated"]
}'
Response:
{
"success": true,
"message": "Webhook registered successfully",
"webhook": {
"id": "wh_...",
"name": "My App Webhook",
"url": "https://your-app.com/webhook",
"events": ["user.created", "user.updated"],
"secret": "generated-secret-key",
"active": true
}
}
Important: Save the secret key! You’ll need it to verify webhook signatures.
If you’re migrating from Xano:
http://your-server:3000/api/incoming-webhooks/xanoSend a test webhook event:
curl -X POST http://localhost:3000/api/webhooks/trigger \
-H "Content-Type: application/json" \
-d '{
"event": "user.created",
"data": {
"userId": "123",
"email": "test@example.com"
}
}'
Check the delivery status of your webhooks:
curl http://localhost:3000/api/webhooks/{webhook-id}/deliveries
GET /api/webhooks - List all webhooksPOST /api/webhooks - Register a new webhookGET /api/webhooks/:id - Get webhook detailsPUT /api/webhooks/:id - Update a webhookDELETE /api/webhooks/:id - Delete a webhookGET /api/webhooks/:id/deliveries - View delivery historyGET /api/webhooks/events/types - List available event typesPOST /api/webhooks/trigger - Trigger a test eventPOST /api/incoming-webhooks/:service - Receive external webhooksuser.created - New user createduser.updated - User information updateduser.deleted - User deletedauth.login - User logged inauth.logout - User logged outdocument.uploaded - Document uploadeddocument.processed - Document processing completedaccessibility.request - Accessibility feature requestedsync.started - Synchronization startedsync.completed - Synchronization completedai.process.started - AI processing startedai.process.completed - AI processing completedWhen you receive a webhook, verify the signature:
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)
);
}
// In your webhook handler:
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
if (verifyWebhook(payload, signature, YOUR_SECRET)) {
// Process webhook
console.log('Valid webhook received:', req.body);
res.status(200).send('OK');
} else {
res.status(401).send('Invalid signature');
}
});
To receive webhooks from Xano:
Endpoint: POST /api/incoming-webhooks/xano
Xano sends:
{
"event": "record.created",
"table": "users",
"data": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
}
}
The system automatically logs and processes these events.
Add to your .env file:
WEBHOOK_SECRET=your-webhook-secret-key-here
XANO_WEBHOOK_SECRET=your-xano-webhook-secret
GET /api/webhooks/:idGET /api/webhooks/:id/deliveriesUse tools like ngrok to expose your local server:
ngrok http 3000
Then use the ngrok URL as your webhook URL.