Webhooks API
Webhooks API
Endpoints for managing webhook subscriptions. All webhook endpoints require the PRO plan and the config:manage permission (Owner only).
Available Events:
quote.created— A new quote was createdquote.status_changed— A quote's status was updatedquote.sent— A quote was shared via emailclient.created— A new client was addedproduct.created— A new product was added
Signature Verification: Every webhook delivery includes an X-Cotizera-Signature header (HMAC-SHA256) and an X-Cotizera-Event header with the event name.
List Webhooks
GET /api/webhooks
Permission: config:manage | Plan: PRO
List all webhooks for the current tenant, including delivery counts.
Response 200 OK:
[
{
"id": "clxyz...",
"url": "https://mi-servidor.mx/webhook",
"events": ["quote.created", "quote.status_changed"],
"secret": "whsec_abc123...",
"isActive": true,
"tenantId": "...",
"createdAt": "2026-03-01T10:00:00.000Z",
"updatedAt": "2026-03-15T10:00:00.000Z",
"_count": { "deliveries": 47 }
}
]Create Webhook
POST /api/webhooks
Permission: config:manage | Plan: PRO
Create a new webhook subscription. Returns the generated secret for signature verification.
Request Body:
{
"url": "https://mi-servidor.mx/webhook",
"events": ["quote.created", "client.created"]
}| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | Valid URL for the webhook endpoint |
| events | string[] | Yes | At least one event from the available events list |
Response 201 Created: Returns the created webhook including the secret.
Get Single Webhook
GET /api/webhooks/:id
Permission: config:manage | Plan: PRO
Retrieve a single webhook with delivery count.
Response 200 OK: Returns the webhook object.
Errors:
| Status | Error | When |
|---|---|---|
| 404 | "Webhook no encontrado" | Webhook not found in tenant |
Update Webhook
PUT /api/webhooks/:id
Permission: config:manage | Plan: PRO
Update a webhook's URL, events, or active status. All fields are optional.
Request Body:
{
"url": "https://nuevo-servidor.mx/webhook",
"events": ["quote.created", "quote.status_changed", "client.created"],
"isActive": true
}| Field | Type | Required | Description |
|---|---|---|---|
| url | string | No | New webhook URL |
| events | string[] | No | Updated event list (at least one) |
| isActive | boolean | No | Enable or disable the webhook |
Response 200 OK: Returns the updated webhook.
Delete Webhook
DELETE /api/webhooks/:id
Permission: config:manage | Plan: PRO
Permanently delete a webhook and all its delivery history.
Response 200 OK:
{
"ok": true
}Test Webhook
POST /api/webhooks/:id/test
Permission: config:manage | Plan: PRO
Send a test payload to the webhook URL. The test event is webhook.test and the delivery is recorded in the delivery log. Times out after 5 seconds.
Request Body: None required.
Response 200 OK:
{
"success": true,
"statusCode": 200
}Test Payload Sent:
{
"event": "webhook.test",
"timestamp": "2026-03-31T10:00:00.000Z",
"data": { "message": "Este es un evento de prueba" }
}Errors:
| Status | Error | When |
|---|---|---|
| 404 | "Webhook no encontrado" | Webhook not found |
| 502 | "No se pudo conectar con el endpoint" | Connection failed or timed out |
Delivery Log
GET /api/webhooks/:id/deliveries
Permission: config:manage | Plan: PRO
Retrieve paginated delivery history for a webhook.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number (default: 1) |
Response 200 OK:
{
"data": [
{
"id": "clxyz...",
"webhookId": "...",
"event": "quote.created",
"payload": { ... },
"statusCode": 200,
"responseBody": "OK",
"deliveredAt": "2026-03-31T10:00:01.000Z",
"createdAt": "2026-03-31T10:00:00.000Z"
}
],
"total": 47,
"page": 1,
"totalPages": 3
}