Skip to content

Ejecutar extracciones

Descripción general

El endpoint de extracción acepta un documento (codificado en base64), lo procesa a través de una plantilla que hayas definido y devuelve datos estructurados que coinciden con las variables de la plantilla. Una sola llamada a la API maneja todo el flujo -- carga, procesamiento con IA y salida estructurada.

Todas las solicitudes de extracción pasan por POST /v1/extractions/run.

Preparar tu documento

Antes de enviar un documento a la API, necesitas codificar el contenido del archivo en base64.

Restricciones:

  • Tamaño máximo del cuerpo de la solicitud: 15 MB
  • Tipos MIME compatibles:
    • application/pdf (PDF)
    • application/vnd.openxmlformats-officedocument.wordprocessingml.document (DOCX)
bash
# Base64-encode a PDF file
base64 -i invoice.pdf -o invoice_b64.txt

# Or inline (macOS / Linux)
PDF_BASE64=$(base64 -w 0 invoice.pdf)
typescript
import { readFileSync } from "fs";

const pdfBuffer = readFileSync("invoice.pdf");
const pdfBase64 = pdfBuffer.toString("base64");
python
import base64

with open("invoice.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

WARNING

La codificación en base64 aumenta el tamaño del archivo aproximadamente un 33%. Un PDF de 10 MB se convierte en aproximadamente 13,3 MB después de la codificación, así que mantén tus archivos fuente por debajo de ~11 MB para respetar el límite de 15 MB de la solicitud.

Realizar la solicitud

Envía una solicitud POST a /v1/extractions/run con el siguiente cuerpo JSON:

CampoTipoRequeridoDescripción
templateIdstringEl ID de la plantilla con la que extraer
fileNamestringNombre original del archivo (por ejemplo, "invoice.pdf")
pdfBase64stringContenido del archivo codificado en base64
mimeTypestringTipo MIME del archivo
runIdstringNoIdentificador opcional para agrupar múltiples extracciones en un lote
bash
curl -X POST https://api.docmap.io/v1/extractions/run \
  -H "Authorization: Bearer dm_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tmpl_abc123",
    "fileName": "invoice.pdf",
    "pdfBase64": "JVBERi0xLjQKJeLj...",
    "mimeType": "application/pdf"
  }'
typescript
const response = await fetch("https://api.docmap.io/v1/extractions/run", {
  method: "POST",
  headers: {
    Authorization: "Bearer dm_live_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    templateId: "tmpl_abc123",
    fileName: "invoice.pdf",
    pdfBase64: pdfBase64,
    mimeType: "application/pdf",
  }),
});

const { data } = await response.json();
console.log(data.extractedData);
python
import requests

response = requests.post(
    "https://api.docmap.io/v1/extractions/run",
    headers={
        "Authorization": "Bearer dm_live_your_api_key",
        "Content-Type": "application/json",
    },
    json={
        "templateId": "tmpl_abc123",
        "fileName": "invoice.pdf",
        "pdfBase64": pdf_base64,
        "mimeType": "application/pdf",
    },
)

data = response.json()["data"]
print(data["extractedData"])

Entender la respuesta

Una extracción exitosa devuelve una respuesta envuelta en un objeto data:

