Automatización con IA

Extracción de Datos de PDFs

Extrae datos estructurados de facturas y contratos automáticamente

Flujo 05: Extracción de Datos de PDFs con IA

El problema

Las facturas de proveedores llegan como PDFs por email. Alguien las abre una a una, busca el importe, la fecha, el NIF del proveedor, las líneas de detalle, y los teclea en el ERP o en una hoja de Excel. Con 20-30 facturas semanales, eso son 2-4 horas de trabajo manual con alta tasa de errores de transcripción. Claude 3.5 puede leer el texto de un PDF y extraer todos los campos en formato JSON en menos de 3 segundos por documento.

Herramientas necesarias

Nodo n8n Función
Gmail Trigger Detecta emails con adjuntos PDF
Gmail Descarga el archivo adjunto en base64
Extract from File Convierte el PDF binario a texto plano
HTTP Request Llama a Claude API con el texto extraído
Google Sheets Guarda los datos estructurados de cada factura

Servicios externos:

  • Cuenta Gmail con OAuth2 en n8n
  • API Key de Anthropic (console.anthropic.com)
  • Google Sheets con la hoja de facturas preparada

Configuración paso a paso

Nodo 1: Gmail Trigger

Configura el trigger para detectar emails con adjuntos PDF:

  • Event: Message Received
  • Filters > Query: has:attachment filename:pdf (sintaxis de búsqueda de Gmail)
  • Simplify: OFF
  • Download Attachments: ON

Importante: activa Download Attachments para que el nodo descargue el binario del adjunto directamente. Sin esto, solo recibes el metadata del email.

Campos disponibles:

{{ $json.attachments[0].name }}        → nombre del archivo
{{ $json.attachments[0].data }}        → contenido en base64
{{ $json.attachments[0].mimeType }}    → tipo MIME
{{ $json.From }}                       → remitente del email
{{ $json.Subject }}                    → asunto del email

Nodo 2: IF — Filtrar solo PDFs

Añade un nodo IF para verificar que el adjunto es realmente un PDF y no una imagen u otro tipo de archivo:

  • Condition:
    • Value 1: ={{ $json.attachments[0].mimeType }}
    • Operation: Contains
    • Value 2: pdf

Solo los emails con adjunto PDF real continúan el flujo.

Nodo 3: Extract from File

Añade el nodo Extract from File:

  • Operation: Extract Text from PDF
  • Binary Property: ={{ $json.attachments[0].data }}

Este nodo convierte el binario del PDF a texto plano. Para PDFs generados digitalmente (no escaneados) la extracción es prácticamente perfecta. Para PDFs escaneados necesitas un servicio de OCR externo antes de este paso.

El texto resultante estará en {{ $json.text }}.

Nodo 4: HTTP Request — Claude API (visión del documento)

Añade el nodo HTTP Request:

  • Method: POST
  • URL: https://api.anthropic.com/v1/messages
  • Authentication: Header Auth
    • x-api-key: tu API Key de Anthropic
  • Headers adicionales:
    • anthropic-version: 2023-06-01
    • content-type: application/json
  • Body (JSON):
{
  "model": "claude-3-5-haiku-20241022",
  "max_tokens": 800,
  "messages": [
    {
      "role": "user",
      "content": "={{ $json.prompt_extraccion }}"
    }
  ]
}

Crea el campo prompt_extraccion en un nodo Set previo:

Extrae los datos de esta factura y devuelve ÚNICAMENTE un JSON válido.
Si un campo no está en el documento, usa null.
Los importes deben ser números sin símbolo de moneda (ej: 1250.50).
Las fechas en formato DD/MM/YYYY.

JSON de salida requerido:
{
  "numero_factura": "...",
  "fecha_emision": "DD/MM/YYYY",
  "fecha_vencimiento": "DD/MM/YYYY o null",
  "proveedor_nombre": "...",
  "proveedor_nif": "...",
  "cliente_nombre": "...",
  "cliente_nif": "...",
  "base_imponible": número,
  "iva_porcentaje": número,
  "iva_importe": número,
  "total_factura": número,
  "concepto": "descripción breve del servicio o producto",
  "lineas": [
    {"descripcion": "...", "cantidad": número, "precio_unitario": número, "importe": número}
  ]
}

