Documentación API

Documentación de Endpoints


POST /v1/extractions

Este endpoint permite subir el archivo (codificado en Base64) junto con la habilidad que definiste.

POST /v1/extractions

Headers

Content-Type: application/json
	x-api-key: TU_API_KEY

Body (JSON)

{
	"model": "gpt-4o-mini",
	"file_name": "documento.pdf",
	"skill": "dni",
	"file_base64": "BASE64_ENCODED_FILE",
	"extraction_mode": "ocr_pdf"
	}
  • model: (opcional) Modelo de IA a utilizar. Si no se especifica, se usa "gpt-4o-mini". .
  • file_name: Nombre original del archivo.
  • skill: El slug de la habilidad que has configurado.
  • file_base64: Contenido del archivo en Base64.
  • extraction_mode: (opcional) Modo de extracción: "ocr_pdf" (predeterminado), "ocr_only" o "pdf_only".

Ejemplos de petición

curl -X POST https://api-docmind.devol.es/v1/extractions \
	-H "Content-Type: application/json" \
	-H "x-api-key: TU_API_KEY" \
	-d '{
			"model": "gpt-4o-mini",
			"file_name": "documento.pdf",
			"skill": "dni",
			"file_base64": "BASE64_ENCODED_FILE",
			"extraction_mode": "ocr_pdf"
	}'

Respuesta

{
	"extraction_id": "b67162ac-8a79-4dc0-9bb5-87c245e4f779"
	}

La API devuelve un 202 Accepted indicando que la extracción está en cola y procesándose.


GET /v1/extractions

Este endpoint permite listar y filtrar las extracciones según varios criterios.

GET /v1/extractions

Headers

x-api-key: TU_API_KEY

Query Parameters

  • status: (opcional) Filtrar por estados separados por coma. Ej: completado,incompleto
  • habilidad_id: (opcional) Filtrar por ID de habilidad
  • habilidad_slug: (opcional) Filtrar por slug de habilidad
  • start_date: (opcional) Fecha inicial en formato YYYY-MM-DD
  • end_date: (opcional) Fecha final en formato YYYY-MM-DD
  • search: (opcional) Texto para buscar en nombre de archivos
  • limit: (opcional) Número máximo de resultados a devolver
  • sort_by: (opcional) Campo para ordenar: fecha_creacion, status, origin_name. Por defecto: fecha_creacion
  • sort_order: (opcional) Orden: asc o desc. Por defecto: desc
  • include_archived: (opcional) Incluir documentos archivados: true o false. Por defecto: false

Ejemplos de petición

curl -X GET "https://api-docmind.devol.es/v1/extractions?status=completado,incompleto&start_date=2023-01-01&limit=50" \
  -H "x-api-key: TU_API_KEY"

Respuesta

{
  "extractions": [
    {
      "id": "b67162ac-8a79-4dc0-9bb5-87c245e4f779",
      "origin_name": "documento1.pdf",
      "extraction_date": "2023-01-15T14:30:00.000000+00:00",
      "last_modification": "2023-01-15T14:35:00.000000+00:00",
      "last_user_id": "USER_ID_123",
      "last_user_name": "Usuario Uno",
      "last_user_email": "usuario1@ejemplo.com",
      "status": "completado",
      "skill_name": "DNI",
      "habilidad_id": "abc123def456"
    },
    {
      "id": "c78273bd-9b80-5ed1-0cc6-98d356f5g890",
      "origin_name": "documento2.pdf",
      "extraction_date": "2023-01-10T09:15:00.000000+00:00",
      "last_modification": "2023-01-10T09:20:00.000000+00:00",
      "last_user_id": "USER_ID_456",
      "last_user_name": "Usuario Dos",
      "last_user_email": "usuario2@ejemplo.com",
      "status": "incompleto",
      "skill_name": "Factura",
      "habilidad_id": "xyz789pqr012"
    }
  ],
  "count": 2
}

La API devuelve la lista de extracciones que coinciden con los filtros especificados y el número total de resultados encontrados.