json
{
  "data": {
    "id": "ext_abc123def456",
    "userId": "user_789",
    "templateId": "tmpl_abc123",
    "templateName": "Invoice Parser",
    "fileName": "invoice.pdf",
    "status": "completed",
    "extractedData": {
      "vendor_name": "Acme Corp",
      "invoice_number": "INV-2024-001",
      "total_amount": 1250.00,
      "line_items": [
        { "description": "Widget A", "quantity": 10, "unit_price": 125.00 }
      ]
    },
    "error": null,
    "variables": [
      { "name": "vendor_name", "type": "string", "description": "Company name of the vendor" },
      { "name": "invoice_number", "type": "string", "description": "Invoice reference number" },
      { "name": "total_amount", "type": "number", "description": "Total invoice amount" },
      { "name": "line_items", "type": "array", "description": "List of line items" }
    ],
    "source": "api",
    "runId": null,
    "processingTimeMs": 3420,
    "createdAt": "2025-07-15T10:30:00.000Z"
  }
}
CampoDescripción
idID único de extracción (con prefijo ext_)
status"processing" mientras se ejecuta (modo asíncrono), "completed" si los datos se extrajeron correctamente, "failed" si el procesamiento encontró un error
extractedDataUn objeto cuyas claves coinciden con los nombres de las variables de tu plantilla. null si la extracción falló
errorCadena con el mensaje de error si la extracción falló. null en caso de éxito
processingTimeMsTiempo que la IA tardó en procesar el documento, en milisegundos
source"api" cuando se activó mediante clave API, "dashboard" cuando se activó desde la interfaz web
variablesLas definiciones de variables de la plantilla que se usaron para esta extracción
runIdEl identificador de lote que proporcionaste, o null si no se especificó
templateNameNombre legible de la plantilla utilizada
createdAtMarca de tiempo ISO 8601 de cuándo se creó la extracción

TIP

Siempre verifica el campo status antes de acceder a extractedData. Si status es "failed", el campo error contiene una descripción de lo que salió mal.

Extracciones por lotes

Para procesar múltiples archivos como un lote lógico, pasa el mismo runId a cada solicitud de extracción. Esto no cambia cómo se procesan los documentos -- cada archivo se extrae de forma independiente -- pero te permite consultar todos los resultados de un lote juntos.

typescript
const runId = "batch-invoices-2025-07";
const files = ["invoice-001.pdf", "invoice-002.pdf", "invoice-003.pdf"];

// Process each file with the same runId
const results = await Promise.all(
  files.map(async (fileName) => {
    const pdfBase64 = readFileSync(fileName).toString("base64");

    const response = await fetch("https://api.docmap.io/v1/extractions/run", {
      method: "POST",
      headers: {
        Authorization: "Bearer dm_live_your_api_key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        templateId: "tmpl_abc123",
        fileName,
        pdfBase64,
        mimeType: "application/pdf",
        runId,
      }),
    });

    return response.json();
  })
);

Luego recupera todas las extracciones del lote:

bash
curl "https://api.docmap.io/v1/extractions?runId=batch-invoices-2025-07" \
  -H "Authorization: Bearer dm_live_your_api_key"
typescript
const response = await fetch(
  "https://api.docmap.io/v1/extractions?runId=batch-invoices-2025-07",
  {
    headers: { Authorization: "Bearer dm_live_your_api_key" },
  }
);

const { data } = await response.json();
console.log(`Batch contains ${data.length} extractions`);
python
response = requests.get(
    "https://api.docmap.io/v1/extractions",
    params={"runId": "batch-invoices-2025-07"},
    headers={"Authorization": "Bearer dm_live_your_api_key"},
)

data = response.json()["data"]
print(f"Batch contains {len(data)} extractions")

TIP

El endpoint de listado también admite filtrado por templateId y un parámetro limit (1--100, predeterminado 50). Puedes combinar filtros: ?runId=batch-001&templateId=tmpl_abc123&limit=100.

Flujo de trabajo asíncrono

Por defecto, las solicitudes de extracción son sincrónicas -- la API bloquea hasta que el procesamiento finaliza. Para extracciones de larga duración o cuando quieras evitar timeouts HTTP, usa el modo asíncrono añadiendo ?async=true a la URL. La API responde inmediatamente con un estado "processing", y consultas un endpoint separado hasta que el resultado esté listo.

Patrón de envío + consulta periódica

typescript
import { readFileSync } from "fs";

const API_BASE = "https://api.docmap.io";
const API_KEY = process.env.DOCMAP_API_KEY!;

// 1. Submit the extraction asynchronously
const submitResponse = await fetch(`${API_BASE}/v1/extractions/run?async=true`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    templateId: "tmpl_abc123",
    fileName: "invoice.pdf",
    pdfBase64: readFileSync("invoice.pdf").toString("base64"),
    mimeType: "application/pdf",
  }),
});

