Saltar al contenido

Apartado 5 de 12 · Sincronizar

Webhooks: que Chatendo te avise

Da de alta un webhook en Chatendo, los ocho eventos que envía, cómo comprobar la firma X-Vertichat-Signature y qué pasa cuando tu servidor no contesta.

Revisado el API 1.11.9 2 min de lectura

En esta página (4)
  1. 5.1 · Dar de alta el aviso
  2. 5.2 · Los ocho eventos de hoy
  3. 5.3 · Comprobar la firma
  4. 5.4 · Contestar rápido

5.1 · Dar de alta el aviso

Necesita el permiso webhooks:manage.

Terminal
curl -s -X POST "$API/webhook-endpoints" \
     -H "Authorization: Bearer $TOKEN" \
     -H 'Accept: application/json' -H 'Content-Type: application/json' \
     -d '{"url":"https://tu-servidor.example/chatendo",
          "events":["message.received","conversation.assigned"]}'

Respuesta (la forma, probada el 22-09-2026; el secreto, recortado y de ejemplo):

JSON
{"id":1,
 "url":"https://tu-servidor.example/chatendo",
 "events":["message.received","conversation.assigned"],
 "active":true,
 "created_at":"2026-09-22T17:18:24Z",
 "signing_secret":"a1b2c3d4…"}

Ese signing_secret es lo único que verás una vez. Guárdalo: sin él no puedes comprobar la firma, y sin comprobar la firma cualquiera puede llamar a tu URL fingiendo ser Chatendo.

La URL tiene que ser pública. Hay guardia anti-SSRF: una dirección interna o de red privada se rechaza con 422 SSRF_BLOCKED. Para desarrollo, usa un túnel público.

5.2 · Los ocho eventos de hoy

Texto
conversation.created      conversation.assigned     conversation.closed
conversation.snoozed      conversation.unsnoozed    message.received
message.status_updated    order.created

Cuerpo de message.received. Los campos son los que manda Chatendo, uno por uno; los valores son de ejemplo:

JSON
{"id": 86934,
 "wamid": "wamid.HBg…",
 "direction": "in",
 "type": "text",
 "body": "¿Seguís teniendo plaza?",
 "conversation_id": 2856,
 "contact_id": 41,
 "created_at": "2026-09-22T17:02:05Z"}

Fíjate en lo que NO trae: ni el teléfono ni el nombre. Con contact_id tienes que dar otra vuelta a GET /contacts/{id} por cada mensaje. Si vas a procesar volumen, cachea la ficha del contacto por contact_id.

5.3 · Comprobar la firma

Cada entrega lleva:

Texto
X-Vertichat-Signature: sha256=<hmac-sha256 del cuerpo crudo, con tu signing_secret>

La cabecera conserva el nombre viejo del producto. Es un identificador, no una errata.

Python
import hmac, hashlib

def firma_valida(cuerpo_crudo: bytes, cabecera: str, secreto: str) -> bool:
    esperada = 'sha256=' + hmac.new(
        secreto.encode(), cuerpo_crudo, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(esperada, cabecera or '')

Dos reglas que no son opcionales:

  1. Sobre el cuerpo SIN parsear. Si lo deserializas y lo vuelves a serializar, un espacio distinto rompe la firma y te pasarás la tarde buscando el fallo donde no está.
  2. Comparación en tiempo constante (compare_digest), nunca ==.

5.4 · Contestar rápido

Hasta 5 intentos con espera creciente. Tras el quinto, la entrega queda en failed.

Devuelve 2xx en cuanto recibas y haz el trabajo después, en una cola tuya. Si procesas antes de contestar y tardas, Chatendo reintenta y te llega el mismo evento otra vez.

Las entregas se consultan en GET /webhook-endpoints/{id}/deliveries, y esa ruta pide webhooks:manage como las demás — devuelve los payloads ya enviados, con teléfonos y textos de clientes dentro. Cambió el 22-09-2026: hasta ese día era la única de las cinco que no lo pedía, y cualquier token del inquilino la leía. Si tu token es anterior y no tiene ese permiso, ahora recibirás 403.

Hoy una entrega fallida no se puede reenviar. Si tu servidor estuvo caído más que los cinco intentos, ese evento se perdió: hay que reconciliar leyendo (§7.3). Es lo primero que cambia (§10).

Escríbenos por WhatsApp Te contesta nuestro agente de IA al momento