Documentación de la API de DocSolved

DocSolved ofrece una API REST para extraer datos estructurados de documentos subidos o adjuntos de correo normalizados. Los trabajos persistentes, la aprobación humana, los webhooks firmados y las exportaciones contables permiten automatizaciones en Make, n8n, Zapier o integraciones personalizadas.

¿Trabaja con un agente de codificación en lugar de código de aplicación? DocSolved MCP conecta Codex, Claude Code, Gemini CLI y otros agentes compatibles con MCP a esta misma API.

Extraiga su primer documento en menos de 3 minutos

  1. Cree una clave de API en Ajustes de desarrollador. El ámbito extract basta para este ciclo; la clave se muestra una sola vez.
  2. Envíe el documento como trabajo asíncrono, consulte el estado hasta que termine y recupere el resultado.
  3. Cada campo de result.extracted_fields[] tiene las mismas claves: confidence, page, evidence (el texto de origen), match_status y bounding_box. En la vía OCR se rellenan cuando el valor ha podido localizarse en la página (match_status exact, fuzzy o llm_located); un valor que el OCR no ha podido anclar es not_found con un recuadro nulo. Las facturas electrónicas estructuradas se analizan desde su XML, así que sus campos no llevan página ni recuadro.

cURL

export DOCAI_API_KEY="sk_docai_YOUR_KEY"

# 1. submit (a retried submit with the same Idempotency-Key returns the same job)
JOB_ID=$(curl -s -X POST https://docsolved.ai/api/v1/jobs \
  -H "Authorization: Bearer $DOCAI_API_KEY" \
  -H "Idempotency-Key: invoice-2026-0847" \
  -F "[email protected]" | python3 -c 'import json,sys; print(json.load(sys.stdin)["job_id"])')

# 2. poll until status is completed / review_required / failed
until curl -s https://docsolved.ai/api/v1/jobs/$JOB_ID \
  -H "Authorization: Bearer $DOCAI_API_KEY" | grep -qE '"status": ?"(completed|review_required|failed)"'; do sleep 2; done

# 3. result
curl -s https://docsolved.ai/api/v1/jobs/$JOB_ID/result \
  -H "Authorization: Bearer $DOCAI_API_KEY"

Python

import os, time, requests

BASE = "https://docsolved.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['DOCAI_API_KEY']}"}

with open("invoice.pdf", "rb") as f:
    submit = requests.post(f"{BASE}/jobs", headers={**HEADERS, "Idempotency-Key": "invoice-2026-0847"},
                           files={"file": ("invoice.pdf", f, "application/pdf")}, timeout=60)
submit.raise_for_status()
job_id = submit.json()["job_id"]

while True:
    status = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS, timeout=30).json()["status"]
    if status in ("completed", "review_required", "failed"):
        break
    time.sleep(2)

result = requests.get(f"{BASE}/jobs/{job_id}/result", headers=HEADERS, timeout=30).json()["result"]
for field in result["extracted_fields"]:
    print(field["field"], field["value"], field["confidence"], field.get("page"), field.get("evidence"))

JavaScript / Node.js 20+

import { readFile } from "node:fs/promises";

const BASE = "https://docsolved.ai/api/v1";
const headers = { Authorization: `Bearer ${process.env.DOCAI_API_KEY}` };

const form = new FormData();
form.append("file", new Blob([await readFile("invoice.pdf")], { type: "application/pdf" }), "invoice.pdf");
const submit = await fetch(`${BASE}/jobs`, { method: "POST", headers: { ...headers, "Idempotency-Key": "invoice-2026-0847" }, body: form });
const { job_id } = await submit.json();

let status;
do {
  await new Promise((r) => setTimeout(r, 2000));
  ({ status } = await (await fetch(`${BASE}/jobs/${job_id}`, { headers })).json());
} while (!["completed", "review_required", "failed"].includes(status));

const { result } = await (await fetch(`${BASE}/jobs/${job_id}/result`, { headers })).json();
for (const f of result.extracted_fields) console.log(f.field, f.value, f.confidence, f.page, f.evidence);

Después: webhooks en lugar de sondeo, envíos idempotentes, revisión y aprobación, exportaciones, ingesta por correo, o la misma API desde un agente de código mediante MCP.

Autenticación

Cree y gestione las claves de API en la página Configuración de desarrollador. Envíe la clave como token bearer; los scopes y la cuota mensual de páginas de la clave se aplican en cada solicitud.

Authorization: Bearer sk_docai_<your_key>

Las claves de API empiezan por sk_docai_. Mantenlas en secreto. Solo se muestran una vez al crearlas.

