Webhooks
Recibir eventos firmados en tu servidor, con reintentos y verificación HMAC.
Antes de empezar
- Un endpoint HTTPS público
- Un webhook creado en Configuración, Desarrolladores
Tinkay envía un POST con Content-Type: application/json cada vez que ocurre un evento al que te suscribiste. Hay 126 eventos disponibles: mirá la referencia completa.
Tu endpoint tiene que responder un 2xx dentro de 10 segundos. Todo lo que tarde más se considera una falla y entra en la cola de reintentos.
Respondé 200 apenas recibís el evento y hacé el trabajo pesado en una cola. Es la diferencia entre una integración estable y una que se cae en los picos.
Crear el webhook
- Entrá a Configuración, Desarrolladores, Webhooks y tocá
Nuevo webhook. - Pegá la URL HTTPS de tu endpoint.
- Elegí los eventos. Podés seleccionar un grupo entero o suscribirte a todos con
*. - Guardá y copiá el signing secret (
whsec_...). Se muestra una sola vez. - Tocá
Enviar pruebapara confirmar que tu endpoint responde.
Formato de la entrega
Cada entrega trae los headers de identificación y firma, y el evento completo en el cuerpo.
Headers de la entrega
| Campo | Tipo | Descripción |
|---|---|---|
X-Tinkay-Event | string | Nombre del evento. |
X-Tinkay-Delivery | string | Identificador de la entrega. Cambia en cada reintento. |
X-Tinkay-Attempt | number | Número de intento, empezando en 1. |
X-Tinkay-Timestamp | number | Epoch en segundos usado para firmar. |
X-Tinkay-Signature | string | sha256= seguido del HMAC en hexadecimal. |
POST /hooks/tinkay HTTP/1.1Content-Type: application/jsonUser-Agent: Tinkay-Webhooks/1.0X-Tinkay-Event: conversation.createdX-Tinkay-Delivery: dlv_7c1a93f0X-Tinkay-Attempt: 1X-Tinkay-Timestamp: 1772668800X-Tinkay-Signature: sha256=9f2ab7c41d0e83ba5c1904e6f8b2d7a3c5e1f0d9b8a7c6e5d4f3a2b1c0d9e8f7Un endpoint mínimo
Este ejemplo valida la firma, responde rápido y encola el trabajo real.
import express from "express";import crypto from "node:crypto";const app = express();const SECRET = process.env.TINKAY_WEBHOOK_SECRET;// El cuerpo crudo es obligatorio: JSON.stringify cambia bytes y rompe la firma.app.post("/hooks/tinkay", express.raw({ type: "application/json" }), (req, res) => { if (!verify(req)) return res.status(400).send("invalid signature"); const event = JSON.parse(req.body.toString("utf8")); res.sendStatus(200); // responder primero queue.push(event); // procesar después});function verify(req) { const timestamp = req.get("X-Tinkay-Timestamp"); const signature = (req.get("X-Tinkay-Signature") || "").replace("sha256=", ""); if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; const expected = crypto .createHmac("sha256", SECRET) .update(`${timestamp}.${req.body.toString("utf8")}`) .digest("hex"); const a = Buffer.from(expected, "hex"); const b = Buffer.from(signature, "hex"); return a.length === b.length && crypto.timingSafeEqual(a, b);}Qué eventos elegir
De los 126 eventos, 80 sirven además como disparadores de automatizaciones dentro de Tinkay. Si lo que querés hacer es asignar, etiquetar o responder, conviene una automatización antes que un webhook.
Suscribite solo a lo que vas a procesar: cada evento extra es tráfico y latencia en tu servidor.
- Sincronizar un CRM:
contact.created,contact.updated,contact.merged,contact.deleted. - Alertas internas:
ai.handoff,conversation.sla_breached,channel.error,invoice.payment_failed. - Data warehouse:
conversation.closed,conversation.rated,ai.replied,ticket.resolved. - Cumplimiento:
login.failed,api_key.revoked,member.role_changed,team.permissions_changed.
Probar en desarrollo
Exponé tu servidor local con un túnel y usá Enviar prueba en Configuración, Desarrolladores. Podés elegir cualquier evento del catálogo y recibirlo con datos realistas.
ngrok http 3000# usá la URL https que te da como destino del webhookCómo saber que quedó bien
- El endpoint responde 200 al botón `Enviar prueba`.
- La firma calculada coincide con el header `X-Tinkay-Signature`.
- Un evento real, por ejemplo cerrar una conversación, llega en menos de un segundo.
