Saltearse al contenido

Webhook

Tandia API puede notificar eventos de documentos y resúmenes hacia una URL configurada como webhook.

Configuración de webhook

La configuración pública documentada se realiza a nivel de compañía mediante el campo web_hook. El backend también puede usar un webhook configurado a nivel de cuenta como respaldo operativo.

Registrar webhook al crear compañía

POST /api/company/create
Host: invoice.test.tandia.io
Authorization: Bearer token-de-api
Content-Type: multipart/form-data

Campo dentro del form-data:

web_hook=https://cliente.com/webhooks/tandia

Actualizar webhook de una compañía existente

PUT /api/company/{taxId}
Host: invoice.test.tandia.io
Authorization: Bearer token-de-api
Content-Type: application/json

Payload:

{
  "web_hook": "https://cliente.com/webhooks/tandia"
}

Validaciones

CampoTipoRequeridoRestricciones backendRecomendación
web_hookstringNomáximo 255 caracteresUsar URL HTTPS pública, estable e idempotente.

Comportamiento

ReglaDescripción
PrioridadSi la compañía tiene web_hook, se envía a esa URL; si no tiene, el backend intenta usar el webhook de la cuenta.
AlcanceLa actualización con PUT /api/company/{taxId} solo afecta a la compañía asociada a la cuenta autenticada.
CuentaLa configuración directa del webhook de cuenta es operación interna y no se publica como endpoint de integración general.
URL vacíaSi no existe webhook de compañía ni de cuenta, no se envía notificación.

Recepción de eventos

Cuando se genera un evento configurado y existe una URL de webhook, Tandia envía una solicitud HTTP POST a la URL registrada.

Eventos observados en backend

TipoEventos que disparan webhook
DocumentoDocumentSucceeded, DocumentError
ResumenSummarySucceeded, SummaryError, SummaryFailed

Solicitud enviada

POST https://cliente.com/webhooks/tandia
Content-Type: application/json
Tandia-Signature: jwt-firmado

Payload: Tandia envía el modelo del documento o resumen mediante toArray(). La estructura exacta depende del tipo de evento y del recurso procesado.

Ejemplo simplificado:

{
  "id": "doc_10987654321",
  "status": "succeeded",
  "company_id": "com_61a80925017e4",
  "account_id": "acc_7449a64d83b17ba",
  "metadata": {
    "external_id": "pedido-123"
  }
}

Entrega y reintentos

ReglaValor observado
MétodoPOST
Timeout30 segundos
Reintentos1 reintento ante ConnectionException
Espera entre reintentos2 segundos
RegistroEl backend adjunta logs de éxito o error al documento/resumen.

Verificación de firma

Cada webhook incluye la cabecera Tandia-Signature. Esta cabecera contiene un JWT firmado con el secret_key de la cuenta.

Tandia-Signature: jwt-firmado

El token de firma expira en 5 minutos y contiene al menos el id del documento o resumen enviado.

Proceso recomendado

  1. Lee la cabecera Tandia-Signature.
  2. Verifica el JWT con el secret_key de la cuenta.
  3. Valida que el token no haya expirado.
  4. Compara el id firmado con el id recibido en el payload.
  5. Procesa el evento de forma idempotente.

Pseudocódigo:

signature = request.headers["Tandia-Signature"]
payload = verify_jwt(signature, secret_key)

if payload is valid and payload.id == request.body.id:
    process_event(request.body)
else:
    reject_request()

Seguridad del receptor

ReglaDescripción
HTTPSPublica el webhook únicamente por HTTPS.
IdempotenciaUn mismo evento puede recibirse más de una vez por reintentos o reprocesos.
Respuesta rápidaResponde 2xx luego de validar y encolar/procesar el evento.
SecretosNo expongas secret_key ni lo envíes en respuestas o logs.
ValidaciónNo proceses eventos sin firma válida.