Use el ámbito extract para enviar trabajos y leer sus resultados. Añada el ámbito history para listar registros guardados y descargar exportaciones contables, y el ámbito webhooks para gestionar los puntos de conexión de webhook. Son los únicos ámbitos de clave de API admitidos. Las claves no caducan; revoque una clave desde Ajustes de desarrollador en cuanto deje de necesitarla.

Límites de frecuencia

El uso del análisis se rige por la cuota de páginas y la cuota de almacenamiento de tu plan. No hay un límite separado por solicitud ni por día.

Las claves de API además contabilizan las páginas de OCR en la cuota mensual de páginas de la clave.

Las solicitudes que se quedan sin páginas o almacenamiento devuelven HTTP 402; una clave de API que supera su cuota mensual de páginas devuelve HTTP 429 con una indicación Retry-After.

Los puntos auxiliares (ayudas de validación, crear/probar/reenviar webhooks, enlaces públicos compartidos) tienen un tope de ráfaga de 60 solicitudes por minuto por IP, 600 para llamadas autenticadas; cada 429 incluye Retry-After en segundos. Los valores vigentes se publican en GET /api/v1/capabilities bajo rate_limits.

Formato de error

{
  "detail": "File too large. Maximum upload size is 15 MB.",
  "request_id": "3f1c9d2e8b4a4c0e9a7d1b2c3d4e5f60",
  "error": {
    "code": "FILE_TOO_LARGE",
    "message": "File too large. Maximum upload size is 15 MB.",
    "retryable": false,
    "request_id": "3f1c9d2e8b4a4c0e9a7d1b2c3d4e5f60"
  }
}

Decida según error.code, nunca según el texto. Códigos: INVALID_REQUEST, AUTHENTICATION_REQUIRED, PERMISSION_DENIED, NOT_FOUND, FILE_TOO_LARGE, UNSUPPORTED_DOCUMENT, RATE_LIMITED, QUOTA_EXCEEDED, IDEMPOTENCY_KEY_CONFLICT, PROCESSING_TIMEOUT, INTERNAL_ERROR. Reintente solo cuando retryable sea verdadero, respetando Retry-After, y reenvíe la misma Idempotency-Key. Indique request_id (también enviado en la cabecera X-Request-ID) al contactar con soporte.

Compatibilidad

Dentro de /api/v1 los cambios son solo aditivos: rutas, campos, códigos de error y estados de trabajo nunca se eliminan ni cambian de tipo. Los cambios incompatibles se publican como /api/v2 con al menos 12 meses de solapamiento, anunciados en el registro de cambios y con las cabeceras Deprecation y Sunset. Lea GET /api/v1/capabilities al arrancar en lugar de fijar formatos y límites en el código.

Extracción síncrona de documentos

POST/api/v1/analyze

Sube un documento y obtén los resultados de extracción de forma síncrona. Ideal para documentos pequeños (< 2 páginas).

Solicitud

Datos de formulario multipart:

CampoTipoDescripción
filefileobligatorioPDF, PNG, JPG, HEIC, AVIF, TIFF, BMP o WEBP (máx. 15 MB)
filenamestringopcionalSustituye el nombre de archivo mostrado

Ejemplo

curl -X POST https://docsolved.ai/api/v1/analyze \
  -H "Authorization: Bearer sk_docai_..." \
  -F "file=@purchase_order.pdf"

Respuesta

{
  "request_id": "3fa8...",
  "filename": "purchase_order.pdf",
  "document_type": "purchase_order",
  "document_type_confidence": 0.94,
  "summary": "Purchase order from Acme Corp to Widget Co.",
  "language": "en",
  "extracted_fields": [
    {
      "field": "po_number",
      "value": "PO-2026-0042",
      "confidence": 0.97,
      "page": 1,
      "evidence": "PO-2026-0042"
    }
  ],
  "warnings": [],
  "ocr": { "pages": 1, "tokens": 312, "language": "eng+pol" },
  "llm": { "status": "success", "provider": "openai", "model": "gpt-4o-mini" }
}

Extracción por streaming (SSE)

POST/api/v1/analyze/stream

Igual que la síncrona, pero transmite Server-Sent Events que muestran el progreso del procesamiento. Ideal para interfaces en tiempo real.

Crear trabajo asíncrono

POST/api/v1/jobs

Sube un documento y obtén un ID de trabajo. El procesamiento se realiza en segundo plano.

curl -X POST https://docsolved.ai/api/v1/jobs \
  -H "Authorization: Bearer sk_docai_..." \
  -F "[email protected]"
{ "job_id": "abc123", "status": "queued", "request_id": "xyz..." }

Ingerir adjuntos de correo

