---
title: "API-Referenz"
description: "Jede Operation mit Scope, Kosten, Headern, Body und Fehlern, gebaut aus der eingefrorenen Spec. Beispiele in curl, TypeScript-SDK und Python-SDK."
lang: de
url: https://developers.bodo-app.com/reference/
apiVersion: 2026-11-01
---

# API-Referenz

Jede Operation mit Scope, Kosten, Headern, Body und Fehlern, gebaut aus der eingefrorenen Spec. Beispiele in curl, TypeScript-SDK und Python-SDK.

OpenAPI 3.1 · Version 2026-11-01 · 42 Operationen · curl · TypeScript · Python

## Codebeispiele

Jedes Beispiel läuft in der CI der SDKs gegen die Sandbox.

**Kontakt anlegen**

curl:

```bash
curl -X POST https://api.bodo-app.com/v1/contacts \
  -H "Authorization: Bearer $BODO_API_KEY" \
  -H "Bodo-Preview: true" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"firstName":"Erika","lastName":"Mustermann","email":"erika@musterfirma.de"}'
```

TypeScript · SDK:

```typescript
// Portal D3 · Reference — the contact operations with the SDK: create, read, list, update, delete.
// Run: BODO_API_KEY=bodo_uk_test_… bun examples/reference-contacts.ts
import { Bodo, BodoApiError } from "@bodo/api";

const bodo = new Bodo({ apiKey: process.env.BODO_API_KEY, preview: true, locale: "en" });

const created = await bodo.contacts.create(
  { firstName: "Max", lastName: "Mustermann", email: "max@musterfirma.de" },
  { idempotencyKey: `quickstart-${Date.now()}` }, // optional: your own key dedupes across processes
);

const read = await bodo.contacts.get(created.id);

// Optimistic update: If-Match with the revision you read.
const updated = await bodo.contacts.update(
  read.id,
  { jobTitle: "Einkauf" },
  { ifMatch: `"r${String(read.revision)}"` },
);
console.log(updated.jobTitle);

// The iterator follows nextCursor by itself.
for await (const contact of bodo.contacts.list({
  updatedSince: "2026-11-01T00:00:00Z",
  limit: 50,
})) {
  if ("deleted" in contact) continue; // deletion markers only with includeDeleted
  console.log(contact.id, contact.displayName);
}

const { count } = await bodo.contacts.count();
console.log("contacts:", count);

await bodo.contacts.delete(updated.id);

try {
  await bodo.contacts.get(updated.id);
} catch (err) {
  if (err instanceof BodoApiError && err.code === "NOT_FOUND") {
    console.log("gone:", err.requestId);
  } else {
    throw err;
  }
}
```

Python · SDK:

```python
# The contact operations with the SDK: create, read, list, update, delete.
# Run: BODO_API_KEY=bodo_uk_test_… python examples/reference_contacts.py
import os
import time

from bodo_api import Bodo, BodoApiError

with Bodo(api_key=os.environ["BODO_API_KEY"], preview=True, locale="en") as bodo:
    created = bodo.contacts.create(
        first_name="Max",
        last_name="Mustermann",
        email="max@musterfirma.de",
        idempotency_key=f"quickstart-{int(time.time())}",  # optional: dedupes across processes
    )
    read = bodo.contacts.get(created.id)

    # Optimistic update: If-Match with the revision you read.
    updated = bodo.contacts.update(read.id, job_title="Einkauf", if_match=f'"r{int(read.revision)}"')
    print(updated.job_title)

    # The iterator follows next_cursor by itself.
    for contact in bodo.contacts.list(updated_since="2026-11-01T00:00:00Z", limit=50):
        print(contact.id)

    print("contacts:", bodo.contacts.count())

    bodo.contacts.delete(updated.id)
    try:
        bodo.contacts.get(updated.id)
    except BodoApiError as err:
        if err.code != "NOT_FOUND":
            raise
        print("gone:", err.request_id)
```

## Alle Operationen

Preview-Operationen brauchen `Bodo-Preview: true`, sonst antwortet die API mit `404 OPERATION_NOT_IN_VERSION`. Preview ist keine Produktionsgrundlage.