GET /v1/extractions/{extraction_id}

Con este endpoint obtienes los datos extraídos de una extracción previa.

GET /v1/extractions/{extraction_id}

Headers

x-api-key: TU_API_KEY

Ejemplos de petición

curl -X GET https://api-docmind.devol.es/v1/extractions/b67162ac-8a79-4dc0-9bb5-87c245e4f779 \
  -H "x-api-key: TU_API_KEY"

Respuesta

{
  "id": "b67162ac-8a79-4dc0-9bb5-87c245e4f779",
  "origin_name": "factura_empresa.pdf",
  "extraction_date": "2023-01-01T00:00:00.000000+00:00",
  "last_modification": "2023-01-01T00:00:00.000000+00:00",
  "last_user_id": "USER_ID_456",
  "last_user_name": "Usuario Demo",
  "last_user_email": "usuario@ejemplo.com",
  "status": "completado",
  "skill_name": "Facturas",
  "fields": [
    {
      "name": "numero_factura",
      "order": 1,
      "type": "string",
      "value": {
        "literal": "FAC-2024-001",
        "parsed": "FAC-2024-001"
      }
    },
    {
      "name": "proveedor",
      "order": 2,
      "type": "catalog",
      "value": {
        "type": "catalog",
        "matching": {
          "status": "found",
          "method": "exacta",
          "score": 1.0,
          "threshold_used": null,
          "extracted_values": {
            "nombre_empresa": "ACME Corp S.L."
          },
          "catalog_record_id": "66fb81b1-7aa1-41aa-971b-7fbcae7bbd2f",
          "key_columns": ["nombre_empresa"]
        },
        "catalog_values": {
          "nombre_empresa": "ACME Corp S.L.",
          "contacto_principal": "Juan Pérez",
          "telefono": "+34 912 345 678",
          "email": "contacto@acme-corp.com"
        },
        "catalog_info": {
          "id": "95f09806-dea9-45aa-8569-a9d9bc59f4fe",
          "name": "Catálogo de Proveedores",
          "output_columns": ["nombre_empresa", "contacto_principal", "telefono", "email"]
        }
      }
    },
    {
      "name": "fecha_emision",
      "order": 3,
      "type": "date",
      "value": {
        "literal": "15 de junio de 2024",
        "parsed": "2024-06-15"
      }
    },
    {
      "name": "cliente",
      "order": 4,
      "type": "object",
      "value": [
        {
          "name": "nombre",
          "order": 1,
          "type": "string",
          "value": {
            "literal": "Juan Pérez",
            "parsed": "Juan Pérez"
          }
        },
        {
          "name": "dni",
          "order": 2,
          "type": "string",
          "value": {
            "literal": "12345678Z",
            "parsed": "12345678Z"
          }
        }
      ]
    },
    {
      "name": "items",
      "order": 5,
      "type": "object",
      "value": [
        {
          "Cantidad": {
            "literal": "2",
            "parsed": 2
          },
          "Descripcion": {
            "literal": "Producto A",
            "parsed": "Producto A"
          },
          "Precio": {
            "literal": "€100.00",
            "parsed": 100.0
          }
        },
        {
          "Cantidad": {
            "literal": "1",
            "parsed": 1
          },
          "Descripcion": {
            "literal": "Producto B",
            "parsed": "Producto B"
          },
          "Precio": {
            "literal": "€150.00",
            "parsed": 150.0
          }
        }
      ]
    },
    {
      "name": "monto_total",
      "order": 6,
      "type": "float",
      "value": {
        "literal": "€1,250.00",
        "parsed": 1250.00
      }
    }
  ],
  "usage": {
    "tokens_consumidos": 1234,
    "prompt_tokens": 567,
    "response_tokens": 89,
    "duration": 45.2,
    "model": "gpt-4o"
  }
}

Si el status es "en cola" o "procesando", no se incluirán "fields" ni "usage". Los posibles estados son: "en cola", "procesando", "completado", "incompleto" o "error".

