Webhooks
Los webhooks notifican cambios de un correo a tu backend. Su administración requiere sesión humana de propietario o administrador; no está disponible para claves de integración. La pantalla Desarrolladores todavía no incluye un formulario para configurarlos.
Configura el destino
La superficie de sesión usa POST /workspaces/{workspaceId}/webhooks, GET de lista/detalle y PATCH /workspaces/{workspaceId}/webhooks/{id}. Las escrituras requieren idempotencia; PATCH requiere además el ETag en If-Match. En el navegador, la fachada /api/workspaces/... aplica sesión, origen y CSRF.
Ejemplo de cuerpo de creación:
{
"url": "https://hooks.example.com/sendiro",
"events": ["email.delivered", "email.bounced", "email.complained"],
"enabled": true
}
Sustituye el destino por un servicio tuyo. Debe usar HTTPS en puerto 443 y resolver a IPv4 público; no se admiten IP literales, destinos privados ni redirecciones. Hay un máximo de 20 endpoints. El secreto se revela una vez al crear, sin volver a aparecer al repetir la operación idempotente.
Catálogo y envelope
Eventos configurables: email.queued, email.submitted, email.submission_unknown, email.delivered, email.bounced, email.complained, email.opened, email.clicked, email.unsubscribed, email.failed y email.suppressed.
El JSON contiene schemaVersion: 1, id, createdAt y event, con id, workspaceId, emailId, kind, occurredAt y recordedAt. No incluye el cuerpo del correo. occurredAt describe el evento; recordedAt, su registro.
Verifica antes de procesar
Lee X-Sendiro-Event-Id, X-Sendiro-Delivery-Id y X-Sendiro-Signature. Esta última tiene formato t=TIMESTAMP,v1=HEX.
Calcula HMAC-SHA256 con el secreto sobre timestamp + "." + rawBody, usando los bytes originales, y compara en tiempo constante. Aplica una ventana de antigüedad del timestamp en tu receptor y rechaza firmas inválidas antes de usar los datos. Parsear y volver a serializar el JSON cambia los bytes firmados.
Rota un secreto de firma
Un administrador puede llamar a
POST /workspaces/{workspaceId}/webhooks/{id}/rotate-secret con sesión humana,
Idempotency-Key y el ETag actual de configuración en If-Match. Para una
renovación programada, envía:
{"mode":"overlap","overlapSeconds":3600,"reason":"Renovación programada del receptor"}
La respuesta revela el nuevo secret una vez e incrementa la revisión del
webhook. Los listados, detalles y reintentos idempotentes no revelan claves.
Guarda de forma segura la primera respuesta; perderla requiere otra rotación
explícita. El solapamiento predeterminado dura una hora, con mínimo de cinco
minutos y máximo de 24 horas. Durante esa ventana, la cabecera es
t=TIMESTAMP,v1=HEX_NUEVA,v1=HEX_ANTERIOR: verifica cada candidato v1 y acepta
si cualquiera coincide con tu clave configurada mediante comparación constante.
Instala la clave nueva antes de secretRotation.overlapExpiresAt y retira la
anterior del receptor. Otra rotación gradual se bloquea mientras haya una activa.
Si la clave está comprometida, envía explícitamente
{"mode":"immediate","reason":"El receptor informó una clave comprometida"}.
Esto revoca inmediatamente todas las claves de firma anteriores, incluso un
solapamiento activo, y puede interrumpir entregas hasta que el receptor instale
la nueva. Quien conserve una clave anterior puede falsificar solicitudes hacia
un receptor que todavía la acepte; retira también del receptor las claves
comprometidas. Las entregas pendientes usan claves vigentes al invocar y
conservan IDs de evento y entrega. Una petición ya enviada no se puede retirar.
Los despliegues de Sendiro no rotan secretos automáticamente.
Confirma y deduplica
Persiste el ID de evento junto con el efecto de negocio en una transacción o aplica idempotencia equivalente. El mismo evento puede llegar más de una vez y fuera de orden; conserva su identidad aunque repita el POST. Devuelve 2xx cuando lo hayas aceptado de forma durable.
Otras respuestas y errores reintentan con espera creciente y presupuesto finito; después el trabajo queda bloqueado para revisión. No hay garantía de llegada eventual ante un fallo permanente. Consulta entregas mediante GET /workspaces/{workspaceId}/webhook-deliveries con sesión administrativa. Deshabilitar cancela pendientes cuando se procesan y no revierte eventos ya recibidos.