| Methode | Pfad | Operation | Kanal | Scope | Kosten |
| --- | --- | --- | --- | --- | --- |
| GET | /v1/me | Wer bin ich? | Stable | — | 1 Punkt |
| GET | /v1/rate_limit | Stand der Limits | Stable | — | 1 Punkt |
| GET | /v1/openapi.json | Die OpenAPI-Spec | Stable | — | 1 Punkt |
| GET | /v1/contacts | Kontakte auflisten | Stable | contacts:read | 2 Punkte |
| POST | /v1/contacts | Kontakt anlegen | Preview | contacts:write | 5 Punkte |
| GET | /v1/contacts/count | Kontakte zählen | Stable | contacts:read | 2 Punkte |
| GET | /v1/contacts/\{id\} | Kontakt lesen | Stable | contacts:read | 1 Punkt |
| PATCH | /v1/contacts/\{id\} | Kontakt ändern | Preview | contacts:write | 5 Punkte |
| DELETE | /v1/contacts/\{id\} | Kontakt löschen | Preview | contacts:write | 10 Punkte |
| GET | /v1/companies | Firmen auflisten | Stable | companies:read | 2 Punkte |
| POST | /v1/companies | Firma anlegen | Preview | companies:write | 5 Punkte |
| GET | /v1/companies/count | Firmen zählen | Stable | companies:read | 2 Punkte |
| GET | /v1/companies/\{id\} | Firma lesen | Stable | companies:read | 1 Punkt |
| PATCH | /v1/companies/\{id\} | Firma ändern | Preview | companies:write | 5 Punkte |
| DELETE | /v1/companies/\{id\} | Firma löschen | Preview | companies:write | 10 Punkte |
| GET | /v1/tasks | Aufgaben auflisten | Stable | tasks:read | 2 Punkte |
| POST | /v1/tasks | Aufgabe anlegen | Preview | tasks:write | 5 Punkte |
| GET | /v1/tasks/count | Aufgaben zählen | Stable | tasks:read | 2 Punkte |
| GET | /v1/tasks/\{id\} | Aufgabe lesen | Stable | tasks:read | 1 Punkt |
| PATCH | /v1/tasks/\{id\} | Aufgabe ändern | Preview | tasks:write | 5 Punkte |
| DELETE | /v1/tasks/\{id\} | Aufgabe löschen | Preview | tasks:write | 10 Punkte |
| POST | /v1/tasks/\{id\}/complete | Aufgabe erledigen | Preview | tasks:write | 5 Punkte |
| GET | /v1/documents | Dokumente auflisten | Stable | documents:read | 2 Punkte |
| POST | /v1/documents | Dokument aus einem Upload anlegen | Preview | documents:write | 10 Punkte |
| GET | /v1/documents/count | Dokumente zählen | Stable | documents:read | 2 Punkte |
| GET | /v1/documents/\{id\} | Dokument lesen | Stable | documents:read | 1 Punkt |
| PATCH | /v1/documents/\{id\} | Dokument ändern | Preview | documents:write | 5 Punkte |
| DELETE | /v1/documents/\{id\} | Dokument löschen | Preview | documents:write | 10 Punkte |
| GET | /v1/documents/\{id\}/content | Datei herunterladen | Stable | documents:read | 1 Punkt |
| POST | /v1/uploads | Upload-Sitzung anlegen | Preview | documents:write | 5 Punkte |
| POST | /v1/batch | Mehrere Aufrufe bündeln | Preview | — | 0 Punkte |
| GET | /v1/operations/\{id\} | Operation abfragen | Stable | — | 1 Punkt |
| GET | /v1/webhook_endpoints | Webhook-Endpunkte auflisten | Stable | webhook_endpoints:read | 2 Punkte |
| POST | /v1/webhook_endpoints | Webhook-Endpunkt anlegen | Preview | webhook_endpoints:write | 5 Punkte |
| GET | /v1/webhook_endpoints/\{id\} | Webhook-Endpunkt lesen | Stable | webhook_endpoints:read | 1 Punkt |
| PATCH | /v1/webhook_endpoints/\{id\} | Webhook-Endpunkt ändern | Preview | webhook_endpoints:write | 5 Punkte |
| DELETE | /v1/webhook_endpoints/\{id\} | Webhook-Endpunkt löschen | Preview | webhook_endpoints:write | 10 Punkte |
| POST | /v1/webhook_endpoints/\{id\}/test | Test-Ereignis senden | Preview | webhook_endpoints:write | 5 Punkte |
| POST | /v1/webhook_endpoints/\{id\}/rotate_secret | Signier-Secret drehen | Preview | webhook_endpoints:write | 5 Punkte |
| GET | /v1/webhook_endpoints/\{id\}/deliveries | Zustell-Log lesen | Stable | webhook_endpoints:read | 2 Punkte |
| GET | /v1/events | Ereignisse auflisten | Stable | — | 1 Punkt |
| GET | /v1/events/\{id\} | Ereignis lesen | Stable | — | 1 Punkt |

## Spec und Try-it

- [openapi.2026-11-01.json herunterladen](/openapi/openapi.2026-11-01.json), zeichengleich mit dem Artefakt im Repo
- Mit Schlüssel: `GET /v1/openapi.json`
- [Try it](/reference/try-it/) mit deinem Sandbox-Schlüssel