POST/api/v1/ingest/email

Puente de correo entrante independiente del proveedor. Postmark, Mailgun, SendGrid, Amazon SES, Make, n8n u otro adaptador debe analizar la carga útil del proveedor y enviar los adjuntos aceptados como datos de formulario multipart. DocSolved no aloja un buzón ni analiza MIME de forma específica para cada proveedor.

CampoTipoDescripción
message_idstringobligatorioIdentificador de mensaje estable del proveedor
source_namespacestringobligatorioÁmbito estable de proveedor/cuenta, como postmark:server-123
filesfile[]obligatorioRepetir para cada adjunto admitido
organization_idstringopcionalEspacio de trabajo de destino; quien llama debe tener permiso de carga
curl -X POST https://docsolved.ai/api/v1/ingest/email \
  -H "Authorization: Bearer sk_docai_..." \
  -F "message_id=provider-message-42" \
  -F "source_namespace=postmark:server-123" \
  -F "organization_id=org_..." \
  -F "[email protected];type=application/pdf" \
  -F "[email protected];type=image/jpeg"
{
  "message_id": "provider-message-42",
  "source_namespace": "postmark:server-123",
  "accepted_count": 1,
  "duplicate_count": 1,
  "jobs": [
    {"job_id": "job-new", "status": "queued", "filename": "invoice.pdf", "duplicate": false},
    {"job_id": "job-old", "status": "completed", "filename": "receipt.jpg", "duplicate": true}
  ]
}

La idempotencia incluye al propietario autenticado, el espacio de nombres de proveedor/cuenta, el destino, el ID del mensaje, el nombre de archivo normalizado, el contenido del archivo y la aparición entre adjuntos idénticos. Los reintentos reordenados del proveedor devuelven los ID de trabajo originales. Una ingesta fallida puede volver a poner en cola el mismo trabajo con bytes nuevos hasta tres intentos en total; los trabajos activos y completados nunca se procesan dos veces.

Obtener estado del trabajo

GET/api/v1/jobs/{job_id}

curl https://docsolved.ai/api/v1/jobs/abc123 \
  -H "Authorization: Bearer sk_docai_..."
{
  "id": "abc123",
  "status": "completed",
  "progress_pct": 100,
  "document_type": "invoice",
  "pages_processed": 2
}

Estados posibles: queued, processing, review_required, completed, failed, cancelled.

Obtener resultado del trabajo

GET/api/v1/jobs/{job_id}/result

Devuelve el resultado completo de la extracción cuando el estado del trabajo es completed o review_required. Acepta el ámbito extract o history, de modo que una clave solo con extract cubre todo el ciclo de envío, consulta y resultado.

curl https://docsolved.ai/api/v1/jobs/abc123/result \
  -H "Authorization: Bearer sk_docai_..."

Exportar JSON

POST/api/v1/export/json

Envía el resultado de la extracción como cuerpo JSON y obtén un archivo de exportación limpio.

curl -X POST https://docsolved.ai/api/v1/export/json \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_docai_..." \
  -d '{"request_id":"...","extracted_fields":[...]}' \
  -o export.json

Exportar CSV

POST/api/v1/export/csv

curl -X POST https://docsolved.ai/api/v1/export/csv \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_docai_..." \
  -d '{"request_id":"...","extracted_fields":[...]}' \
  -o fields.csv

Exportar XLSX

POST/api/v1/export/xlsx

Devuelve un libro de Excel con hojas de Resumen, Campos, Líneas de detalle, Advertencias y Metadatos.

Listar historial

GET/api/v1/history

curl https://docsolved.ai/api/v1/history \
  -H "Authorization: Bearer sk_docai_..."

Flujo de revisión y aprobación

POST/api/v1/history/{record_id}/workflow

Aplica una transición controlada del flujo de trabajo a un registro guardado. Esta ruta requiere una sesión interactiva de Clerk: las claves API no pueden aprobar documentos. Los miembros del espacio de trabajo pueden revisar; los administradores pueden aprobar, solicitar cambios o rechazar. El propietario de un registro personal desempeña ambas funciones.

{
  "action": "approve",
  "comment": "Ready to post"
}

Acciones: start_review, complete_review, reopen_review, submit_for_approval, approve, request_changes, reject y accept_partial_analysis. La aprobación confirma conjuntamente el evento de auditoría del flujo de trabajo y el evento de bandeja de salida document.approved.

Eliminar todo el historial

DELETE/api/v1/history

Elimina permanentemente todos los análisis guardados de tu cuenta.

Listar claves de API

GET/api/v1/keys

Crear clave de API

POST/api/v1/keys