const { data: submitted } = await submitResponse.json();
console.log(`Extraction ${submitted.id} submitted, status: ${submitted.status}`);

// 2. Poll until complete
async function poll(extractionId: string): Promise<any> {
  for (let i = 0; i < 30; i++) {
    const res = await fetch(`${API_BASE}/v1/extractions/${extractionId}`, {
      headers: { Authorization: `Bearer ${API_KEY}` },
    });
    const { data } = await res.json();
    if (data.status !== "processing") return data;
    await new Promise((r) => setTimeout(r, 2000));
  }
  throw new Error("Extraction timed out");
}

const result = await poll(submitted.id);
console.log(`Final status: ${result.status}`);
console.log("Extracted data:", result.extractedData);
python
import base64
import time
import requests

API_BASE = "https://api.docmap.io"
API_KEY = "dm_live_your_api_key"
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

# 1. Submit the extraction asynchronously
with open("invoice.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

submit_response = requests.post(
    f"{API_BASE}/v1/extractions/run?async=true",
    headers=headers,
    json={
        "templateId": "tmpl_abc123",
        "fileName": "invoice.pdf",
        "pdfBase64": pdf_base64,
        "mimeType": "application/pdf",
    },
)

submitted = submit_response.json()["data"]
print(f"Extraction {submitted['id']} submitted, status: {submitted['status']}")

# 2. Poll until complete
def poll(extraction_id: str):
    for _ in range(30):
        res = requests.get(
            f"{API_BASE}/v1/extractions/{extraction_id}",
            headers={"Authorization": f"Bearer {API_KEY}"},
        )
        data = res.json()["data"]
        if data["status"] != "processing":
            return data
        time.sleep(2)
    raise TimeoutError("Extraction timed out")

result = poll(submitted["id"])
print(f"Final status: {result['status']}")
print("Extracted data:", result["extractedData"])

Cuándo usar el modo asíncrono

Usa el modo asíncrono cuando proceses documentos grandes, cuando tu cliente HTTP tenga timeouts cortos, o cuando quieras enviar múltiples extracciones y recoger los resultados después. Para la mayoría de las extracciones de un solo documento, el modo sincrónico es más sencillo.

Ejemplo completo de flujo de trabajo

Aquí hay un ejemplo completo de extremo a extremo en TypeScript que lee un PDF del disco, ejecuta una extracción y maneja tanto el éxito como el fallo:

typescript
import { readFileSync } from "fs";

const API_BASE = "https://api.docmap.io";
const API_KEY = process.env.DOCMAP_API_KEY!;

async function extractInvoice(filePath: string) {
  // 1. Read and encode the PDF
  const pdfBuffer = readFileSync(filePath);
  const pdfBase64 = pdfBuffer.toString("base64");
  const fileName = filePath.split("/").pop()!;

  console.log(`Processing ${fileName} (${(pdfBuffer.length / 1024).toFixed(0)} KB)...`);

  // 2. Run the extraction
  const response = await fetch(`${API_BASE}/v1/extractions/run`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      templateId: "tmpl_invoice_parser",
      fileName,
      pdfBase64,
      mimeType: "application/pdf",
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`API error ${response.status}: ${error.error.message}`);
  }

  const { data } = await response.json();

  // 3. Check the extraction result
  if (data.status === "failed") {
    console.error(`Extraction failed: ${data.error}`);
    return null;
  }

  console.log(`Extraction completed in ${data.processingTimeMs}ms`);
  console.log("Extracted data:", JSON.stringify(data.extractedData, null, 2));

  return data.extractedData;
}

// Run it
extractInvoice("./invoices/invoice-001.pdf")
  .then((result) => {
    if (result) {
      console.log(`Vendor: ${result.vendor_name}`);
      console.log(`Total: $${result.total_amount}`);
    }
  })
  .catch(console.error);

Documentación de la API de DocMap