TEXTO DE LA FACTURA:
{{ $json.text }}

Nodo 5: Code — Parsear y validar JSON

Añade un nodo Code (JavaScript) para extraer y validar el JSON:

const respuesta = $input.first().json.content[0].text;
// Limpiar markdown si la IA lo añade
const limpio = respuesta.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
const datos = JSON.parse(limpio);

// Validación: campos obligatorios
const camposObligatorios = ['numero_factura', 'total_factura', 'proveedor_nombre'];
const camposFaltantes = camposObligatorios.filter(c => datos[c] === null || datos[c] === undefined);

if (camposFaltantes.length > 0) {
  throw new Error(`Campos obligatorios faltantes: ${camposFaltantes.join(', ')}`);
}

return [{ json: {
  ...datos,
  fecha_procesado: new Date().toISOString(),
  archivo_fuente: $('Gmail Trigger').item.json.attachments[0].name,
  remitente_email: $('Gmail Trigger').item.json.From,
  estado: 'procesado_ok'
}}];

Nodo 6: Google Sheets — Guardar factura

Añade el nodo Google Sheets:

  • Operation: Append Row
  • Document ID: ID de tu hoja
  • Sheet Name: Facturas_Recibidas
  • Column Matching: By Column Name
  • Columns: mapea cada campo del JSON a la columna correspondiente

Columnas recomendadas en la hoja: Fecha_Procesado | Numero_Factura | Fecha_Emision | Fecha_Vencimiento | Proveedor | NIF_Proveedor | Base_Imponible | IVA_% | IVA_€ | Total | Concepto | Estado | Archivo

Ejemplo de prompt IA

Extrae los datos de esta factura y devuelve ÚNICAMENTE un JSON válido.

TEXTO DE LA FACTURA:
FACTURA Nº: F2025-0142
Fecha: 15/04/2025
Vencimiento: 30/04/2025

EMISOR:
Servicios Cloud SL
CIF: B-12345678

RECEPTOR:
Acme Corp SL
CIF: A-87654321

DETALLE:
- Licencias software anual (5 usuarios) × 1 ... 2.500,00€
- Soporte técnico mensual × 1 ................... 450,00€

Base imponible: 2.950,00€
IVA 21%: 619,50€
TOTAL: 3.569,50€

Respuesta de Claude:

{
  "numero_factura": "F2025-0142",
  "fecha_emision": "15/04/2025",
  "fecha_vencimiento": "30/04/2025",
  "proveedor_nombre": "Servicios Cloud SL",
  "proveedor_nif": "B-12345678",
  "cliente_nombre": "Acme Corp SL",
  "cliente_nif": "A-87654321",
  "base_imponible": 2950.00,
  "iva_porcentaje": 21,
  "iva_importe": 619.50,
  "total_factura": 3569.50,
  "concepto": "Licencias software y soporte técnico",
  "lineas": [
    {"descripcion": "Licencias software anual (5 usuarios)", "cantidad": 1, "precio_unitario": 2500.00, "importe": 2500.00},
    {"descripcion": "Soporte técnico mensual", "cantidad": 1, "precio_unitario": 450.00, "importe": 450.00}
  ]
}

Ahorro estimado

Tarea Antes Con automatización
Abrir y revisar 25 PDFs/semana 30 min/semana 0 min
Teclear datos en sistema 2 h/semana 0 min
Revisar errores de transcripción 30 min/semana 5 min (revisión spot)
Total semanal 3 h/semana ~5 min/semana

Ahorro neto: ~2,9 horas/semana. Tasa de error en transcripción manual: 3-5%. Con IA sobre PDFs digitales: <1%. Coste de Claude por factura procesada: ~€0,001.