> This documentation belongs to Invofox, an AI-powered document processing
> platform. The API extracts structured data (fields) from unstructured
> documents (invoices, contracts, forms, bank statements, and more).
> Key concepts: Account, Environment, Document Type, Field, File, Import,
> and Document. When answering, prefer the exact terminology defined in the
> Glossary and cite the relevant API Reference endpoint when applicable.

# Implementación de webhooks

> Cómo configurar la entrega de webhooks de Invofox e implementar handlers fiables para los eventos de procesamiento de imports, files y documents.

Ahora que entiendes el flujo de procesamiento y los eventos de webhook de cada entidad ([Import](processing-tracking#import-processing), [File](processing-tracking#file-processing), [Document](processing-tracking#document-processing)), aquí tienes cómo configurar la entrega de webhooks e implementar handlers robustos.

## Configuración de webhooks

Para recibir eventos de cambio de estado necesitarás:

- **URL accesible públicamente** - tu endpoint debe ser alcanzable por los sistemas de Invofox
- **Configuración de lista de IPs permitidas** - consulta nuestros rangos de IP públicos para configurar el firewall
- **Firma HMAC opcional** - configura una clave secreta que se usará para firmar las notificaciones de webhook con HMAC, para mayor seguridad y verificación de autenticidad

Contacta con el administrador de tu cuenta para la configuración de webhooks, la información de rangos de IP y la configuración de la firma HMAC.

Los webhooks se disparan en las transiciones de estado y en las actualizaciones de documentos, garantizando que recibas actualizaciones a tiempo sin notificaciones redundantes.

## Estructura del evento de webhook

Todos los eventos de webhook siguen esta estructura consistente:

- `type` - Identificador del tipo de evento (coincide con las transiciones de estado)
- `id` - Identificador único del evento (úsalo para un procesamiento idempotente)
- `timestamp` - Marca de tiempo de creación del evento en formato ISO 8601
- `data` - Carga útil del evento con la instancia de la entidad (objeto Import, File o Document)
- `version` - Versión del esquema del evento

### Ejemplo de evento

```json
{
  "type": "document.processed",
  "id": "000000000000000000000016",
  "timestamp": "2024-12-15T14:30:00.000Z",
  "data": { /* DATOS DEL DOCUMENTO */ },
  "version": "1.0"
}
```

> **Nota:** La estructura de datos del documento se está refinando. Consulta la referencia de la API para ver la estructura completa y actual del documento.

## Buenas prácticas de implementación de webhooks

Esta sección cubre las buenas prácticas para implementar handlers de webhook robustos que procesen los eventos de Invofox de forma fiable y eficiente.

### Patrón de confirmación rápida

⚠️ **Buena práctica:** Tu endpoint de webhook debe responder con un código de estado 2xx **en menos de 30 segundos** para garantizar una entrega fiable.

**Por qué importan las respuestas rápidas:**

- Evitan fallos por timeout y reintentos
- Mantienen una entrega de eventos fiable
- Te permiten gestionar el procesamiento de forma asíncrona

**Patrón recomendado:** Verificar firma → Encolar evento → Responder de inmediato

```typescript
import express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json());

// Cola de mensajes (ejemplo: AWS SQS, RabbitMQ, Bull, etc.)
import { messageQueue } from './queue';

app.post('/webhook', async (req, res) => {
  // Paso 1: Verificar la firma
  if (!verifyWebhookSignature(req.body, req.headers['x-invofox-signature'], process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Paso 2: Encolar el evento para procesamiento asíncrono
  await messageQueue.send({
    type: 'invofox-webhook',
    payload: req.body,
    receivedAt: Date.now()
  });

  // Paso 3: Responder de inmediato
  res.status(200).json({ received: true });
});

function verifyWebhookSignature(requestBody: any, signature: string | undefined, secret: string): boolean {
  if (!signature || !secret) return false;

  const splitIndex = signature.indexOf('=');
  const algorithm = signature.slice(0, splitIndex);
  const receivedHmac = signature.slice(splitIndex + 1);

  const computedHmac = crypto
    .createHmac(algorithm, secret)
    .update(JSON.stringify(requestBody))
    .digest('base64');

  return computedHmac === receivedHmac;
}
```

### ID de evento e idempotencia

Cada evento de webhook incluye un campo `id` único. Úsalo para implementar un procesamiento idempotente y evitar el manejo duplicado.

**Por qué importa la idempotencia:**

- Los problemas de red pueden hacer que Invofox reintente la entrega
- Tu lógica de procesamiento podría dispararse varias veces
- Los IDs de evento garantizan que cada evento se procese exactamente una vez

### Manejo de errores y comportamiento de reintentos

**Códigos de estado HTTP:**

Tu endpoint de webhook debe devolver:

- **200-299**: Éxito - Invofox no reintentará
- **4xx**: Error de cliente - Invofox no reintentará (tu endpoint rechazó el evento)
- **5xx**: Error de servidor - Invofox reintentará hasta 3 veces
- **Timeout**: La petición expira tras 30 segundos - Invofox reintentará hasta 3 veces

**Estrategia de reintentos de Invofox:**

Cuando tu endpoint devuelve un error o expira, Invofox reintentará automáticamente hasta **3 veces**:

- Los retrasos entre reintentos se basan en la cabecera de respuesta `Retry-After` de tu endpoint (por defecto: 300 ms si no se especifica)
- Total de intentos: petición original + 3 reintentos = 4 intentos de entrega

### Buenas prácticas de seguridad

**Verificación de la firma HMAC:**

Verifica siempre la firma HMAC cuando configures un secreto de webhook. Esto garantiza que los eventos provienen de Invofox.

**Puntos clave de seguridad:**

1. **Almacenamiento del secreto**: guarda los secretos de webhook en variables de entorno o sistemas de gestión de secretos
2. **Solo HTTPS**: los endpoints de webhook deben usar HTTPS en producción
3. **Valida las firmas**: verifica siempre las firmas HMAC cuando haya secretos configurados (consulta la Referencia de la API para la implementación)
4. **Lista de IPs permitidas**: opcional - configura tu firewall para aceptar solo peticiones de los rangos de IP de Invofox (contacta con soporte)

### Checklist resumen

- ✅ **Confirmación rápida**: responde con 200 en menos de 30 segundos
- ✅ **Procesamiento asíncrono**: encola los eventos y procésalos de forma asíncrona
- ✅ **Verificación HMAC**: verifica siempre las firmas cuando haya un secreto configurado
- ✅ **Idempotencia**: usa el `id` del evento para evitar el procesamiento duplicado
- ✅ **Manejo de errores**: devuelve los códigos de estado HTTP adecuados según el tipo de error
- ✅ **Seguridad**: usa HTTPS, almacenamiento seguro de secretos y, opcionalmente, lista de IPs permitidas