API de Webhooks
Los webhooks permiten que la plataforma notifique a sus otros sistemas en el momento en que ocurre algo: un nuevo contacto, una respuesta, una cita reservada y más. Esta API gestiona las suscripciones en sí: qué URL reciben qué eventos. Para saber cómo recibir y verificar las cargas útiles que obtiene su endpoint, consulte Webhooks.
Todas las rutas a continuación son relativas a la URL base de la API:
https://api.youraiconnector.com/v1
Cada solicitud debe estar autenticada. Consulte Autenticación para conocer los cuatro métodos aceptados. Los ejemplos aquí utilizan el encabezado X-API-Key (y una forma de parámetro de consulta para cURL).
Nota: Los webhooks deben estar habilitados para su cuenta. Si no lo están, estos endpoints devuelven un 403.
Cómo se direccionan las suscripciones
Cada suscripción tiene un id y un name opcional. Cualquiera de los dos puede usarse como {webhookId} en la ruta para actualizar, eliminar, probar, verificar el estado y volver a habilitar.
Prefiera el nombre. Los ID de suscripción son posicionales, por lo que pueden cambiar después de que se elimine otra suscripción. Si establece un
nameestable al crear una suscripción, diríjase a ella por su nombre para evitar sorpresas.
Listar suscripciones
GET /webhooks
cURL
curl "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/webhooks",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Respuesta
{
"success": true,
"webhooks": [
{
"id": "0",
"name": "Order updates hook",
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"subscribed_to_tags": [],
"created_at": "2026-06-09T12:00:00.000Z",
"signing_enabled": true,
"signing_secret_created_at": "2026-07-15T09:30:00.000Z",
"retries_enabled": true,
"enabled": true,
"apply_to_sub_accounts": false
}
]
}
signing_enabled y retries_enabled son opciones de suscripción individuales, ambas desactivadas a menos que las actives. Consulta Cargas útiles firmadas y Reintentos.
apply_to_sub_accounts es la opción de herencia de agencia: consulte Una suscripción para todas las cuentas de cliente. Desactivada de forma predeterminada e inerte en cuentas que no tienen cuentas de cliente.
enabled es el interruptor de encendido/apagado de la suscripción; consulte Desactivación de una suscripción. Las suscripciones desactivadas siguen apareciendo en la lista aquí.
El secreto de firma en sí nunca se incluye aquí; léelo desde GET /webhooks/{id}/signing-secret.
Listar tipos de eventos suscribibles
Devuelve las cadenas exactas que puede usar en subscribed_to. Utilice esto para descubrir nombres de eventos válidos en lugar de codificarlos de forma rígida.
GET /webhooks/events
cURL
curl "https://api.youraiconnector.com/v1/webhooks/events" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/events", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/webhooks/events",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Respuesta
La respuesta es {"success": true, "events": [...]}, donde events actualmente contiene 22 cadenas exactas: Contact Created, Human Alerted, Appointment Booked, Replies, Reads, Deliveries, Credits Spent, Credits Recharged, Low Credit Balance, Contact Paused, Contact Do Not Disturb, Contact Unarchived, New Message, Contact Resumed, Chat Concluded, Task Created, Task Updated, Task Completed, Daily Summary Created, Channel Connected, Broadcast Started y Broadcast Completed (Channel Connected se acepta en subscribed_to, pero actualmente nada lo emite, así que no desarrolle basándose en ello).
Para saber qué significa cada evento y el código event que envía en la carga útil, consulte Los 22 eventos de webhook. Este endpoint es la lista autorizada en cualquier momento; léalo en tiempo real en lugar de codificar los nombres de forma rígida.
Crear una suscripción
POST /webhooks
| Campo | Obligatorio | Descripción |
|---|---|---|
url |
Sí | URL HTTPS que recibirá las cargas útiles de eventos a través de POST. Debe ser accesible públicamente. |
subscribed_to |
Sí | Una matriz no vacía de nombres de eventos (consulte /webhooks/events). |
name |
No | Un nombre para mostrar. También se puede usar como {webhookId} más adelante. El valor predeterminado es un nombre con marca de tiempo. |
subscribed_to_tags |
No | IDs de etiquetas que limitan qué etiquetas producen una notificación de resumen de conversación. No limita los eventos de la suscripción a esas etiquetas; para recibir una solicitud cuando se aplica una etiqueta específica, establezca una URL de webhook en esa etiqueta en la pestaña Etiquetas del agente (o campaña). |
retries_enabled |
No | Booleano, el valor predeterminado es false. Opte por reintentos de entregas fallidas. |
generate_signing_secret |
No | Booleano, el valor predeterminado es false. Genere un secreto de firma HMAC con la suscripción. El secreto se devuelve una vez, como un signing_secret de nivel superior en la respuesta. |
enabled |
No | Booleano, el valor predeterminado es true. Pase false para crear la suscripción desactivada. Consulte Desactivación de una suscripción. |
apply_to_sub_accounts |
No | Booleano, el valor predeterminado es false. En una cuenta de agencia, true hace que esta suscripción también reciba eventos de todas las cuentas de cliente; consulte Una suscripción para todas las cuentas de cliente. |
Reglas de URL: La URL debe usar
https://y ser accesible públicamente. Las direccioneshttp://simples,localhost, direcciones de red privada y direcciones internas de la plataforma se rechazan con un400.
cURL
curl -X POST "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"name": "Order updates hook"
}'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://hooks.example.com/incoming",
subscribed_to: ["Contact Created", "Replies"],
name: "Order updates hook",
}),
});
const data = await res.json();
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/webhooks",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"name": "Order updates hook",
},
)
data = res.json()
Respuesta
{
"success": true,
"webhook_id": "1",
"webhook": {
"id": "1",
"name": "Order updates hook",
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"subscribed_to_tags": [],
"created_at": "2026-06-09T12:00:00.000Z"
}
}
Actualizar una suscripción
Proporcione al menos uno de los siguientes: url, subscribed_to, name, subscribed_to_tags, retries_enabled, enabled o apply_to_sub_accounts. Los campos omitidos conservan sus valores actuales. subscribed_to y subscribed_to_tags son reemplazos, no fusiones.
PUT /webhooks/{webhookId}
Actualizar una suscripción nunca altera su secreto de firma; gestiónalo a través de las rutas de secreto de firma.
Cuando la URL cambia, la entrega para la nueva URL se vuelve a habilitar automáticamente, lo que le da un nuevo comienzo a un endpoint que fallaba anteriormente.
cURL
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/Order%20updates%20hook" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/v2/incoming",
"subscribed_to": ["Replies", "Chat Concluded"]
}'
JavaScript
const res = await fetch(
`https://api.youraiconnector.com/v1/webhooks/${encodeURIComponent("Order updates hook")}`,
{
method: "PUT",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://hooks.example.com/v2/incoming",
subscribed_to: ["Replies", "Chat Concluded"],
}),
}
);
const data = await res.json();
Python
import requests
res = requests.put(
"https://api.youraiconnector.com/v1/webhooks/Order updates hook",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"url": "https://hooks.example.com/v2/incoming",
"subscribed_to": ["Replies", "Chat Concluded"],
},
)
data = res.json()
Respuesta
{
"success": true,
"webhook_id": "0",
"webhook": {
"id": "0",
"name": "Order updates hook",
"url": "https://hooks.example.com/v2/incoming",
"subscribed_to": ["Replies", "Chat Concluded"],
"subscribed_to_tags": [],
"created_at": "2026-06-09T12:00:00.000Z"
}
}
Un id o nombre desconocido devuelve 404 con { "success": false, "error": "Webhook not found" }.
Eliminar una suscripción
Elimina la suscripción para que su URL deje de recibir cargas útiles. Sus contadores de estado de entrega se restablecen, por lo que volver a añadir la misma URL más tarde comienza con un registro limpio.
DELETE /webhooks/{webhookId}
cURL
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0", {
method: "DELETE",
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.delete(
"https://api.youraiconnector.com/v1/webhooks/0",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Respuesta
{
"success": true
}
Enviar una carga útil de prueba
Envía una carga útil de muestra a la URL de la suscripción para que pueda verificar su receptor de extremo a extremo. Opcionalmente, pase un event para controlar qué tipo de evento simula la muestra. Las entregas de prueba nunca afectan a los contadores de estado de la suscripción.
POST /webhooks/{webhookId}/test
La respuesta siempre devuelve 200 e informa del resultado con un indicador delivered: una prueba fallida no devuelve un estado de error. Cuando delivered es false, la respuesta incluye los detalles del error.
| Campo | Obligatorio | Descripción |
|---|---|---|
event |
No | Tipo de evento a simular (debe ser uno de /webhooks/events). El valor predeterminado es un evento de entrega. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/test?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "event": "Contact Created" }'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/test", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ event: "Contact Created" }),
});
const data = await res.json();
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/webhooks/0/test",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"event": "Contact Created"},
)
data = res.json()
Respuesta (entregada)
{
"success": true,
"webhook_id": "0",
"delivered": true
}
Respuesta (fallida)
{
"success": true,
"webhook_id": "0",
"delivered": false,
"failure_type": "permanent",
"status_code": 404,
"error_message": "Request failed with status code 404"
}
failure_type es uno de permanent, temporary, timeout, network o unknown.
Comprobar el estado de la entrega
Devuelve el registro del estado de entrega para la URL de la suscripción: cuántas entregas han tenido éxito y cuántas han fallado, si la entrega está actualmente pausada tras fallos repetidos y los detalles del fallo más reciente. Devuelve "health": null cuando aún no se ha intentado ninguna entrega.
GET /webhooks/{webhookId}/health
cURL
curl "https://api.youraiconnector.com/v1/webhooks/0/health" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/health", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/webhooks/0/health",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Respuesta
{
"success": true,
"webhook_id": "0",
"url": "https://hooks.example.com/incoming",
"health": {
"consecutive_failures": 0,
"total_failures": 2,
"total_successes": 120,
"is_disabled": false,
"disabled_at": null,
"disabled_reason": null,
"last_failure": null,
"last_success_at": "2026-06-09T12:00:00.000Z",
"created_at": "2026-05-01T08:00:00.000Z",
"updated_at": "2026-06-09T12:00:00.000Z"
}
}
Cuando is_disabled es true, la entrega a la URL se ha pausado automáticamente tras fallos repetidos. Repare su receptor y, a continuación, vuelva a habilitarlo (abajo).
Volver a habilitar la entrega
Reanuda la entrega para un webhook cuya URL se pausó automáticamente tras fallos repetidos. Esto restablece el indicador de pausa y los contadores de fallos, pero no intenta realizar una entrega; utilice el endpoint de prueba después para confirmar que su receptor vuelve a funcionar correctamente.
POST /webhooks/{webhookId}/reenable
cURL
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/reenable?apiKey=YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/reenable", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/webhooks/0/reenable",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Respuesta
{
"success": true,
"webhook_id": "0"
}
Desactivación de una suscripción
enabled es el propio interruptor de encendido/apagado de la suscripción. Desactivarlo detiene las entregas mientras mantiene intactos la URL, la lista de eventos y el secreto de firma.
# Off
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'
# Back on
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
- Si está ausente, significa encendido. Una suscripción creada antes de que existiera este campo no tiene ningún valor
enabledalmacenado y se entrega normalmente.GET /webhookssiempre informa un booleano concreto. - Las suscripciones desactivadas siguen apareciendo en la lista de
GET /webhooks; así es como las encuentra para volver a activarlas. - Un reintento en cola antes de la desactivación no se reanuda: el reintento vuelve a leer la suscripción en el momento del envío y la descarta si está desactivada.
- Nada de lo suprimido mientras estaba desactivado se vuelve a reproducir cuando la vuelve a activar.
Distinto de la desactivación automática tras fallos repetidos, que es reportada por
GET /webhooks/{id}/healthcomois_disabledy se borra conPOST /webhooks/{id}/reenable.enabledes el interruptor de la cuenta;is_disabledes el nuestro. Ninguno anula al otro: una suscripción debe estar tanto activada como no desactivada automáticamente para realizar la entrega.
Una suscripción para todas las cuentas de cliente (agencias)
En una cuenta de agencia, establezca apply_to_sub_accounts: true en una suscripción (al momento de la creación o mediante PUT) y también recibirá eventos que ocurran en cada una de las cuentas de cliente de la agencia; un endpoint cubre toda la agencia, en lugar de volver a crear la suscripción en cada cuenta de cliente.
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"apply_to_sub_accounts": true}'
Cómo funciona:
- El bloque
userdistingue las cuentas. El bloqueuserde cada carga útil identifica la cuenta en la que realmente ocurrió el evento, por lo que su receptor puede enrutar por cliente. - La configuración propia de la suscripción de la agencia se aplica en todas partes. Su lista de eventos, secreto de firma y opción de reintento también se utilizan para las entregas heredadas.
- La propia suscripción de una cuenta de cliente a la misma URL tiene prioridad. Si una cuenta de cliente tiene su propia suscripción apuntando a la misma URL, esa es la que se utiliza para los eventos de esa cuenta; el mismo evento nunca se entrega dos veces al mismo endpoint.
- Las cuentas de cliente no la ven. Las suscripciones heredadas no aparecen en la lista de webhooks propia de una cuenta de cliente, y el cliente no puede desactivarlas; solo la agencia las gestiona.
- El estado de la entrega se rastrea por cuenta de cliente. Un endpoint que sigue fallando se deshabilita automáticamente para la cuenta cuyas entregas fallaron, no para toda la agencia.
subscribed_to_tagsno se hereda. La lista de etiquetas hace referencia a las etiquetas propias de la agencia, que no existen en las cuentas de cliente; la limitación del resumen de conversación solo se aplica a los eventos propios de la agencia.- Inerte en otros lugares. En una cuenta sin cuentas de cliente, la marca se almacena correctamente y no hace nada.
Encabezados en cada entrega
Estos tres encabezados se envían en cada entrega, independientemente de si la suscripción está firmada o no:
| Encabezado | Significado |
|---|---|
X-Webhook-Delivery |
ID estable para el evento lógico. Idéntico en todos los reintentos; úselo para deduplicar. |
X-Webhook-Attempt |
Número de intento basado en 1. |
X-Webhook-Event |
El nombre del evento. |
Cargas útiles firmadas
La firma es opcional, está desactivada de forma predeterminada y se configura por suscripción. Cuando una suscripción tiene un secreto de firma, cada entrega incluye dos encabezados adicionales además de los tres enviados en cada entrega (X-Webhook-Delivery, X-Webhook-Attempt y X-Webhook-Event):
| Encabezado | Significado |
|---|---|
X-Webhook-Signature |
v1=<hex> — HMAC-SHA256 de la cadena "<timestamp>.<raw request body>", codificada con el secreto de firma por webhook que usted genera y rota en GET/POST/DELETE /v1/webhooks/{webhookId}/signing-secret. |
X-Webhook-Timestamp |
Hora de envío, en segundos Unix. Vinculada a la firma, por lo que no se puede alterar de forma independiente. |
Para verificar, vuelva a calcular el HMAC-SHA256 sobre el cuerpo sin procesar con su secreto y compárelo con el encabezado. Verifique contra el cuerpo de la solicitud sin procesar. Volver a serializar el JSON analizado cambia los bytes y rompe la comparación. Rechace las entregas cuya marca de tiempo esté fuera de una ventana de frescura (300 s es un valor predeterminado razonable) para evitar la reproducción, y compare con una función segura para el tiempo.
Consulta Cargas útiles firmadas para ver ejemplos completos de verificación en Node y Python.
La firma no es lo mismo que la autenticación de API. La API REST en sí se autentica con claves de API en lugar de OAuth (OAuth 2.1 existe para servidores MCP que usted registra como herramientas de bot), y aún no hay paquetes SDK oficiales de npm o PyPI; llame a los endpoints con cualquier cliente HTTP.
Leer el secreto de firma
GET /webhooks/{id}/signing-secret
curl "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
Respuesta
{
"success": true,
"webhook_id": "0",
"signing_enabled": true,
"signing_secret": "whsec_1a2b3c...",
"signing_secret_created_at": "2026-07-15T09:30:00.000Z"
}
Cuando la firma está desactivada, signing_enabled es false y signing_secret es null.
Generar o rotar el secreto de firma
POST /webhooks/{id}/signing-secret
Crea un secreto (activando la firma) o reemplaza el existente. Devuelve el nuevo secreto.
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
Respuesta
{
"success": true,
"webhook_id": "0",
"signing_enabled": true,
"signing_secret": "whsec_9f8e7d...",
"signing_secret_created_at": "2026-07-15T10:00:00.000Z"
}
La rotación entra en vigor inmediatamente: la siguiente entrega se firma únicamente con el nuevo secreto. Acepte ambos secretos brevemente mientras implementa el cambio en un endpoint activo.
También puede generar un secreto al momento de la creación pasando "generate_signing_secret": true a POST /webhooks; la respuesta incluirá entonces un campo signing_secret de nivel superior.
Desactivar la firma
DELETE /webhooks/{id}/signing-secret
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
Respuesta
{
"success": true,
"webhook_id": "0",
"signing_enabled": false
}
Las tres rutas de secretos de firma requieren el permiso de edición de integraciones, incluido
GET; el secreto es una credencial que puede falsificar entregas, por lo que no se expone a roles de solo lectura.
Reintentos
Opcional, desactivado por defecto y configurado por suscripción mediante el booleano retries_enabled en POST /webhooks o PUT /webhooks/{id}.
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"retries_enabled": true}'
Cuando está habilitado, una entrega fallida se reintenta a los 1m, 5m, 30m y 2h después del primer intento (aproximadamente 2h 40m de cobertura).
- Reintentado: respuestas 5xx, tiempos de espera agotados y errores de conexión.
- No reintentado: cualquier 4xx. El receptor está rechazando la solicitud en sí, por lo que volver a enviarla sin cambios solo reproduce el rechazo.
Los reintentos hacen posible la entrega duplicada: un endpoint que procesó un evento pero agotó el tiempo de espera antes de responder lo verá de nuevo. Utilice X-Webhook-Delivery para la deduplicación, ya que es constante en todos los intentos. Por este motivo, los reintentos son opcionales.
Los contadores de delivery-health cuentan una entrega completa, no cada intento: un fallo se registra solo una vez que se agotan todos los reintentos, por lo que habilitar los reintentos no hace que el disparador de desactivación automática se active antes.
Errores
Todos los errores utilizan el sobre estándar:
{
"success": false,
"error": "Webhook not found"
}
Casos comunes: una URL no permitida, un subscribed_to vacío/inválido o campos faltantes devuelven 400; un id o nombre desconocido devuelve 404; y un 403 significa que los webhooks no están habilitados para su cuenta. Consulte Errores para ver la lista completa.
Próximos pasos
- Webhooks (recepción de cargas útiles) — configure su receptor y comprenda la estructura de la carga útil.
- Autenticación — las cuatro formas de autenticar una solicitud.
- Errores y límites de tasa — códigos de estado y el límite de 300 solicitudes/min.