Saltar al contenido principal

Crear un webhook

POST/v1/webhooks

Para desarrolladores

Descripción​

Registra un endpoint que recibe los eventos de los correos de la instancia. La respuesta incluye el secreto de firma (whsec_…) con el que se firman las entregas, y es la única vez que se entrega.

El formato de las entregas, la verificación de la firma y los reintentos están en Webhooks.

Autenticación​

Authorizationbearer tokenheaderobligatorio
API key con scope webhooks:write. Formato: Bearer <API_KEY>.
X-Instance-Slugstringheaderobligatorio
Identificador de su instancia. Ver Autenticación.

Request​

Body:

{
"name": "CRM de ventas",
"url": "https://hooks.example.com/fidelizador",
"events": ["mail.sent", "mail.bounced"],
"is_active": true
}
namestringobligatorio
1–255 caracteres.
urlstringobligatorio
Endpoint que recibe las entregas, hasta 1.024 caracteres. Debe ser https://, sin usuario ni contraseña, y su host debe resolver a direcciones públicas. Ver Requisitos del endpoint.
eventsstring[], enum: `mail.sent | mail.bounced | mail.dropped | mail.opened | mail.clicked | mail.unsubscribed | mail.resubscribed | mail.complained | mail.replied` | null
Tipos de evento que recibe; al menos uno si se envía la lista, y los repetidos se ignoran. Si se omite o es null, recibe todos.
is_activeboolean
false crea el webhook pausado. Default: true.

Response​

201 CreatedDevuelve el objeto creado. El header Location trae su URL (ver Headers).
idintegersiempre presente
Identificador del webhook creado.
namestringsiempre presente
Nombre del webhook.
urlstringsiempre presente
Endpoint que recibe las entregas.
eventsstring[] | nullsiempre presente
Los tipos de evento, sin repetidos. null recibe todos.
is_activebooleansiempre presente
false si el webhook está pausado.
last_success_atstring (date-time) | nullsiempre presente
null hasta la primera entrega exitosa.
last_failure_atstring (date-time) | nullsiempre presente
null hasta la primera entrega fallida.
last_status_codeinteger | nullsiempre presente
null hasta la primera entrega.
consecutive_failuresintegersiempre presente
0 al crear.
failing_sincestring|nullsiempre presente
Momento del primer fallo de la racha en curso, o null si la última entrega fue exitosa.
auto_paused_atstring (date-time) | nullsiempre presente
null al crear.
previous_secret_expires_atstring (date-time) | nullsiempre presente
null al crear: todavía no hubo una rotación.
created_atstring (date-time)siempre presente
Fecha y hora de creación.
updated_atstring (date-time)siempre presente
Fecha y hora de la última modificación.
secretstringsiempre presente
Secreto de firma. Solo se entrega en esta respuesta.

Errores​

CódigoCuándo
402Crear el webhook supera la cantidad de webhooks que permite el plan (plan_webhooks_limit_exceeded).
422El body no es válido, o la URL no cumple los requisitos: errors[].code es webhook_url_insecure si no usa https, o webhook_url_not_allowed si no resuelve a una dirección pública.

Detalle completo en Errores de negocio y Errores genéricos.

Notas
  • Guarde el secreto de inmediato: no se puede recuperar después. Si lo pierde, rótelo con POST /v1/webhooks/{id}/rotate-secret.
  • El secreto lo genera la plataforma. Un campo secret en el body se ignora, igual que cualquier otro campo no documentado.
  • El cupo del plan cuenta todos los webhooks de la instancia, activos o pausados.
  • Para comprobar que el endpoint recibe y verifica la firma sin esperar un evento real, envíe un evento de prueba con POST /v1/webhooks/{id}/test.
Request
curl -X POST "https://$API_HOST/v1/webhooks" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
-H "Content-Type: application/json" \
-d '{
"name": "CRM de ventas",
"url": "https://hooks.example.com/fidelizador",
"events": [
"mail.sent",
"mail.bounced"
]
}'
Response
{
"id": 3,
"name": "CRM de ventas",
"url": "https://hooks.example.com/fidelizador",
"events": [
"mail.sent",
"mail.bounced"
],
"is_active": true,
"last_success_at": null,
"last_failure_at": null,
"last_status_code": null,
"consecutive_failures": 0,
"failing_since": null,
"auto_paused_at": null,
"previous_secret_expires_at": null,
"created_at": "2026-09-14T10:00:00Z",
"updated_at": "2026-09-14T10:00:00Z",
"secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
}