Estructura de fields

Nueva estructura como lista ordenada: Los campos ahora se devuelven como una lista de objetos ordenada por el campo order, garantizando que siempre aparezcan en el orden correcto definido en la habilidad. Cada elemento de la lista fields contiene:
  • name: Nombre del campo
  • order: Número de orden del campo (entero)
  • type: Tipo del campo (string, integer, float, date, boolean, object, catalog)
  • value: Valor del campo (estructura varía según el tipo)

Tipos de valores en fields

Campos simples: El value contiene literal (texto extraído tal como aparece) y parsed (valor procesado/normalizado). Campos de tipo object: El value es una lista de subcampos ordenados, cada uno con su propia estructura name, order, type y value. Campos de lista (isList=true): El value es una lista donde cada elemento puede ser un objeto simple o un diccionario con múltiples subcampos. Campos de catálogo: Cuando un campo está configurado para hacer matching contra un catálogo privado, la estructura es:
  • type: Siempre "catalog" para identificar este tipo de campo
  • matching: Información sobre el proceso de búsqueda en el catálogo
    • status: "found" si se encontró coincidencia, "not_found" si no
    • method: Tipo de búsqueda utilizada ("exacta" o "aproximada")
    • score: Puntuación de similitud (0.0 a 1.0)
    • extracted_values: Datos que se extrajeron del documento para hacer el matching
    • catalog_record_id: ID único del registro encontrado en el catálogo
    • key_columns: Nombres de las columnas utilizadas para la búsqueda
  • catalog_values: Los valores finales del catálogo (lo más importante)
    • Contiene todos los datos del registro encontrado en el catálogo
    • Incluye tanto las columnas de búsqueda como las columnas de salida configuradas
    • Estos son los valores "oficiales" del catálogo, no los extraídos del documento
  • catalog_info: Metadatos sobre el catálogo utilizado

Importante: Para campos de catálogo, utiliza siempre los valores de catalog_values como datos finales. Los valores en matching.extracted_values son solo para referencia del proceso de búsqueda.


GET /v1/extractions/{extraction_id}/detailed

Este endpoint devuelve toda la información detallada de una extracción, incluyendo las coordenadas OCR de cada palabra detectada en el documento.

GET /v1/extractions/{extraction_id}/detailed

Headers

x-api-key: TU_API_KEY

Ejemplos de petición

curl -X GET https://api-docmind.devol.esm/v1/extractions/b67162ac-8a79-4dc0-9bb5-87c245e4f779/detailed \
  -H "x-api-key: TU_API_KEY"

Respuesta

