# Dokumente-API-Referenz — Upload, Status & bbox

> Dokumente und Bilder hochladen, deren Extraktionsstatus abfragen, ein Seitenbild oder einen normalisierten Ausschnitt davon abrufen und optionale Bounding-Box-Positionierung für die ImageToTable.ai v1-API auslösen.

Ein **Dokument** ist eine einzelne verarbeitete Seite – ein hochgeladenes Bild oder eine aus einem hochgeladenen PDF gerenderte Seite. Jedes Dokument gehört zu einem [Batch](/developers/reference/batches) (identifiziert durch `batch_name`), der die eigentliche Verarbeitungseinheit darstellt. Beim Hochladen eines mehrseitigen PDFs wird *ein Dokument pro Seite* im selben Batch erstellt – siehe [Dokument hochladen](#upload-a-document) unten.

## Dokument hochladen

Lädt eine einzelne Datei (Bild oder PDF) in einen Batch hoch. Wenn `batch_name` weggelassen wird, wird einer automatisch generiert und in der Antwort zurückgegeben. Das Hochladen startet keine Extraktion – rufen Sie [Batch-Verarbeitung starten](/developers/reference/batches#start-processing-a-batch) auf, sobald Sie alles hochgeladen haben, was zusammen verarbeitet werden soll. Das `remaining_batch_capacity`-Feld der Antwort gibt an, wie viele weitere Dokumente dieser Batch aufnehmen kann, bevor die maximale Batch-Größe Ihres Plans erreicht ist (siehe `max_batch_size` im [Konto](/developers/reference/account)) – nützlich, um clientseitig zu entscheiden, ob Sie diesem Batch weitere Dokumente hinzufügen oder einen neuen beginnen sollen, ohne eine separate Abfrage durchführen zu müssen.

`POST /api/v1/documents`

### Parameter

| Name | Ort | Typ | Beschreibung |
| --- | --- | --- | --- |
| file | body (multipart) | file | Erforderlich, falls url nicht angegeben wird. Ein Bild (JPEG/PNG/etc.) oder ein PDF. PDFs sind auf 30 Seiten pro Upload begrenzt und werden in ein Dokument pro Seite aufgeteilt. |
| url | body (multipart) | string, optional | Alternative zu file – der Server lädt die Datei von dieser URL herunter, anstatt dass Sie sie anhängen müssen. Schließt sich gegenseitig mit file aus; übergeben Sie genau eines. Muss eine öffentliche http:// - oder https:// -URL sein (keine localhost/Privatnetzwerk-Adressen); der Download ist auf 30 MB mit einem Lese-Timeout von 15 Sekunden begrenzt. |
| batch_name | body (multipart) | string, optional | Batch, dem dieses Dokument hinzugefügt werden soll. Auslassen, um automatisch einen neuen Batch-Namen zu generieren (wird in der Antwort zurückgegeben). Verwenden Sie denselben Wert bei mehreren Uploads, um einen Batch aufzubauen, bevor Sie ihn verarbeiten. |
| template_id | body (multipart) | integer, optional | Eine Template -ID, die zu Ihrem Konto gehört, um sie diesem Dokument vorab zuzuordnen. Nicht erforderlich – Sie können auch ein Template (oder Ad-hoc-Felder) übergeben, wenn Sie process aufrufen. |
| password | body (multipart) | string, optional | Nur für PDF. Wird zuerst versucht, wenn die Datei passwortgeschützt ist. Wenn es weggelassen wird oder die Datei nicht entsperrt, wird auf bereits unter den Email-Inbox-Einstellungen Ihres Kontos gespeicherte Passwörter zurückgegriffen – dieses Feld erfordert keine eingerichtete Email Inbox, es ist nur eine alternative Angabe pro Aufruf. |
| Idempotency-Key | header, optional | string | Sicher wiederholbar. Siehe Idempotenz . |

**PDF-Uploads geben ein Array zurück, keine einzelne ID.** Beim Hochladen eines PDFs wird jede Seite als eigenes Dokument gerendert und das `document_id`-Feld der Antwort wird zu einem JSON-Array (ein String pro Seite, in Seitenreihenfolge), plus ein `page_count`-Feld. Ein einzelner Bild-Upload gibt stattdessen einen skalaren String zurück. Client-Code, der annimmt, dass `document_id` immer ein String ist, wird bei einem PDF-Upload fehlschlagen – prüfen Sie, ob die gesendete Datei ein PDF ist, und verzweigen Sie basierend auf der Antwortform, oder senden Sie immer Bilder und verlassen Sie sich nie auf den skalaren Fall. Siehe die beiden Antwortbeispiele rechts.

### Mögliche Fehler

- `missing_api_key` / `invalid_api_key` / `plan_required` — siehe [Fehlerbehandlung](/developers/guides/errors).
- `missing_parameter` — es wurde weder `file` noch `url` gesendet.
- `invalid_parameter` (`param: "file"`) — ungültiges oder beschädigtes Bild/PDF, ein passwortgeschütztes PDF, das nicht entsperrt werden konnte (weder das `password`-Feld noch ein gespeichertes Email-Inbox-Passwort funktionierte), oder ein PDF, das die 30-Seiten-Grenze überschreitet.
- `invalid_parameter` (`param: "url"`) — sowohl `file` als auch `url` wurden gesendet, die URL löst keine öffentliche Adresse auf, der Download ist fehlgeschlagen oder abgelaufen, oder die heruntergeladene Datei überschreitet 30 MB.
- `invalid_parameter` (`param: "batch_name"`) — der Batch hat bereits die maximale Batch-Größe Ihres Tarifs erreicht.
- `invalid_parameter` (`param: "template_id"`) oder `template_not_found`.
- `rate_limit_exceeded` — es befinden sich bereits zu viele unverarbeitete (queued) Dokumente auf dem Konto; verarbeiten oder löschen Sie zuerst einige.

## Dokument abrufen

Ruft den aktuellen Status eines einzelnen Dokuments sowie nach erfolgreicher Extraktion dessen umgeformte `line_items` ab. Dies ist das Einzeldokument-Äquivalent zu [Batch-Ergebnisse abrufen](/developers/reference/batches#get-batch-results) — gleiche Umformungsregeln, jedoch ohne die Option `?include=bbox` (diese gibt es nur auf dem Batch-Ergebnis-Endpunkt).

`GET /api/v1/documents/{document_id}`

### Parameter

| Name | Ort | Typ | Beschreibung |
| --- | --- | --- | --- |
| document_id | Pfad | Zeichenkette | Die Dokument-ID, die von POST /documents zurückgegeben wurde (oder ein Eintrag dieses Arrays für eine PDF-Seite). |

`status` ist immer einer der Werte `queued`, `processing`, `succeeded`, `failed`, `canceled` — siehe die Anleitung zum [Async-Modell](/developers/guides/async-model) für die Zustandsmaschine. `completed_at` wird gesetzt, sobald das Dokument einen Endzustand (`succeeded`, `failed` oder `canceled`) erreicht, und bleibt davor `null`.

### Mögliche Fehler

- `missing_api_key` / `invalid_api_key` / `plan_required` — siehe [Fehlerbehandlung](/developers/guides/errors).
- `document_not_found` — kein Dokument mit dieser ID auf Ihrem Konto.

## Dokumentenbild abrufen

Gibt das Seitenbild hinter einem Dokument zurück — standardmäßig die gesamte Seite oder einen normalisierten Ausschnitt davon mit `?crop=`. Dies ist die Grundlage für `image_url` bei reinen Positionsfeldern (siehe [Batch-Ergebnisse abrufen](/developers/reference/batches#get-batch-results)), kann aber auch direkt mit eigenen Koordinaten aufgerufen werden.

`GET /api/v1/documents/{document_id}/image`

### Parameter

| Name | Ort | Typ | Beschreibung |
| --- | --- | --- | --- |
| document_id | Pfad | Zeichenkette | Die Dokumenten-ID. |
| crop | Abfrage, optional | Zeichenkette | "x1,y1,x2,y2" — vier Gleitkommazahlen zwischen 0 und 1, dieselbe normalisierte Koordinatenkonvention wie jedes bbox -Objekt in der API. Weglassen, um das vollständige, unbeschnittene Seitenbild zu erhalten. |

Die Antwort sind die rohen Bildbytes (`Content-Type: image/jpeg`), kein JSON — es gibt kein JSON-Antwortbeispiel auf der rechten Seite für diesen Endpunkt, nur die Anfrage.

### Mögliche Fehler

- `missing_api_key` / `invalid_api_key` / `plan_required` — siehe [Fehlerbehandlung](/developers/guides/errors).
- `document_not_found` — kein Dokument mit dieser ID, oder die ursprüngliche Bilddatei ist nicht mehr verfügbar (z. B. das automatische Löschfenster Ihres Kontos ist überschritten).
- `invalid_parameter` (`param: "crop"`) — fehlerhafter `crop`-Wert, Koordinaten außerhalb von 0–1 oder ein Ausschnittbereich, der nach dem Beschneiden auf die Bildgrenzen leer ist.

## Bbox-Annotation auslösen

Startet explizit den optionalen, **kostenpflichtigen** Zweitdurchlauf, der lokalisiert, wo jeder extrahierte Feldwert physisch auf der Seite sitzt. Dies ist eine separate abrechenbare Aktion von der Extraktion selbst – siehe die [Bounding Boxes](/developers/guides/bbox)-Anleitung, bevor Sie dies einbinden, insbesondere den Hinweis zur `auto_annotate_bbox`-Einstellung Ihres Kontos, die möglicherweise denselben Job automatisch auslöst (und abrechnet), ohne dass Sie diesen Endpunkt jemals aufrufen.

`POST /api/v1/documents/{document_id}/bbox`

### Parameter

| Name | Ort | Typ | Beschreibung |
| --- | --- | --- | --- |
| document_id | Pfad | string | Muss bereits ein succeeded -Dokument mit extrahierten Daten sein – Sie können kein Dokument annotieren, dessen Extraktion noch nicht abgeschlossen ist. |
| Idempotency-Key | Header, optional | string | Empfohlen – diese Aktion verbraucht Guthaben. Siehe Idempotenz . |

Gibt **202** zurück, wenn ein neuer Bbox-Job gerade in die Warteschlange gestellt wurde, oder **200**, wenn ein *Bbox*-Job für dieses Dokument bereits läuft (`already_running: true`) – d.h. Sie haben diesen Endpunkt bereits einmal für dieses Dokument aufgerufen und dieser frühere Bbox-Job ist noch nicht abgeschlossen. Dies ist unabhängig davon, ob die Extraktion des Dokuments selbst abgeschlossen ist – Bbox kann nur für ein Dokument ausgelöst werden, das bereits `succeeded` ist (siehe „Mögliche Fehler" unten). Wenn Sie diesen Endpunkt überhaupt aufrufen können, ist die Extraktion also abgeschlossen. `already_running` bezieht sich ausschließlich auf einen *zweiten Bbox-Job* für dasselbe Dokument, nicht auf den Extraktionsjob. In beiden Fällen (202 oder 200) wird auf dem 200-Pfad nichts Neues gestartet oder berechnet – rufen Sie [Bbox-Annotation abrufen](#get-bbox-annotation) mit der zurückgegebenen `group_batch_id` für das Ergebnis auf.

### Mögliche Fehler

- `missing_api_key` / `invalid_api_key` / `plan_required` — siehe [Fehlerbehandlung](/developers/guides/errors).
- `document_not_found` — kein Dokument mit dieser ID auf Ihrem Konto.
- `insufficient_credits` — nicht genügend Credits für diesen Annotationsdurchlauf.
- `invalid_parameter` — das Dokument befindet sich noch in keinem gültigen Zustand dafür (wird noch verarbeitet) oder enthält keine extrahierten Daten, um Boxen zu lokalisieren.

## Bbox-Annotation abrufen

Ruft den Status des letzten für ein Dokument ausgelösten Bbox-Annotationsauftrags ab und holt dessen Ergebnisse. Wenn für dieses Dokument noch nie ein Auftrag ausgelöst wurde, ist `exists` `false` und `status`/`group_batch_id` sind `null` — dies ist eine normale, häufige Antwort (die meisten Dokumente haben nie eine Bbox-Annotation), kein Fehler.

`GET /api/v1/documents/{document_id}/bbox`

### Parameter

| Name | Ort | Typ | Beschreibung |
| --- | --- | --- | --- |
| document_id | Pfad | string | Die Dokument-ID. |

`rows` bildet einen Zeilenindex (als String, z. B. `"0"`) auf eine Map von Feldname → normalisiertem `bbox`-Objekt ab (oder `null`, wenn die Position dieses Feldes auf der Seite nicht gefunden wurde). `status` verwendet dasselbe geschlossene 5-Werte-Enum wie überall sonst in der API.

### Mögliche Fehler

- `missing_api_key` / `invalid_api_key` / `plan_required` — siehe [Fehlerbehandlung](/developers/guides/errors).
- `document_not_found` — kein Dokument mit dieser ID auf Ihrem Konto.

## Code Examples

### Dokument hochladen

POST /api/v1/documents

**cURL**

```bash
curl -X POST https://imagetotable.ai/api/v1/documents \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "file=@invoice.jpg" \
  -F "batch_name=july-invoices"
```

**Python**

```python
import os
import uuid
import requests

response = requests.post(
    "https://imagetotable.ai/api/v1/documents",
    headers={
        "Authorization": f"Bearer {os.environ['API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    files={"file": open("invoice.jpg", "rb")},
    data={"batch_name": "july-invoices"},
)
print(response.json())
```

**Javascript**

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

const formData = new FormData();
formData.append("file", new Blob([await readFile("invoice.jpg")]), "invoice.jpg");
formData.append("batch_name", "july-invoices");

const response = await fetch("https://imagetotable.ai/api/v1/documents", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: formData,
});
console.log(await response.json());
```

### Dokument hochladen — von einer URL

POST /api/v1/documents

Keine lokale Datei nötig — dieses Beispiel ist sofort ausführbar, da `invoice.webp` eine echte Datei auf unserer eigenen Website ist.

**cURL**

```bash
curl -X POST https://imagetotable.ai/api/v1/documents \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "url=https://imagetotable.ai/static/samples/invoice.webp" \
  -F "batch_name=july-invoices"
```

**Python**

```python
import os
import uuid
import requests

response = requests.post(
    "https://imagetotable.ai/api/v1/documents",
    headers={
        "Authorization": f"Bearer {os.environ['API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    data={
        "url": "https://imagetotable.ai/static/samples/invoice.webp",
        "batch_name": "july-invoices",
    },
)
print(response.json())
```

**Javascript**

```javascript
const formData = new FormData();
formData.append("url", "https://imagetotable.ai/static/samples/invoice.webp");
formData.append("batch_name", "july-invoices");

const response = await fetch("https://imagetotable.ai/api/v1/documents", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: formData,
});
console.log(await response.json());
```

### Antwort — Einzelbild

```json
{
  "document_id": "8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
  "batch_name": "july-invoices",
  "remaining_batch_capacity": 199
}
```

### Antwort — mehrseitiges PDF

```json
{
  "document_id": [
    "8f14e45f-ceea-467e-9de1-a3e9c93a9c95_p1",
    "8f14e45f-ceea-467e-9de1-a3e9c93a9c95_p2"
  ],
  "batch_name": "july-invoices",
  "page_count": 2,
  "remaining_batch_capacity": 198
}
```

### Dokument abrufen

GET /api/v1/documents/{document_id}

**cURL**

```bash
curl https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95 \
  -H "Authorization: Bearer $API_KEY"
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95", {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
console.log(await response.json());
```

### Antwort

```json
{
  "document_id": "8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
  "batch_name": "july-invoices",
  "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"
    }
  ]
}
```

### Dokumentbild abrufen — ganze Seite

GET /api/v1/documents/{document_id}/image

**cURL**

```bash
curl https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/image \
  -H "Authorization: Bearer $API_KEY" \
  -o page.jpg
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/image",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
)
with open("page.jpg", "wb") as f:
    f.write(response.content)
```

**Javascript**

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

const response = await fetch("https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/image", {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
await writeFile("page.jpg", Buffer.from(await response.arrayBuffer()));
```

### Dokumentbild abrufen — zugeschnitten

GET /api/v1/documents/{document_id}/image?crop=...

**cURL**

```bash
curl "https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/image?crop=0.10,0.08,0.42,0.30" \
  -H "Authorization: Bearer $API_KEY" \
  -o crop.jpg
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/image",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    params={"crop": "0.10,0.08,0.42,0.30"},
)
with open("crop.jpg", "wb") as f:
    f.write(response.content)
```

**Javascript**

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

const url = new URL("https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/image");
url.searchParams.set("crop", "0.10,0.08,0.42,0.30");

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

### Bbox-Annotation auslösen

POST /api/v1/documents/{document_id}/bbox

**cURL**

```bash
curl -X POST https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/bbox \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

**Python**

```python
import os
import uuid
import requests

response = requests.post(
    "https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/bbox",
    headers={
        "Authorization": f"Bearer {os.environ['API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/bbox", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
  },
});
console.log(await response.json());
```

### Antwort — 202, neuer Auftrag

```json
{
  "document_id": "8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
  "group_batch_id": "bx_8a3c2e1f",
  "status": "queued",
  "already_running": false,
  "row_groups": 1
}
```

### Antwort — 200, bereits in Bearbeitung

```json
{
  "document_id": "8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
  "group_batch_id": "bx_8a3c2e1f",
  "status": "processing",
  "already_running": true,
  "row_groups": 1
}
```

Es wurde nichts Neues gestartet oder berechnet – ein früherer Aufruf dieses Endpunkts für dieses Dokument hat bereits einen laufenden Auftrag. Rufen Sie in jedem Fall [Bbox-Annotation abrufen](#get-bbox-annotation) mit derselben `group_batch_id` auf.

### Bbox-Annotation abrufen

GET /api/v1/documents/{document_id}/bbox

**cURL**

```bash
curl https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/bbox \
  -H "Authorization: Bearer $API_KEY"
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/bbox",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
)
print(response.json())
```

**Javascript**

```javascript
const response = await fetch("https://imagetotable.ai/api/v1/documents/8f14e45f-ceea-467e-9de1-a3e9c93a9c95/bbox", {
  headers: { "Authorization": `Bearer ${process.env.API_KEY}` },
});
console.log(await response.json());
```

### Antwort

```json
{
  "document_id": "8f14e45f-ceea-467e-9de1-a3e9c93a9c95",
  "exists": true,
  "status": "succeeded",
  "group_batch_id": "bx_8a3c2e1f",
  "rows": {
    "0": {
      "invoice_number": {"x1": 0.121, "y1": 0.084, "x2": 0.418, "y2": 0.112, "unit": "normalized"},
      "total_amount": null
    }
  }
}
```

---

Source: https://imagetotable.ai/de/developers/reference/documents
