Recibir webhooks
Un webhook es AssinaJá llamando a la puerta de su sistema cuando le ocurre algo a
un documento, en lugar de que su sistema tenga que preguntar continuamente. Es una
petición POST que la plataforma hace a una dirección suya.
Esta página es para quien integra AssinaJá con otro programa. Si solo quiere ver qué ha pasado con un documento, use el historial del documento.
Configurar la dirección
Sección titulada «Configurar la dirección»Los webhooks de la organización se configuran en Configuración → Desarrolladores → Webhooks, y solo el Propietario de la organización tiene acceso a esa pestaña. La página tiene tres partes: URL y eventos, Secreto del webhook y, debajo, Entregas.
En URL y eventos:
- En URL del webhook, escriba la dirección de su sistema: «HTTPS, puerto 443 u 8443, en una dirección pública. Se rechazan los nombres internos y las direcciones privadas.»
- En Eventos que recibir, elija los eventos; consulte Los eventos. «Si no elige eventos, no se envía nada. Elija al menos uno.»
- Compruebe que Envío activo está activado y pulse Guardar.
Enviar evento de prueba hace una petición a la dirección e indica qué ha respondido: «La URL ha respondido {código}.» o «El envío de prueba ha fallado: {error}».
La dirección que acepta la plataforma
Sección titulada «La dirección que acepta la plataforma»La dirección no es libre. La plataforma la valida antes de guardarla, para que no se pueda usar para llamar a máquinas que no son suyas:
- HTTPS, siempre.
- Puerto 443 u 8443, y ningún otro.
- Un host público: ni
localhost, ni*.localhost, ni*.internal, nimetadata.google.internal. - Una dirección pública. Si el nombre se resuelve en una dirección privada o
reservada (
10.x,172.16–31.x,192.168.x,127.x,169.254.x,100.64.x, multicast o sus equivalentes en IPv6), se rechaza. Se comprueban todas las direcciones en las que se resuelve el nombre, no solo la primera.
El rechazo aparece en su idioma:
| Rechazo | Qué hacer |
|---|---|
| «Indique la URL del webhook.» | el campo está vacío |
| «La dirección no es una URL válida.» | falta el esquema o hay un error de escritura |
| «La URL debe usar HTTPS.» | cambie http:// por https:// |
| «El puerto debe ser 443 u 8443.» | quite el puerto de la dirección o use uno de estos |
| «El host está reservado (localhost, .internal, metadatos de la nube) y no puede recibir webhooks.» | use un nombre accesible desde internet |
| «La dirección IP no es pública.» | ha escrito una IP privada directamente |
| «El nombre de host no se resuelve en ninguna dirección.» | compruebe el DNS |
| «No se ha podido resolver el nombre de host.» | el DNS ha fallado; inténtelo de nuevo |
| «El host se resuelve en una dirección que no es pública.» | el nombre apunta al interior de su red |
Al elegir los eventos, «Uno de los eventos elegidos no se reconoce.» significa que la lista enviada contiene un nombre que la plataforma no conoce; compruébelo en la tabla de los eventos, más abajo. Y «No hay ninguna URL de webhook configurada: indique una o guarde primero la suscripción.» aparece cuando se intenta suscribir eventos antes de que haya dirección.
Los eventos
Sección titulada «Los eventos»| Evento | En pantalla | Cuándo se envía |
|---|---|---|
document.completed |
Documento completado | Todos han firmado y el documento final está listo |
document.rejected |
Documento rechazado | Un firmante lo ha rechazado |
document.canceled |
Documento cancelado | El documento se ha cancelado |
document.expired |
Documento caducado | Ha vencido el plazo sin completarse |
document.pdf_application_failed |
Error al aplicar las firmas en el PDF | No se ha podido aplicar la firma al PDF |
recipient.signed |
El firmante ha firmado | Un firmante ha firmado; una vez por firmante |
document.sent |
Documento enviado para firma | El documento se ha publicado y han salido las invitaciones |
Los dos últimos no son finales: el documento sigue avanzando después de ellos. No trate ningún evento como «ha terminado»: consulte el estado del documento que viene en el cuerpo.
document.pdf_application_failed es el que no se debe ignorar: significa que
alguien ha firmado pero la firma no ha llegado a entrar en el archivo. En
AssinaJá aparece como Problema técnico en el detalle del documento, con
Reintentar; consulte
Seguir y gestionar documentos.
La cabecera Idempotency-Key sirve para que su sistema descarte repeticiones,
pero no tiene una sola forma. Depende del destino del evento y de cuál sea:
| Destino | Evento | Clave |
|---|---|---|
Dirección del documento (webhookUrl) |
cualquiera, salvo recipient.signed |
{documentPublicId}:{event} |
| Dirección del documento | recipient.signed |
{documentPublicId}:{event}:{recipientId} |
| Dirección de la organización | cualquiera, salvo recipient.signed |
{documentPublicId}:{event}:org |
| Dirección de la organización | recipient.signed |
{documentPublicId}:{event}:{recipientId}:org |
Guarde y compare la clave entera, como un texto opaco. No la divida en
partes. Si tiene una restricción de unicidad sobre (documento, evento) en su
base de datos, rechazará entregas legítimas: recipient.signed llega una vez por
firmante, y un documento con dirección propia en una organización que también
tiene dirección configurada genera dos entregas del mismo evento, con claves
distintas.
El secreto del webhook
Sección titulada «El secreto del webhook»El secreto es lo que le permite tener la certeza de que la petición procede realmente de AssinaJá. Está en Configuración → Desarrolladores, en la pestaña Webhooks, en la tarjeta Secreto del webhook. Solo lo ve el Propietario de la organización.
Secreto del webhook:
El secreto se utiliza para verificar la firma de los eventos enviados a su webhook.
Use Generar secreto la primera vez, y Copiar para guardarlo. A partir de ahí, la tarjeta muestra el secreto oculto, con Copiar y Rotar. No salga de esa página sin haberlo guardado:
Guarde este valor ahora: no se volverá a mostrar.
Cambiar el secreto
Sección titulada «Cambiar el secreto»Rotar genera un secreto nuevo sin interrumpir las entregas:
¿Está seguro de que desea rotar el secreto? El secreto anterior seguirá siendo válido durante 24 horas.
Durante esas 24 horas («Secreto anterior válido 24 h más.»), las peticiones van firmadas con los dos secretos, separados por comas en la misma cabecera. Por eso la verificación tiene que aceptar una lista, y no un único valor. Pasado ese plazo, solo se usa el nuevo.
Verificar la firma
Sección titulada «Verificar la firma»Cada petición trae estas cabeceras:
| Cabecera | Qué es |
|---|---|
X-AssinaJa-Signature |
La firma, v1=<hex>, o varias separadas por comas durante una rotación |
X-AssinaJa-Event |
El nombre del evento |
X-AssinaJa-Delivery |
Un identificador nuevo en cada intento: no sirve para descartar repeticiones |
X-AssinaJa-Timestamp |
La hora, en segundos Unix |
Idempotency-Key |
Consulte la tabla anterior: cuatro formas posibles |
La firma es un HMAC-SHA256 sobre la hora y el cuerpo de la petición unidos por un
punto ({timestamp}.{cuerpo}), en hexadecimal en minúsculas y con el prefijo
v1=.
La clave no es el secreto tal como lo copió. El secreto viene codificado en base64url; la clave del HMAC son los bytes que resultan de descodificarlo. Pasar el texto directamente a la función de HMAC produce una firma que nunca coincide: es la causa más habitual de que la verificación falle.
const crypto = require('crypto');
function verifyWebhookSignature(secret, timestamp, body, signatureHeader) { const message = `${timestamp}.${body}`; // o segredo é base64url — a chave são os bytes descodificados, não o texto const secretBytes = Buffer.from(secret, 'base64url'); const expected = 'v1=' + crypto .createHmac('sha256', secretBytes) .update(message) .digest('hex');
// durante uma rotação vêm as duas assinaturas const signatures = signatureHeader.split(',').map(s => s.trim()); return signatures.some(sig => sig === expected);}Use el cuerpo tal como llegó, en bruto. Si lo pasa por un analizador de JSON y lo vuelve a serializar, los bytes cambian y la firma deja de coincidir.
Qué hace la plataforma con su respuesta
Sección titulada «Qué hace la plataforma con su respuesta»| Lo que responde | Qué ocurre |
|---|---|
2xx |
Entregada. No hay nuevo intento. El cuerpo de la respuesta tiene que caber en 4 KB. |
3xx |
Vuelve a intentarlo: las redirecciones no se siguen. |
4xx |
Vuelve a intentarlo, igual que con un 5xx. |
5xx |
Vuelve a intentarlo. |
| Sin respuesta en 10 segundos | Vuelve a intentarlo. |
Solo una respuesta 2xx cuenta como entregada. No existe ningún código que
haga que la plataforma desista a propósito: si quiere que una entrega se detenga,
responda 2xx y descarte el contenido en su sistema.
Los intentos se espacian 1 min, 2 min, 5 min, 15 min, 30 min, 60 min y 60 min. Son ocho en total, y el octavo es una entrega real: solo cuando falla, la entrega queda marcada como fallida.
Comprobar si ha llegado
Sección titulada «Comprobar si ha llegado»El detalle de cada documento muestra la última entrega de ese documento, sea cual sea el evento, en la tarjeta Integración, con Webhook (el nombre del evento), Estado, Intentos, Entregado el y, si ha fallado, el Error. Es el lugar más rápido para distinguir «AssinaJá no lo ha enviado» de «mi servidor no lo ha aceptado». Esta tarjeta no tiene botón de reenvío.
Para ver el historial completo de la organización y reenviar entregas fallidas, vaya a Configuración → Desarrolladores → Webhooks, a la sección Entregas, debajo de la dirección y del secreto:
Cada evento enviado, con la respuesta de su URL. Las entregas fallidas se pueden reenviar.
Cada fila tiene Evento, URL, Estado (Entregada o Fallida), Intentos, Fecha y Último error; las fallidas tienen Reenviar, que responde «Entrega reenviada. La URL ha respondido {código}.» Solo el Propietario de la organización tiene acceso a esa pantalla.
Cuando el reenvío no funciona, la pantalla indica por qué:
Esa entrega ya no existe.
Esa entrega ya se ha recibido: solo se reenvían las fallidas.
No se puede reenviar esta entrega en este momento.