{
  "id": "b67162ac-8a79-4dc0-9bb5-87c245e4f779",
  "origin_name": "factura_empresa.pdf",
  "extraction_date": "2023-01-01T00:00:00.000000+00:00",
  "last_modification": "2023-01-01T00:00:00.000000+00:00",
  "last_user_id": "USER_ID_456",
  "last_user_name": "Usuario Demo",
  "last_user_email": "usuario@ejemplo.com",
  "status": "completado",
  "skill_name": "Facturas",
  "fields": [
    {
      "name": "numero_factura",
      "order": 1,
      "type": "string",
      "value": {
        "literal": "FAC-2024-001",
        "parsed": "FAC-2024-001",
        "word_ids": ["word-uuid-1", "word-uuid-2"],
        "id": "field-uuid-123",
        "type": "string"
      }
    },
    {
      "name": "proveedor",
      "order": 2,
      "type": "catalog",
      "value": {
        "type": "catalog",
        "matching": {
          "status": "found",
          "method": "exacta",
          "score": 1.0,
          "threshold_used": null,
          "extracted_values": {
            "nombre_empresa": "ACME Corp S.L."
          },
          "catalog_record_id": "66fb81b1-7aa1-41aa-971b-7fbcae7bbd2f",
          "key_columns": ["nombre_empresa"]
        },
        "catalog_values": {
          "nombre_empresa": "ACME Corp S.L.",
          "contacto_principal": "Juan Pérez",
          "telefono": "+34 912 345 678",
          "email": "contacto@acme-corp.com"
        },
        "catalog_info": {
          "id": "95f09806-dea9-45aa-8569-a9d9bc59f4fe",
          "name": "Catálogo de Proveedores",
          "output_columns": ["nombre_empresa", "contacto_principal", "telefono", "email"]
        }
      }
    },
    {
      "name": "fecha_emision",
      "order": 3,
      "type": "date",
      "value": {
        "literal": "15/06/2024",
        "parsed": "2024-06-15",
        "word_ids": ["word-uuid-3"],
        "id": "field-uuid-456",
        "type": "date"
      }
    }
  ],
  "words": {
    "1": [
      {
        "id": "word-uuid-1",
        "word": "FAC-2024-001",
        "x0": 150.5,
        "y0": 200.2,
        "x1": 220.3,
        "y1": 215.8,
        "page": 1
      },
      {
        "id": "word-uuid-2",
        "word": "ACME",
        "x0": 150.5,
        "y0": 250.1,
        "x1": 185.3,
        "y1": 265.9,
        "page": 1
      },
      {
        "id": "word-uuid-3",
        "word": "15/06/2024",
        "x0": 300.1,
        "y0": 200.2,
        "x1": 380.7,
        "y1": 215.8,
        "page": 1
      }
    ]
  },
  "full_text": "Texto completo extraído del documento...",
  "num_pages": 1,
  "usage": {
    "tokens_consumidos": 1234,
    "prompt_tokens": 567,
    "response_tokens": 89,
    "duration": 45.2,
    "model": "gpt-4o"
  }
}

Esta respuesta incluye toda la información de la extracción básica más:

  • fields con información detallada: Cada campo incluye word_ids (referencias a las palabras OCR), id único del campo y type del dato.
  • words: Diccionario organizados por número de página, donde cada palabra contiene sus coordenadas exactas (x0, y0, x1, y1) en el documento.
  • num_pages: Número total de páginas procesadas en el documento.
Las coordenadas permiten visualizar exactamente dónde se encontró cada palabra en el documento original.


GET /v1/extractions/{extraction_id}/document

Este endpoint permite descargar el documento original de una extracción.

GET /v1/extractions/{extraction_id}/document

Headers

x-api-key: TU_API_KEY

Ejemplos de petición

curl -X GET https://api-docmind.devol.es/v1/extractions/b67162ac-8a79-4dc0-9bb5-87c245e4f779/document \
  -H "x-api-key: TU_API_KEY" \
  --output documento_descargado.pdf

Respuesta

Este endpoint devuelve directamente el archivo binario con Content-Disposition: attachment para que el navegador lo descargue automáticamente. El nombre del archivo será el original con el que se subió.


PATCH /v1/extractions/{extraction_id}/status

Este endpoint permite cambiar el status de una extracción entre "completado" e "incompleto". Útil para marcar extracciones como incompletas cuando necesiten revisión adicional o para completar extracciones previamente marcadas como incompletas.

PATCH /v1/extractions/{extraction_id}/status

Headers

Content-Type: application/json
x-api-key: TU_API_KEY

Query Parameters

  • client_id: (solo para global_admin) ID del cliente al que pertenece la extracción que se quiere modificar

Body (JSON)

{
	"status": "incompleto",
	"message": "Faltan datos de contacto del cliente"
}
  • status: (obligatorio) Nuevo status: "completado" o "incompleto".
  • message: (opcional) Mensaje explicativo. Solo se guarda cuando se cambia a "incompleto". Se limpia automáticamente al cambiar a "completado".

Ejemplos de petición

# Cambiar de incompleto a completado
curl -X PATCH https://api-docmind.devol.es/v1/extractions/7caa3cd1-8a88-4f9e-ba76-1e75eaedb55f/status \
  -H "Content-Type: application/json" \
  -H "x-api-key: TU_API_KEY" \
  -d '{
    "status": "completado"
  }'