curl -X POST https://docsolved.ai/api/v1/keys \
  -H "Authorization: Bearer <clerk_session_token>" \
  -H "Content-Type: application/json" \
          -d '{"name": "My automation key", "scopes": "extract,history"}'
{
  "id": "...",
  "name": "My automation key",
  "key": "sk_docai_...",   // shown ONCE - save it now
  "prefix": "sk_docai_abc",
  "scopes": "extract,history",
  "created_at": "2026-06-10T12:00:00Z"
}

Revocar clave de API

DELETE/api/v1/keys/{key_id}

Crear webhook

POST/api/v1/webhooks

curl -X POST https://docsolved.ai/api/v1/webhooks \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
          -d '{"name": "My webhook", "endpoint_url": "https://my.app/hook", "event_types": ["document.completed", "document.review_required", "document.approved", "document.failed"]}'

La respuesta incluye un secret para la verificación de la firma. Guárdalo ahora, no se volverá a mostrar.

Tipos de eventos de webhook

EventoCuándo se activa
document.completedLa extracción se completó y se guardó el resultado
document.review_requiredLa validación o el enrutamiento por confianza requiere revisión humana; también se activa con document.completed
document.approvedUn aprobador autorizado confirmó la decisión de aprobación; úsalo para registros contables
document.failedEl procesamiento falló; los trabajos ingeridos por correo incluyen metadatos de posibilidad de reintento e intentos
Usa document.approved, no document.completed, como punto de control para registrar datos en un sistema contable. La extracción puede completarse aunque los campos todavía requieran corrección.

Probar webhook

POST/api/v1/webhooks/{webhook_id}/test

Verificar la firma del webhook

Cada entrega incluye estas cabeceras:

import hashlib, hmac

def verify(secret, body_str, timestamp, signature_header):
    msg = f"{timestamp}.{body_str}"
    digest = hmac.new(secret.encode(), msg.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(f"sha256={digest}", signature_header)

Eventos duraderos fallidos

DocSolved vuelve a intentar automáticamente las entregas salientes. Si un evento duradero de bandeja de salida no se puede ampliar después de cinco intentos, se convierte en mensaje no entregable. El propietario puede inspeccionar los metadatos sin exponer la carga útil almacenada y volver a ejecutar el evento después de corregir la causa.

GET/api/v1/webhook-outbox/failed

curl https://docsolved.ai/api/v1/webhook-outbox/failed \
  -H "Authorization: Bearer sk_docai_..."

POST/api/v1/webhook-outbox/{event_id}/replay

curl -X POST https://docsolved.ai/api/v1/webhook-outbox/EVENT_ID/replay \
  -H "Authorization: Bearer sk_docai_..."

Los mismos controles están disponibles en Configuración para desarrolladores → Eventos que requieren atención. Los registros de entrega y de bandeja de salida terminal se conservan durante 30 días.

Uso con Make / n8n / Zapier

Para cargas directas, llama a /api/v1/jobs. Para correo entrante, deja que el proveedor analice los adjuntos y llame a /api/v1/ingest/email con un ID de mensaje y un espacio de nombres de origen estables. Ambas rutas crean los mismos trabajos persistentes y usan el mismo flujo de revisión.

Suscríbete a los eventos de finalización y revisión para conocer el estado, y luego usa document.approved para activar acciones contables posteriores controladas. Los webhooks firmados eliminan la necesidad de sondeo.

Preguntas frecuentes

¿Cómo me autentico con la API de DocSolved?

Crea una clave de API en /developer (se muestra solo una vez) y envíala como token Bearer en la cabecera Authorization: Authorization: Bearer sk_docai_your_key.

¿Cuál es la diferencia entre /api/v1/analyze y /api/v1/jobs?

/api/v1/analyze devuelve el resultado en la misma solicitud, lo que resulta adecuado para un uso interactivo. /api/v1/jobs pone el documento en una cola para que consultes el job o recibas un webhook firmado cuando termine, lo cual es mejor para lotes y documentos grandes.

¿Cómo se me notifica cuando un documento ha finalizado?

Registra un webhook. DocSolved envía mediante POST un evento firmado con HMAC-SHA256 en document.completed, document.review_required, document.failed y document.approved. Verifica la cabecera X-DocAI-Signature y responde con un HTTP 2xx en un plazo de cinco segundos.

¿Devuelve la API evidencia de origen para los valores extraídos?

En los documentos escaneados, cada campo lleva el texto del que se leyó y, cuando el OCR localizó el valor, su página y su cuadro delimitador. Las facturas electrónicas estructuradas se analizan a partir de su XML y, por diseño, no llevan cuadro delimitador.