Webhooks
Recibe eventos firmados de SociaHive en tu propio endpoint HTTPS y verifícalos.
Un webhook envía un POST HTTPS a tu endpoint cuando ocurre algo en tu cuenta de SociaHive: una publicación programada se publica o falla, una automatización se inicia para alguien o termina con un error, una plantilla de WhatsApp se aprueba o se rechaza.
Agrega uno en el panel, en Integraciones → Webhooks, o con la API REST (/api/v1/webhooks, scopes webhooks:read y webhooks:write).
Cualquiera puede configurar un webhook, pero los eventos solo se entregan mientras tu plan incluya acceso a la API (la prueba gratis y todos los planes de pago). Los webhooks que creaste se conservan y vuelven a enviar eventos cuando cambias a un plan superior.
Límites por plan
| Plan | Webhooks |
|---|---|
| Gratis | 0 |
| Creator | 2 |
| Studio | 5 |
| Pro | 10 |
| Agency | 50 |
El límite abarca integration_type webhook, custom y n8n. Las suscripciones de Zapier y Make (zapier, make) no cuentan para él.
Eventos
| Evento | Cuándo | Campos de data |
|---|---|---|
post.published | Una publicación programada salió en una plataforma | postId, platform, accountId, platformPostId |
post.failed | Una publicación programada no se pudo publicar en una plataforma | postId, platform, accountId, error |
flow.triggered | Una automatización se inició para alguien | flowId, executionId, platform, accountId, senderId |
flow.error | Una automatización se detuvo con un error | flowId, executionId (cuando se conoce), flowName, errorMessage, errorNodeId |
whatsapp.template_status | Meta aprobó, rechazó o pausó una plantilla de WhatsApp | accountId, templateName, templateLanguage, event, reason |
post.review_decision | Un cliente aprobó una publicación, pidió cambios o dejó un comentario en un enlace de revisión | postId, reviewLinkId, kind (approved, changes_requested, comment), reviewerName, comment (cuando existe) |
post.plug_fired | Se activó un plug en una publicación (una republicación o un comentario) | plug_id, post_id, account_id, platform, metric, threshold, value, action |
Una publicación que sale en tres plataformas envía tres eventos post.published, uno por plataforma.
post.review_decision requiere enlaces de revisión para clientes (Studio, Pro y Agency) y post.plug_fired requiere plugs (todos los planes de pago). Suscribirte a uno que tu plan no incluye devuelve 400.
El contacto en los eventos sobre una persona
flow.triggered, flow.error (cuando indica a la persona), los eventos de suscriptores del boletín y data.collected también incluyen contact, la persona tal como SociaHive la conoce cuando se envía el evento:
Los campos personalizados usan como clave sus nombres tal como los ves en SociaHive. contact no se envía cuando SociaHive todavía no tiene un contacto para la persona.
Aceptados, aún no se envían
Puedes suscribirte a estos eventos con la API (la app de Make y el nodo de n8n los ofrecen), pero SociaHive todavía no los envía. Un webhook suscrito a ellos los recibirá cuando se lancen, sin que tengas que cambiar nada.
| Evento | Significado previsto |
|---|---|
message.received | Alguien envió un mensaje directo a una de tus cuentas |
comment.received | Alguien comentó en una de tus publicaciones |
flow.completed | Una automatización terminó para alguien |
account.disconnected | Se desconectó una cuenta conectada |
El panel solo ofrece los eventos que se envían hoy.
Limitar un webhook a algunas cuentas
Define account_ids (ID de cuentas conectadas, de GET /api/v1/connected-accounts) para recibir solo los eventos de esas cuentas. Déjalo vacío para recibir los de todas. Los eventos nombran su cuenta como accountId (post.plug_fired: account_id). Los eventos que no nombran una cuenta (flow.error, post.review_decision) siempre se envían.
Formato de la solicitud
Responde con cualquier estado 2xx en un máximo de 10 segundos. Haz el trabajo lento después de responder.
Verificar la firma
Cada solicitud se firma con el secreto de firma del webhook, que se muestra una sola vez al crear el webhook (y de nuevo solo cuando generas un secreto nuevo).
X-SociaHive-Signature tiene la forma t=<unix seconds>,v1=<hex>. v1 es el HMAC-SHA256 de la cadena <t>.<raw request body>, con tu secreto como clave.
- Lee el cuerpo sin procesar antes de analizar el JSON; volver a serializarlo cambia los bytes.
- Calcula el HMAC y compáralo con
v1en tiempo constante. - Rechaza la solicitud si
tse aleja más de cinco minutos de la hora actual. Esto impide los ataques de repetición (replay).
Entrega y reintentos
- La entrega es al menos una vez. El mismo evento puede llegar más de una vez; usa
id(también enX-SociaHive-Event-Id) para omitir los duplicados. - Una entrega fallida (una respuesta distinta de
2xx, un tiempo de espera agotado o la falta de conexión) se intenta hasta 5 veces en total, con esperas cada vez mayores entre intentos. - Cuando 3 eventos seguidos fallan en todos sus reintentos, el webhook se desactiva y recibes una notificación en la app. Corrige el endpoint y vuelve a activarlo; el conteo de fallos empieza de nuevo desde cero.
- No se garantiza que los eventos lleguen en orden. Usa
timestampsi el orden importa. - Los endpoints deben ser URL
httpspúblicas. Las direcciones privadas e internas se rechazan.
Probar un webhook
El botón Enviar prueba del panel envía de inmediato un evento firmado y muestra el código de estado y el tiempo de respuesta:
Funciona con un webhook desactivado, así que puedes comprobar un endpoint antes de volver a activarlo. Puedes enviar 5 pruebas por minuto.
API REST
| Método | Ruta | Qué hace |
|---|---|---|
GET | /api/v1/webhooks | Lista tus webhooks, incluidos los desactivados |
POST | /api/v1/webhooks | Crea uno: target_url, events, y de forma opcional integration_type (webhook por defecto, custom, n8n, make, zapier) y account_ids. La respuesta incluye signing_secret |
PATCH | /api/v1/webhooks/{id} | Cambia target_url, events, account_ids o active (true lo vuelve a activar y reinicia el conteo de fallos) |
DELETE | /api/v1/webhooks/{id} | Lo elimina. Después puedes agregar de nuevo la misma URL |
Cada webhook de una respuesta incluye last_delivery_at, last_status (el estado HTTP, o null cuando el endpoint no respondió) y last_error.