# Cambiar de completado a incompleto con mensaje
curl -X PATCH https://api-docmind.devol.es/v1/extractions/7caa3cd1-8a88-4f9e-ba76-1e75eaedb55f/status \
  -H "Content-Type: application/json" \
  -H "x-api-key: TU_API_KEY" \
  -d '{
    "status": "incompleto",
    "message": "Faltan datos de contacto del cliente"
  }'

Respuesta

{
  "message": "Status actualizado exitosamente",
  "extraction": {
    "id": "7caa3cd1-8a88-4f9e-ba76-1e75eaedb55f",
    "status": "incompleto",
    "last_modification": "2025-07-24T15:30:45.123456Z",
    "last_user_id": "user-uuid-123",
    "error_message": "Faltan datos de contacto del cliente"
  }
}

Comportamiento según el cambio de status:

  • Completado → Incompleto: Se puede añadir un mensaje opcional que se guarda en error_message
  • Incompleto → Completado: El campo error_message se limpia automáticamente
Campos que se actualizan automáticamente:
  • status: El nuevo status especificado
  • last_modification: Fecha y hora actual del cambio
  • last_user_id: ID del usuario que realizó el cambio
  • error_message: Se añade si se proporciona mensaje al cambiar a "incompleto", se limpia al cambiar a "completado"
Permisos:
  • Usuarios normales: Solo pueden modificar extracciones de su propia organización
  • Global admins: Pueden modificar extracciones de cualquier organización usando el parámetro client_id

Nota: Solo se permiten las transiciones "completado" ↔ "incompleto". Otros cambios de status devolverán un error 400.


Campos de Catálogo - Casos de Uso

Los campos de catálogo permiten normalizar y enriquecer datos extraídos contra catálogos privados. Aquí algunos ejemplos prácticos:

Ejemplo 1: Proveedor encontrado con coincidencia exacta

{
  "proveedor": {
    "type": "catalog",
    "matching": {
      "status": "found",
      "method": "exacta",
      "score": 1.0,
      "extracted_values": {
        "nombre_empresa": "ACME Corp S.L."
      }
    },
    "catalog_values": {
      "nombre_empresa": "ACME Corp S.L.",
      "contacto_principal": "Juan Pérez",
      "telefono": "+34 912 345 678",
      "email": "contacto@acme-corp.com"
    }
  }
}

Ejemplo 2: Búsqueda aproximada con coincidencia parcial

{
  "cliente": {
    "type": "catalog",
    "matching": {
      "status": "found",
      "method": "aproximada",
      "score": 0.85,
      "threshold_used": 0.8,
      "extracted_values": {
        "nif": "B12345678"
      }
    },
    "catalog_values": {
      "nif": "B12345678",
      "razon_social": "Empresa Ejemplo S.L.",
      "direccion": "Calle Mayor 123, Madrid"
    }
  }
}

Ejemplo 3: No se encontró coincidencia

{
  "proveedor": {
    "type": "catalog",
    "matching": {
      "status": "not_found",
      "method": "exacta",
      "score": 0.0,
      "extracted_values": {
        "nombre_empresa": "Empresa Desconocida S.L."
      }
    },
    "catalog_values": {}
  }
}

Recomendaciones de implementación

  • Verificar siempre matching.status antes de usar los datos
  • Usar catalog_values como fuente de verdad para los datos finales
  • Mostrar extracted_values al usuario para transparencia sobre qué se detectó en el documento
  • Considerar el score para búsquedas aproximadas - valores altos (>0.9) indican alta confianza

Códigos de error

  • 400 Bad Request: Parámetros inválidos o falta algún campo obligatorio.
  • 401 Unauthorized: Falta o es inválido el x-api-key.
  • 404 Not Found: No se encontró la extracción solicitada.
  • 500 Internal Server Error: Error interno (reintentar más tarde o contactar al soporte).

© 2025 Devol. Todos los derechos reservados.