Salida

Canales existentes

Canal Eventos Trigger Transporte Configuracion
Webhook org-level `record.created`, `expedient.completed` Firestore triggers POST directo con `WebhookDispatcher` organizations/{orgId}
Legacy user integrations `expedient.completed` `onExpedientWrite` + Cloud Tasks Queue `webhooks-queue` + worker HTTP users/{userId}/integrations/{integrationId}

Evento 1

Flujo de `record.created`

Este evento sale por el trigger `onRecordCreated` cuando se crea un documento de `records` dentro de una captura.

  1. 1
    Firestore crea `users/{userId}/captures/{captureId}/records/{recordId}`. El trigger v1 escucha ese path exacto.
  2. 2
    El record se valida con `isRecord`. Si el schema no cuadra, el evento se descarta sin retry.
  3. 3
    Se resuelve la organizacion del usuario. Si el usuario no tiene `organizationId`, no se emite webhook.
  4. 4
    El dispatcher revisa si `record.created` esta soportado. Necesita URL, secret y el evento habilitado en la configuracion.
  5. 5
    Se crea el payload publico. `record.data` se expone como `data`; se promueven `vendor` y `currency`; no salen metadatos internos como `confidenceScore` o `boundingBox`.
  6. 6
    Se firma y se envia el POST. `WebhookDispatcher` usa HMAC SHA-256 y timeout de 5 segundos.
Dato operativo

El trigger de `record.created` declara `failurePolicy: true` en el repositorio, por lo que el developer receptor debe tratar el evento como potencialmente reintentable.

Evento 2

Flujo de `expedient.completed`

Este evento se produce cuando un expediente pasa de estar procesando a quedar terminado sin error.

  1. 1
    `onExpedientWrite` recibe un cambio de documento. El trigger ignora creaciones puras y borrados.
  2. 2
    Se valida la transicion de estado. Debe cumplirse `before.isProcessing === true`, `after.isProcessing !== true` y ausencia de `errorMessage`.
  3. 3
    El payload se sanitiza. El campo `imageBytes` se elimina antes de cualquier handoff.
  4. 4
    Se resuelve la configuracion de organizacion. Si el evento esta soportado, se prepara la salida org-level.
  5. 5
    En paralelo puede activarse la ruta legacy por usuario. Se consultan `users/{userId}/integrations` con `isActive=true` y `events array-contains expedient.completed`.
  6. 6
    Se emite el POST org-level si esta activo. El payload expone `event`, `id`, `timestamp`, `type` y el expediente sanitizado como `data`.

Compatibilidad

Ruta legacy por usuario

Esta ruta no es la superficie publica recomendada, pero sigue activa en el repositorio y hay que conocerla para no confundirse al leer logs o soporte historico.

Como se encola

  • Usa la cola `webhooks-queue` en `us-central1`.
  • La task se nombra `webhook-{expedientId}-{integrationId}`.
  • Si la task ya existe, se trata como exito por deduplicacion.
  • El body base64 incluye `integrationId`, `payload` y `attempt`.

Como entrega

  • El worker `dispatchWebhook` exige bearer token de service account.
  • Lee `targetUrl`, `customHeaders` y `secretKey` de la integracion.
  • Construye un envelope con `eventId`, `eventType`, `timestamp` y `data`.
  • Devuelve 200 para 4xx del destino y 500 para fallos transitorios.

Operacion

Comportamiento que importa para integracion

Headers del org-level

`Content-Type: application/json`, `User-Agent: Kapture-Webhooks/1.0`, `X-Kapture-Signature`, `X-Kapture-Event` y `X-Kapture-Timestamp`.

Headers del worker legacy

El worker usa `User-Agent: Kapture-Webhook-Bot/1.0` y permite `customHeaders` por integracion.

Timeout del dispatcher directo

`WebhookDispatcher` usa 5 segundos. Si el destino tarda mas, el handoff se considera fallido.

Nota de mantenimiento

En este repositorio solo `onRecordCreated` declara explicitamente `failurePolicy`. El trigger `onExpedientWrite` no expone una opcion de retry junto a su declaracion, asi que conviene verificar esa postura al nivel de despliegue antes de asumir simetria.

Codigo

Mapa de codigo para maintainers

backend/functions/src/services/WebhookDispatcher.ts Soporte de eventos, resolucion de compatibilidad, firma y POST directo.
backend/functions/src/triggers/webhooks.ts Trigger v1 que produce `record.created`.
backend/functions/src/triggers/expedients/onExpedientWrite.ts Transicion de expediente terminado, sanitizacion y fanout.
backend/functions/src/services/TaskQueueService.ts Encolado de la via legacy con nombre determinista de task.
backend/functions/src/workers/dispatchWebhook.ts Worker HTTP de Cloud Tasks, envelope y clasificacion 4xx/5xx.
backend/functions/src/types/organization.ts Contrato del webhook org-level dentro de la organizacion.