# Referencia de la API de Lotes — Iniciar, Exportar y Eliminar

> Inicie la extracción en un lote de documentos subidos, liste y filtre sus lotes, consulte el estado agregado, obtenga los resultados JSON reorganizados, exporte a Excel/Word y elimine lotes para la API v1 de ImageToTable.ai.

Un **lote** es un grupo con nombre de uno o más [Documentos](/developers/reference/documents) que usted procesa, consulta y cuyos resultados obtiene en conjunto. No crea un lote explícitamente; se crea implícitamente la primera vez que sube un documento con ese `batch_name` (consulte [Subir un documento](/developers/reference/documents#upload-a-document)).

## Iniciar el procesamiento de un lote

Inicia la extracción en cada documento elegible actualmente en el lote (cualquiera que no esté ya en estado `processing` o `succeeded`). Este es el endpoint que realmente consume créditos: uno por documento encolado.

`POST /api/v1/batches/{batch_name}/process`

### Parámetros

| Nombre | Ubicación | Tipo | Descripción |
| --- | --- | --- | --- |
| batch_name | path | string | El lote a procesar. |
| template_id | body (JSON) | integer, opcional | Una plantilla guardada para aplicar. Tiene prioridad sobre fields si se proporcionan ambos. |
| fields | body (JSON) | array, opcional | Lista de campos ad-hoc solo para esta ejecución — [{"name": "...", "format_requirement": "..."}] o un array simple de cadenas con nombres. Se ignora si se proporciona template_id . Omita ambos para que el modelo infiera las columnas por sí mismo. |
| quality | body (JSON) | string, opcional | "fast" o "high" . Omítalo para recurrir a la configuración de thinking_type de su cuenta — consulte Configuración de la cuenta y comportamiento de la API . |
| webhook_url | body (JSON) | string, opcional | Registra (o actualiza) el callback de finalización de este lote en la misma llamada — equivalente a llamar también a Registrar un webhook de lote . Debe ser http:// o https:// . |
| Idempotency-Key | header, opcional | string | Muy recomendado — este endpoint descuenta créditos. Consulte Idempotencia . |

`quality` es la única configuración de cuenta que la API permite anular por llamada; cualquier otra preferencia a nivel de cuenta (anotación automática de bbox, política de retención) se lee de su cuenta y no se puede anular por solicitud. Consulte [Configuración de cuenta y comportamiento de la API](/developers/guides/account-settings) para obtener una visión completa, incluyendo por qué `auto_annotate_bbox` puede significar que esta llamada termine facturándole también la anotación de bbox, aunque nunca haya llamado a ese endpoint.

**El campo `webhook_registered` de la respuesta refleja solo esta llamada específica** — es `true` si y solo si *esta* solicitud incluyó `webhook_url`, no si el lote tiene un webhook en absoluto. Un lote cuyo webhook se configuró previamente mediante [Registrar un webhook de lote](/developers/reference/webhooks) (y no se repitió aquí) activará correctamente su callback al finalizar, pero este campo devuelve `false` para esa llamada — no verifica si ya existe un `BatchWebhook`. No interprete un `false` aquí como "no se activará ningún webhook para este lote".

Llamar a este endpoint nuevamente en un lote que ya procesó y del que fue notificado — después de cargar más documentos en él — reactiva automáticamente el webhook de ese lote si ya se había activado, de modo que la finalización de la nueva tanda también notifique. No se necesita ninguna llamada adicional para que esto ocurra; consulte la sección "Reprocesar un lote" de la [guía de Webhooks](/developers/guides/webhooks#reprocessing-a-batch) para conocer la semántica exacta (incluyendo qué sucede si dos tandas se superponen).

### Posibles errores

- `missing_api_key` / `invalid_api_key` / `plan_required` — consulte [Manejo de errores](/developers/guides/errors).
- `batch_not_found` — no existen documentos bajo este `batch_name` en su cuenta.
- `invalid_parameter` — valor incorrecto de `quality`/`webhook_url`/`template_id`, o no hay documentos en el lote actualmente elegibles para procesamiento (todos ya completados/en procesamiento, o el lote está vacío).
- `template_not_found`
- `insufficient_credits` — no hay suficientes créditos disponibles para cubrir los documentos que se están poniendo en cola.

## Listar lotes

Devuelve una lista resumida paginada y filtrable de sus lotes, el equivalente a "Files Filter" para consumidores de la API. Esto solo devuelve resúmenes (`document_count`, `status` agregado); use [Obtener resultados del lote](#get-batch-results) para obtener los datos completos por documento de un lote específico.

`GET /api/v1/batches`

### Parámetros

| Nombre | Ubicación | Tipo | Descripción |
| --- | --- | --- | --- |
| source | query, opcional | string | Uno de direct , collect , email_inbox , api (subido mediante POST /documents , distinto de direct que es la aplicación web principal), o share (un alias que cubre tanto collect como email_inbox ). Omita para todas las fuentes. |
| q | query, opcional | string | Coincidencia de subcadena sin distinción de mayúsculas/minúsculas contra los nombres de archivo dentro del lote. |
| date_from | query, opcional | string ( YYYY-MM-DD ) | Límite inferior inclusivo para la hora de subida. |
| date_to | query, opcional | string ( YYYY-MM-DD ) | Límite superior inclusivo para la hora de subida (fin del día). |
| status | query, opcional | string | Lista separada por comas de estados públicos ( queued,processing,succeeded,failed,canceled ) para filtrar. |
| template_id | query, opcional | integer | Solo lotes que usaron esta plantilla. |
| mode | query, opcional | string | El único valor aceptado en esta ronda es "table" (el único modo que v1 soporta actualmente). Reservado para futuros modos de extracción. |
| limit | query, opcional | integer | 1–100. Valor predeterminado 20. |
| page_token | query, opcional | string | Cursor opaco de next_page_token de una respuesta anterior. Consulte Paginación . |

### Posibles errores

- `missing_api_key` / `invalid_api_key` / `plan_required` — consulte [Manejo de errores](/developers/guides/errors).
- `invalid_parameter` — `mode`, `limit`, `status` o `page_token` incorrectos.

## Obtener estado del lote

Estado agregado ligero de un lote: recuentos por estado público más un indicador `all_done`, útil para un bucle de sondeo económico que aún no necesita la carga completa de resultados.

`GET /api/v1/batches/{batch_name}`

### Parámetros

| Nombre | Ubicación | Tipo | Descripción |
| --- | --- | --- | --- |
| batch_name | ruta | string | El lote a consultar. |

### Posibles errores

- `missing_api_key` / `invalid_api_key` / `plan_required` — consulte [Manejo de errores](/developers/guides/errors).
- `batch_not_found`

## Obtener resultados del lote

La forma principal de recuperar los datos extraídos. Cada documento del lote se devuelve con su arreglo `line_items` reorganizado: un arreglo de objetos `{field_name: value}`, uno por fila extraída. Los valores a nivel de campo son escalares simples de forma predeterminada (una cadena, un número, etc.).

`GET /api/v1/batches/{batch_name}/results`

### Parámetros

| Nombre | Ubicación | Tipo | Descripción |
| --- | --- | --- | --- |
| batch_name | ruta | string | El lote del que obtener los resultados. |
| include | consulta, opcional | string | "bbox" — al incluirlo, cada valor de campo se convierte en {"value": ..., "bbox": {...}|null} en lugar de un escalar simple, y cada documento recibe un campo bbox_status . Véase más abajo — esto nunca desencadena un nuevo trabajo de bbox, solo devuelve lo que ya se haya calculado. |

`?include=bbox` solo lee resultados ya rellenados; no llama a [Activar anotación bbox](/developers/reference/documents#trigger-bbox-annotation) por usted. Si nunca se activó bbox para un documento (manualmente o mediante la configuración `auto_annotate_bbox` de su cuenta), los campos de ese documento se devuelven con `"bbox": null`.

**Los campos de ubicación pura son una tercera forma distinta.** Algunos campos de la plantilla le piden al modelo que localice algo en lugar de transcribir texto (p. ej., "localice la foto de retrato"). Para esos campos, el valor completo *es* una ubicación, por lo que en lugar de un escalar o el par `{"value","bbox"}` anterior, obtiene `{"type": "image_region", "bbox": {...}, "image_url": "..."}`, **independientemente de si se incluyó `?include=bbox`** — aquí el recuadro no es metadato opcional, es el único contenido del campo. `image_url` apunta a un JPEG recortado listo para descargar (consulte [Obtener imagen de un documento](/developers/reference/documents#get-a-document-image)) para que no tenga que recortar el original usted mismo a partir de cuatro números.

Cada objeto `bbox` — en cualquiera de sus formas — usa `"unit": "normalized"`: las coordenadas son flotantes de 0 a 1 relativas al ancho/alto de la página, no píxeles ni una escala de 0 a 1000. Consulte la guía de [Bounding Boxes](/developers/guides/bbox) para conocer la advertencia de precisión: estas coordenadas provienen directamente del modelo sin una verificación a nivel de píxel, así que considérelas como "aproximadas" en lugar de exactas en documentos densos o complejos.

### Posibles errores

- `missing_api_key` / `invalid_api_key` / `plan_required` — consulte [Error Handling](/developers/guides/errors).
- `batch_not_found`

## Exportar un lote

Una descarga de conveniencia — `results` arriba es el formato canónico y estructurado para el que está diseñada esta API; este endpoint existe para extraer los mismos datos en una hoja de cálculo sin necesidad de escribir código de reestructuración usted mismo. Solo xlsx — v1 solo admite el modo tabla (extract), y la exportación a Word (docx) en la aplicación principal es exclusivamente la salida nativa del modo page_word (un prompt y una forma de resultado completamente diferentes), que v1 no expone. No existe una opción de "datos de tabla como documento de Word" aquí.

`GET /api/v1/batches/{batch_name}/export`

### Parámetros

| Nombre | Ubicación | Tipo | Descripción |
| --- | --- | --- | --- |
| batch_name | path | string | El lote a exportar. |
| format | query, opcional | string | Solo se acepta xlsx (el valor predeterminado). |

La respuesta es una descarga de archivo (`Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`), no JSON — no hay un ejemplo de JSON de respuesta para este endpoint.

### Posibles errores

- `missing_api_key` / `invalid_api_key` / `plan_required` — consulte [Manejo de errores](/developers/guides/errors).
- `batch_not_found`
- `invalid_parameter` (`param: "format"`) — cualquier valor que no sea `xlsx`.

## Eliminar un lote

Elimina permanentemente todos los documentos del lote. Cualquier documento que aún esté `queued` se reembolsa antes de la eliminación. Esto también elimina el registro del webhook del lote (si lo hubiera) y cualquier trabajo de anotación de bbox vinculado a sus documentos.

`DELETE /api/v1/batches/{batch_name}`

### Parámetros

| Nombre | Ubicación | Tipo | Descripción |
| --- | --- | --- | --- |
| batch_name | ruta | string | El lote a eliminar. |

### Posibles errores

- `missing_api_key` / `invalid_api_key` / `plan_required` — consulte [Manejo de errores](/developers/guides/errors).
- `batch_not_found` — a diferencia de otros recursos, eliminar un `batch_name` que no le pertenece (o que no existe) devuelve un 404 aquí, no una operación silenciosa sin efecto.

## Code Examples

### Iniciar procesamiento de un lote

POST /api/v1/batches/{batch_name}/process

**cURL**

```bash
curl -X POST https://imagetotable.ai/api/v1/batches/july-invoices/process \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
        "fields": [
          {"name": "invoice_number"},
          {"name": "invoice_date", "format_requirement": "YYYY-MM-DD"},
          {"name": "total_amount"}
        ],
        "quality": "high",
        "webhook_url": "https://example.com/webhooks/imagetotable"
      }'
```

**Python**

```python
import os
import uuid
import requests

response = requests.post(
    "https://imagetotable.ai/api/v1/batches/july-invoices/process",
    headers={
        "Authorization": f"Bearer {os.environ['API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "fields": [
            {"name": "invoice_number"},
            {"name": "invoice_date", "format_requirement": "YYYY-MM-DD"},
            {"name": "total_amount"},
        ],
        "quality": "high",
        "webhook_url": "https://example.com/webhooks/imagetotable",
    },
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/batches/july-invoices/process", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    fields: [
      { name: "invoice_number" },
      { name: "invoice_date", format_requirement: "YYYY-MM-DD" },
      { name: "total_amount" },
    ],
    quality: "high",
    webhook_url: "https://example.com/webhooks/imagetotable",
  }),
});
console.log(await response.json());
```

### Respuesta

```json
{
  "batch_name": "july-invoices",
  "queued": 3,
  "quality": "high",
  "webhook_registered": true
}
```

### Iniciar procesamiento — con una plantilla guardada

POST /api/v1/batches/{batch_name}/process

La otra de las dos formas de especificar qué extraer: `template_id` tiene prioridad sobre `fields` si envía ambos, y es la opción más común cuando reutiliza la misma lista de columnas en varias ejecuciones en lugar de declararla ad-hoc cada vez.

**cURL**

```bash
curl -X POST https://imagetotable.ai/api/v1/batches/july-invoices/process \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"template_id": 42}'
```

**Python**

```python
import os
import uuid
import requests

response = requests.post(
    "https://imagetotable.ai/api/v1/batches/july-invoices/process",
    headers={
        "Authorization": f"Bearer {os.environ['API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={"template_id": 42},
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/batches/july-invoices/process", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ template_id: 42 }),
});
console.log(await response.json());
```

### Respuesta

```json
{
  "batch_name": "july-invoices",
  "queued": 3,
  "quality": "fast",
  "webhook_registered": false
}
```

Aquí `quality` es `"fast"` porque se omitió en la solicitud y se usó la configuración de `thinking_type` de la cuenta, no porque se usara una plantilla — `template_id`/`fields` y `quality` son parámetros independientes.

### Listar lotes

GET /api/v1/batches

**cURL**

```bash
curl "https://imagetotable.ai/api/v1/batches?status=succeeded&limit=20" \
  -H "Authorization: Bearer $API_KEY"
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/batches",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    params={"status": "succeeded", "limit": 20},
)
print(response.json())
```

**Javascript**

```javascript
const url = new URL("https://imagetotable.ai/api/v1/batches");
url.searchParams.set("status", "succeeded");
url.searchParams.set("limit", "20");

const response = await fetch(url, {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
console.log(await response.json());
```

### Respuesta

```json
{
  "data": [
    {
      "batch_name": "july-invoices",
      "status": "succeeded",
      "document_count": 3,
      "created_at": "2026-07-16T09:12:03+00:00"
    }
  ],
  "has_more": false,
  "next_page_token": null
}
```

### Obtener estado del lote

GET /api/v1/batches/{batch_name}

**cURL**

```bash
curl https://imagetotable.ai/api/v1/batches/july-invoices \
  -H "Authorization: Bearer $API_KEY"
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/batches/july-invoices",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/batches/july-invoices", {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
console.log(await response.json());
```

### Respuesta

```json
{
  "batch_name": "july-invoices",
  "document_count": 3,
  "status_counts": {
    "queued": 0,
    "processing": 0,
    "succeeded": 3,
    "failed": 0,
    "canceled": 0
  },
  "all_done": true,
  "created_at": "2026-07-16T09:12:03+00:00"
}
```

### Obtener resultados del lote

GET /api/v1/batches/{batch_name}/results

**cURL**

```bash
curl https://imagetotable.ai/api/v1/batches/july-invoices/results \
  -H "Authorization: Bearer $API_KEY"
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/batches/july-invoices/results",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/batches/july-invoices/results", {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
console.log(await response.json());
```

### Respuesta — predeterminada (sin include)

```json
{
  "batch_name": "july-invoices",
  "status": "succeeded",
  "created_at": "2026-07-16T09:12:03+00:00",
  "started_at": "2026-07-16T09:12:05+00:00",
  "completed_at": "2026-07-16T09:12:14+00:00",
  "documents": [
    {
      "document_id": "8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
      "filename": "invoice_042.jpg",
      "status": "succeeded",
      "created_at": "2026-07-16T09:12:03+00:00",
      "started_at": "2026-07-16T09:12:05+00:00",
      "completed_at": "2026-07-16T09:12:14+00:00",
      "line_items": [
        {
          "invoice_number": "INV-1042",
          "invoice_date": "2026-07-01",
          "total_amount": "1,204.50"
        }
      ]
    }
  ]
}
```

### Obtener resultados del lote — con bbox

GET /api/v1/batches/{batch_name}/results?include=bbox

**cURL**

```bash
curl "https://imagetotable.ai/api/v1/batches/july-invoices/results?include=bbox" \
  -H "Authorization: Bearer $API_KEY"
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/batches/july-invoices/results",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    params={"include": "bbox"},
)
print(response.json())
```

**Javascript**

```javascript
const url = new URL("https://imagetotable.ai/api/v1/batches/july-invoices/results");
url.searchParams.set("include", "bbox");

const response = await fetch(url, {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
console.log(await response.json());
```

### Respuesta — `?include=bbox`

```json
{
  "batch_name": "july-invoices",
  "status": "succeeded",
  "created_at": "2026-07-16T09:12:03+00:00",
  "started_at": "2026-07-16T09:12:05+00:00",
  "completed_at": "2026-07-16T09:12:14+00:00",
  "documents": [
    {
      "document_id": "8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
      "filename": "invoice_042.jpg",
      "status": "succeeded",
      "created_at": "2026-07-16T09:12:03+00:00",
      "started_at": "2026-07-16T09:12:05+00:00",
      "completed_at": "2026-07-16T09:12:14+00:00",
      "bbox_status": "succeeded",
      "line_items": [
        {
          "invoice_number": {
            "value": "INV-1042",
            "bbox": {"x1": 0.121, "y1": 0.084, "x2": 0.418, "y2": 0.112, "unit": "normalized"}
          },
          "total_amount": {
            "value": "1,204.50",
            "bbox": null
          },
          "portrait_photo": {
            "type": "image_region",
            "bbox": {"x1": 0.740, "y1": 0.060, "x2": 0.920, "y2": 0.260, "unit": "normalized"},
            "image_url": "https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/image?crop=0.7241%2C0.0426%2C0.9359%2C0.2774"
          }
        }
      ]
    }
  ]
}
```

### Exportar un lote

GET /api/v1/batches/{batch_name}/export

**cURL**

```bash
curl "https://imagetotable.ai/api/v1/batches/july-invoices/export?format=xlsx" \
  -H "Authorization: Bearer $API_KEY" \
  -o july-invoices.xlsx
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/batches/july-invoices/export",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    params={"format": "xlsx"},
)
with open("july-invoices.xlsx", "wb") as f:
    f.write(response.content)
```

**Javascript**

```javascript
import { writeFile } from "node:fs/promises";

const url = new URL("https://imagetotable.ai/api/v1/batches/july-invoices/export");
url.searchParams.set("format", "xlsx");

const response = await fetch(url, {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
await writeFile("july-invoices.xlsx", Buffer.from(await response.arrayBuffer()));
```

### Eliminar un lote

DELETE /api/v1/batches/{batch_name}

**cURL**

```bash
curl -X DELETE https://imagetotable.ai/api/v1/batches/july-invoices \
  -H "Authorization: Bearer $API_KEY"
```

**Python**

```python
import os
import requests

response = requests.delete(
    "https://imagetotable.ai/api/v1/batches/july-invoices",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/batches/july-invoices", {
  method: "DELETE",
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
console.log(await response.json());
```

### Respuesta

```json
{
  "batch_name": "july-invoices",
  "deleted": 3,
  "canceled": 1
}
```

---

Source: https://imagetotable.ai/es/developers/reference/batches
