Schnellstart
In fünf Minuten von null zur ersten Rechnung im Entwurf. Legen Sie vorher einen Schlüssel mit den Berechtigungen customers:read, customers:write und invoices:write an und setzen Sie ihn als Umgebungsvariable:
export KOSTENKLAR_API_KEY="kk_live_..."
1. Verbindung testen
curl
curl https://api.kosten-klar.de/v1/me \
-H "Authorization: Bearer $KOSTENKLAR_API_KEY"
Node.js
const BASE = 'https://api.kosten-klar.de';
const headers = { Authorization: `Bearer ${process.env.KOSTENKLAR_API_KEY}` };
const res = await fetch(`${BASE}/v1/me`, { headers });
console.log(res.status, await res.json());
PHP
<?php
$base = 'https://api.kosten-klar.de';
$ch = curl_init("$base/v1/me");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('KOSTENKLAR_API_KEY')],
]);
$body = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), ' ', $body;
Python
import os, requests
BASE = 'https://api.kosten-klar.de'
headers = {'Authorization': f"Bearer {os.environ['KOSTENKLAR_API_KEY']}"}
res = requests.get(f'{BASE}/v1/me', headers=headers)
print(res.status_code, res.json())
Antwort:
{
"keyId": "0c1c8a3e-5b0e-4d52-9a57-6b2f3f6a9d10",
"name": "Shop-Anbindung",
"prefix": "kk_live_AbCd1234",
"scopes": ["customers:read", "customers:write", "invoices:write"],
"scopeLabels": {
"customers:read": "Kunden lesen",
"customers:write": "Kunden anlegen und ändern",
"invoices:write": "Rechnungsentwürfe anlegen und ändern"
},
"expiresAt": null
}
Bekommen Sie 401 oder 403, schauen Sie in die Fehlertabelle.
2. Kunden anlegen
Pflicht sind ein Name (company oder firstName plus lastName), street, postalCode (genau fünf Ziffern), city und email. Jeder POST braucht einen Idempotency-Key, siehe Idempotenz.
curl
curl -X POST https://api.kosten-klar.de/v1/customers \
-H "Authorization: Bearer $KOSTENKLAR_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"customerType": "business",
"company": "Beispiel GmbH",
"email": "buchhaltung@beispiel.de",
"street": "Musterstraße 1",
"postalCode": "10115",
"city": "Berlin"
}'
Node.js
import { randomUUID } from 'node:crypto';
const res = await fetch(`${BASE}/v1/customers`, {
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json',
'Idempotency-Key': randomUUID(),
},
body: JSON.stringify({
customerType: 'business',
company: 'Beispiel GmbH',
email: 'buchhaltung@beispiel.de',
street: 'Musterstraße 1',
postalCode: '10115',
city: 'Berlin',
}),
});
const customer = await res.json();
console.log(res.status, customer.id);
PHP
<?php
$payload = json_encode([
'customerType' => 'business',
'company' => 'Beispiel GmbH',
'email' => 'buchhaltung@beispiel.de',
'street' => 'Musterstraße 1',
'postalCode' => '10115',
'city' => 'Berlin',
]);
$ch = curl_init("$base/v1/customers");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KOSTENKLAR_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$customer = json_decode(curl_exec($ch), true);
echo $customer['id'];
Python
import uuid
res = requests.post(
f'{BASE}/v1/customers',
headers={**headers, 'Idempotency-Key': str(uuid.uuid4())},
json={
'customerType': 'business',
'company': 'Beispiel GmbH',
'email': 'buchhaltung@beispiel.de',
'street': 'Musterstraße 1',
'postalCode': '10115',
'city': 'Berlin',
},
)
customer = res.json()
print(res.status_code, customer['id'])
Die Antwort hat Status 201 und enthält den Kunden mit seiner id (gekürzt):
{
"id": "5d1f3a52-8f0c-4c0e-9d0a-2f8d6a7b9c11",
"customerNumber": "K-0042",
"type": "business",
"company": "Beispiel GmbH",
"email": "buchhaltung@beispiel.de",
"address": { "street": "Musterstraße 1", "postalCode": "10115", "city": "Berlin", "country": null },
"createdAt": "2026-10-06T10:15:00.000Z",
"updatedAt": "2026-10-06T10:15:00.000Z"
}
3. Rechnungsentwurf anlegen
curl
curl -X POST https://api.kosten-klar.de/v1/invoices \
-H "Authorization: Bearer $KOSTENKLAR_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"customerId": "5d1f3a52-8f0c-4c0e-9d0a-2f8d6a7b9c11",
"issueDate": "2026-10-06",
"dueDate": "2026-10-20",
"taxRate": 19,
"items": [
{ "description": "Beratung Oktober", "quantity": 8, "unit": "Std.", "unitPrice": 95 }
]
}'
Node.js
const res = await fetch(`${BASE}/v1/invoices`, {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json', 'Idempotency-Key': randomUUID() },
body: JSON.stringify({
customerId: customer.id,
issueDate: '2026-10-06',
dueDate: '2026-10-20',
taxRate: 19,
items: [{ description: 'Beratung Oktober', quantity: 8, unit: 'Std.', unitPrice: 95 }],
}),
});
const invoice = await res.json();
console.log(invoice.status, invoice.total); // draft 904.4
PHP
<?php
$payload = json_encode([
'customerId' => $customer['id'],
'issueDate' => '2026-10-06',
'dueDate' => '2026-10-20',
'taxRate' => 19,
'items' => [['description' => 'Beratung Oktober', 'quantity' => 8, 'unit' => 'Std.', 'unitPrice' => 95]],
]);
$ch = curl_init("$base/v1/invoices");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KOSTENKLAR_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$invoice = json_decode(curl_exec($ch), true);
echo $invoice['status'], ' ', $invoice['total'];
Python
res = requests.post(
f'{BASE}/v1/invoices',
headers={**headers, 'Idempotency-Key': str(uuid.uuid4())},
json={
'customerId': customer['id'],
'issueDate': '2026-10-06',
'dueDate': '2026-10-20',
'taxRate': 19,
'items': [{'description': 'Beratung Oktober', 'quantity': 8, 'unit': 'Std.', 'unitPrice': 95}],
},
)
invoice = res.json()
print(invoice['status'], invoice['total'])
Die Rechnung liegt jetzt in KostenKlar als Entwurf ohne Rechnungsnummer. Prüfen und versenden Sie sie dort. Die Summen berechnet KostenKlar selbst: 8 Stunden zu 95 Euro netto ergeben 760 Euro netto, 144,40 Euro Umsatzsteuer und 904,40 Euro brutto.
Webhooks: Ereignisse empfangen
Statt regelmäßig nachzufragen, lassen Sie sich benachrichtigen. KostenKlar sendet bei einem Ereignis einen POST mit JSON an Ihre Adresse.
Einrichten
- Öffnen Sie in KostenKlar Einstellungen, Entwickler & API und legen Sie unter Webhooks einen Endpunkt an: Ihre
https-Adresse und die gewünschten Ereignisse.
- Kopieren Sie das Signatur-Secret (
whsec_...). Es wird nur einmal angezeigt. Speichern Sie es wie einen API-Schlüssel.
- Mit Test senden schickt KostenKlar sofort ein
ping-Ereignis und zeigt Ihnen die Antwort Ihres Servers.
Der Endpunkt muss öffentlich per https erreichbar sein. Adressen im lokalen Netz oder auf den eigenen Rechner (localhost, 192.168.x.x) werden aus Sicherheitsgründen abgelehnt. Zum Entwickeln nutzen Sie einen Tunnel-Dienst, der eine öffentliche https-Adresse bereitstellt. Weiterleitungen (3xx) werden nicht verfolgt.
Ereignisse
| Ereignis | Wann | data |
invoice.created | Eine Rechnung wurde angelegt, auch als Entwurf | Invoice |
invoice.sent | Eine Rechnung wurde versendet | Invoice |
invoice.paid | Eine Rechnung wurde vollständig bezahlt | Invoice |
invoice.overdue | Eine Rechnung ist überfällig geworden | Invoice |
quote.created | Ein Angebot wurde angelegt, auch als Entwurf oder neue Fassung | Quote |
quote.accepted | Ein Angebot wurde angenommen | Quote |
credit-note.created | Eine Gutschrift wurde angelegt, auch als Entwurf | CreditNote |
payment.received | Ein Zahlungseingang wurde erfasst: per Hand, aus dem Bankabgleich oder über die API | Payment |
expense.created | Eine Ausgabe oder Einnahme ohne Rechnung wurde angelegt | Expense |
time-entry.created | Eine Zeitbuchung wurde angelegt, auch per Stoppuhr | TimeEntry |
customer.created | Ein Kunde wurde angelegt | Customer |
customer.updated | Ein Kunde wurde geändert | Customer |
project.created | Ein Projekt wurde angelegt | Project |
project.updated | Ein Projekt wurde geändert, auch beim Statuswechsel und wenn Meilensteine angelegt, geändert, erledigt, abgerechnet oder gelöscht werden | Project |
project.deleted | Ein Projekt wurde gelöscht. data enthält nur id, customerId, name und status vor dem Löschen | DeletedProject |
task.created | Eine Aufgabe wurde angelegt | Task |
task.completed | Eine Aufgabe wurde erledigt | Task |
workflow.triggered | Eine eigene Workflow-Regel mit der Aktion „Webhook auslösen“ hat gegriffen (Einstellungen > Automatisierung) | WorkflowTrigger |
ping | Test aus den Einstellungen | { "message": "..." } |
Webhooks entstehen auch bei Änderungen, die Sie selbst über die API auslösen, zum Beispiel bei customer.created nach einem POST /v1/customers. Das müssen Sie in Ihrer Anwendung berücksichtigen, damit keine Schleife entsteht.
Aufbau einer Zustellung
POST /webhooks/kostenklar HTTP/1.1
Content-Type: application/json
User-Agent: KostenKlar-Webhooks/1
KostenKlar-Event: invoice.paid
KostenKlar-Delivery: 9b6a2c0e-6d62-4a4b-8c53-5a0f2c3d1e77
KostenKlar-Signature: t=1790000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
{
"id": "9b6a2c0e-6d62-4a4b-8c53-5a0f2c3d1e77",
"type": "invoice.paid",
"createdAt": "2026-10-06T10:15:00.000Z",
"data": { "id": "...", "number": "RE-2026-0042", "status": "paid", "total": 904.4, "...": "..." }
}
data hat dieselbe Form wie die Antwort der jeweiligen Abruf-Endpunkte. id ist je Zustellung eindeutig und bei Wiederholungen identisch. Merken Sie sich die id, um doppelte Zustellungen zu erkennen.
Referenz: Endpunkte
Diese Referenz wird aus openapi.json erzeugt und stimmt daher mit der API überein. Alle Pfade beziehen sich auf https://api.kosten-klar.de.
Konto
GET/v1/me
Verbindungstest
Zeigt, mit welchem Schlüssel Sie sprechen und welche Berechtigungen er hat. Braucht keine bestimmte Berechtigung und eignet sich als erster Aufruf.
Keine bestimmte Berechtigung nötig
Antworten
| Status | Inhalt | Bedeutung |
200 | Me | Der Schlüssel ist gültig. |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Kunden
GET/v1/customers
Kunden auflisten
Seitenweise, aufsteigend nach id. Für eine Synchronisation den Filter updatedSince nutzen.
Berechtigung: customers:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/customers
Kunden anlegen
Pflicht sind ein Name (company oder firstName plus lastName), street, postalCode (genau 5 Ziffern), city und email. Bei type: business ist company Pflicht. Ohne customerNumber vergibt KostenKlar die nächste freie Nummer.
Berechtigung: customers:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema CustomerInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Customer | Der Kunde wurde angelegt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/customers/{id}
Einen Kunden abrufen
Berechtigung: customers:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Customer | Der Kunde. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/customers/{id}
Kunden ändern
Geändert werden nur die gesendeten Felder. Dasselbe Schema wie beim Anlegen, aber alle Felder sind optional. Die Pflichtfelder müssen nach der Änderung weiterhin gefüllt sein.
Berechtigung: customers:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema CustomerInput
Antworten
| Status | Inhalt | Bedeutung |
200 | Customer | Der geänderte Kunde. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Rechnungen
GET/v1/invoices
Rechnungen auflisten
Seitenweise, aufsteigend nach id, mit Positionen.
Berechtigung: invoices:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | draft | sent | paid | overdue | cancelled | archived | cancellation | payment_plan | partially_paid | dunning_level_1 | dunning_level_2 | dunning_level_3 | Nur Rechnungen mit diesem Status. |
customerId | Query | string (uuid) | Nur Rechnungen dieses Kunden. |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/invoices
Rechnungsentwurf anlegen
Legt ausschließlich einen Entwurf an (status: draft). Rechnungsnummer, Versand und Festschreiben bleiben in KostenKlar, damit die lückenlose Nummernfolge erhalten bleibt. Summen berechnet KostenKlar selbst.
Berechtigung: invoices:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema InvoiceInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Invoice | Der Entwurf wurde angelegt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/invoices/{id}
Eine Rechnung abrufen
Berechtigung: invoices:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Invoice | Die Rechnung mit Positionen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/invoices/{id}
Rechnungsentwurf ändern
Ändert nur die gesendeten Felder; items ersetzt alle Positionen. Nur Entwürfe: ausgestellte Rechnungen antworten mit 403 INVOICE_CANNOT_EDIT_NON_DRAFT. Summen berechnet KostenKlar neu.
Berechtigung: invoices:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema InvoiceUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | Invoice | Der geänderte Entwurf. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/invoices/{id}/pdf
Rechnung als PDF herunterladen
Festgeschriebene Rechnungen liefern das unveränderliche PDF, Entwürfe werden beim Abruf frisch erzeugt. Dateiname Rechnung_<Nummer>.pdf.
Berechtigung: invoices:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | PDF | Das PDF (Content-Disposition: attachment). |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Angebote
GET/v1/quotes
Angebote auflisten
Seitenweise, aufsteigend nach id, mit Positionen.
Berechtigung: quotes:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | draft | sent | accepted | rejected | archived | Nur Angebote mit diesem Status. |
customerId | Query | string (uuid) | Nur Angebote dieses Kunden. |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/quotes
Angebot anlegen
Legt ein Angebot mit Angebotsnummer an, standardmäßig als Entwurf. Mit markSent: true wird es sofort als versendet markiert (status: sent, Versanddatum gesetzt), ohne E-Mail an den Kunden; das PDF liefert GET /v1/quotes/{id}/pdf. Summen berechnet KostenKlar. Bei priceMode: gross werden die Einzelpreise mit taxRate in Nettopreise umgerechnet (4 Nachkommastellen), Angebote speichern immer netto. Unbekannte Kunden antworten mit 422 und details.field: customerId.
Berechtigung: quotes:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema QuoteInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Quote | Das Angebot wurde angelegt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/quotes/{id}
Ein Angebot abrufen
Berechtigung: quotes:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Quote | Das Angebot mit Positionen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/quotes/{id}
Angebotsentwurf ändern
Ändert nur die gesendeten Felder; items ersetzt alle Positionen. Nur Entwürfe: versendete Angebote antworten mit 403 QUOTE_CANNOT_EDIT_NON_DRAFT.
Berechtigung: quotes:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema QuoteUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | Quote | Der geänderte Entwurf. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/quotes/{id}/accept
Angebot annehmen
Nur aus status: sent. Ist das Angebot bereits angenommen, kommt es unverändert zurück (200). Andere Status antworten mit 409 QUOTE_INVALID_STATUS_TRANSITION, ein abgelaufenes Angebot (validUntil überschritten) mit 403 QUOTE_EXPIRED. Die Annahme läuft wie in der App: Webhook quote.accepted, Workflows und, falls eingestellt, die automatische Rechnung.
Berechtigung: quotes:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Antworten
| Status | Inhalt | Bedeutung |
200 | Quote | Das angenommene Angebot. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
409 | Error | Der Status erlaubt die Aktion nicht (QUOTE_INVALID_STATUS_TRANSITION, details.status nennt den aktuellen), oder die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/quotes/{id}/reject
Angebot ablehnen
Nur aus status: sent. Ist das Angebot bereits abgelehnt, kommt es unverändert zurück (200). Andere Status antworten mit 409 QUOTE_INVALID_STATUS_TRANSITION.
Berechtigung: quotes:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Antworten
| Status | Inhalt | Bedeutung |
200 | Quote | Das abgelehnte Angebot. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
409 | Error | Der Status erlaubt die Aktion nicht (QUOTE_INVALID_STATUS_TRANSITION, details.status nennt den aktuellen), oder die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/quotes/{id}/pdf
Angebot als PDF herunterladen
Das PDF wird beim Abruf mit dem aktuellen Stand und Layout erzeugt, wie in der App. Dateiname Angebot_<Nummer>.pdf.
Berechtigung: quotes:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | PDF | Das PDF (Content-Disposition: attachment). |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Gutschriften
GET/v1/credit-notes
Gutschriften auflisten
Seitenweise, aufsteigend nach id, mit Positionen. Alle Status einschließlich Entwürfen.
Berechtigung: credit-notes:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | draft | issued | applied | refunded | cancelled | Nur Gutschriften mit diesem Status. |
customerId | Query | string (uuid) | Nur Gutschriften dieses Kunden. |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/credit-notes
Gutschriftentwurf zu einer Rechnung anlegen
Rechnungskorrektur zu einer ausgestellten, nicht stornierten Rechnung, immer als Entwurf. Kunde und Anschrift kommen von der Rechnung, die Nummer vergibt KostenKlar. Ausstellen, Verrechnen und Erstatten bleiben in KostenKlar. Webhook credit-note.created.
Berechtigung: credit-notes:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema CreditNoteInput
Antworten
| Status | Inhalt | Bedeutung |
201 | CreditNote | Der Gutschriftentwurf. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/credit-notes/{id}
Eine Gutschrift abrufen
Berechtigung: credit-notes:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | CreditNote | Die Gutschrift mit Positionen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/credit-notes/{id}/pdf
Gutschrift als PDF herunterladen
Das PDF wird beim Abruf erzeugt, wie in der App. Dateiname Gutschrift_<Nummer>.pdf.
Berechtigung: credit-notes:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | PDF | Das PDF (Content-Disposition: attachment). |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Lieferscheine
GET/v1/delivery-notes
Lieferscheine auflisten
Seitenweise, mit Positionen. Modul Lieferscheine, sonst 403 FEATURE_DISABLED.
Berechtigung: delivery-notes:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | draft | issued | cancelled | |
customerId | Query | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/delivery-notes/{id}
Einen Lieferschein abrufen
Berechtigung: delivery-notes:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | DeliveryNote | Der Lieferschein mit Positionen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/delivery-notes/{id}/pdf
Lieferschein als PDF herunterladen
Dateiname Lieferschein_<Nummer>.pdf.
Berechtigung: delivery-notes:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | PDF | Das PDF (Content-Disposition: attachment). |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Mahnungen
GET/v1/dunnings
Mahnungen auflisten
Seitenweise. Mahnläufe und Versand bleiben in KostenKlar. Modul Mahnwesen, sonst 403 FEATURE_DISABLED.
Berechtigung: dunnings:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | pending | sent | paid | cancelled | escalated | |
level | Query | first | second | final | collections | |
invoiceId | Query | string (uuid) | |
customerId | Query | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/dunnings/{id}
Eine Mahnung abrufen
Berechtigung: dunnings:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Dunning | Die Mahnung. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/dunnings/{id}/pdf
Mahnung als PDF herunterladen
Dateiname Mahnung_<Rechnungsnummer>_<Stufe>.pdf.
Berechtigung: dunnings:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | PDF | Das PDF (Content-Disposition: attachment). |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Verträge
GET/v1/contracts
Verträge auflisten
Seitenweise, aufsteigend nach id, mit Positionen. Alle Status einschließlich Entwürfen; filtern Sie bei Bedarf selbst oder mit status.
Berechtigung: contracts:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | draft | sent | signed | active | expired | cancelled | Nur Verträge mit diesem Status. |
customerId | Query | string (uuid) | Nur Verträge dieses Kunden. |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/contracts/{id}
Einen Vertrag abrufen
Berechtigung: contracts:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Contract | Der Vertrag mit Positionen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/contracts/{id}/usage
Zeitverbrauch eines Vertrags
Inklusivzeit und gebuchte Zeit im aktuellen Abrechnungszeitraum, z. B. für Wartungsverträge. Der Zeitraum endet mit der nächsten Rechnung (nextInvoiceDate); bei einmaligen Verträgen oder ohne nächstes Rechnungsdatum ist es die gesamte Laufzeit. Gezählt werden alle Zeitbuchungen für den Kunden des Vertrags im Zeitraum, bei mehreren gleichzeitig laufenden Verträgen desselben Kunden also auch Zeit für die anderen. Enthält bewusst keine Beträge oder Stundensätze.
Berechtigung: contracts:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | ContractUsage | Der Zeitverbrauch. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/contracts/{id}/pdf
Vertrag als PDF herunterladen
Das PDF mit Vertragstext und, falls vorhanden, digitaler Unterschrift wird beim Abruf erzeugt. Dateiname Vertrag_<Nummer>.pdf.
Berechtigung: contracts:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | PDF | Das PDF (Content-Disposition: attachment). |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Zahlungen
POST/v1/invoices/{id}/payments
Zahlungseingang zu einer Rechnung erfassen
Wie „Zahlung erfassen“ in KostenKlar: Teil- oder Vollzahlung bis zum offenen Betrag. Bei Vollzahlung wird die Rechnung bezahlt (Webhook invoice.paid). Die Zahlung landet in der EÜR (Webhook payment.received). Nicht möglich bei Entwürfen, stornierten oder bereits bezahlten Rechnungen (403) und in festgeschriebenen Monaten.
Berechtigung: payments:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema PaymentInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Invoice | Die Rechnung mit neuem Zahlstand. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/payments
Zahlungen auflisten
Zahlungen der Einnahmen-Überschuss-Rechnung mit Zuordnung zu Rechnungen und Gutschriften, seitenweise. Modul EÜR, sonst 403 FEATURE_DISABLED.
Berechtigung: payments:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
direction | Query | in | out | |
from | Query | string (date) | Erster Tag (JJJJ-MM-TT, einschließlich). |
to | Query | string (date) | Letzter Tag (JJJJ-MM-TT, einschließlich). |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/payments/{id}
Eine Zahlung abrufen
Berechtigung: payments:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Payment | Die Zahlung mit Zuordnungen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Ausgaben
GET/v1/expenses
Ausgaben auflisten
Ausgaben und Einnahmen ohne Rechnung, seitenweise, ohne Belegdatei. Modul Ausgaben, sonst 403 FEATURE_DISABLED.
Berechtigung: expenses:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
type | Query | expense | income | |
category | Query | office | travel | equipment | software | marketing | training | utilities | rent | insurance | taxes | salary | meals | entertainment | other | |
from | Query | string (date) | Erster Tag (JJJJ-MM-TT, einschließlich). |
to | Query | string (date) | Letzter Tag (JJJJ-MM-TT, einschließlich). |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/expenses
Ausgabe anlegen
Mit denselben Prüfungen wie in KostenKlar (§ 13b nur mit Steuersatz, Privat ohne Steuer, festgeschriebene Monate, Kassenabschluss bei Barzahlung). Aufteilung auf mehrere Steuersätze und Anlagegüter bleiben in KostenKlar. Webhook expense.created.
Berechtigung: expenses:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema ExpenseInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Expense | Die angelegte Ausgabe. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/expenses/{id}
Eine Ausgabe abrufen
Berechtigung: expenses:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Expense | Die Ausgabe. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/expenses/{id}
Ausgabe ändern
Ändert nur die gesendeten Felder, mit denselben Prüfungen wie beim Anlegen.
Berechtigung: expenses:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema ExpenseUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | Expense | Die geänderte Ausgabe. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/expenses/{id}/receipt
Beleg hochladen
Beleg als PDF, PNG, JPG oder E-Rechnung (XML) im Feld file (multipart/form-data), höchstens 10 MB. Ein vorhandener Beleg wird als Version archiviert (GoBD).
Berechtigung: expenses:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Expense | Die Ausgabe mit Beleg. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Produkte
GET/v1/products
Produkte und Leistungen auflisten
Seitenweise, nur nicht archivierte Einträge.
Berechtigung: products:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/products
Produkt anlegen
Wie im Produktkatalog: code ist je Konto eindeutig. Ohne type ist es eine Leistung (service, 60 Minuten je Einheit). Mit trackStock wird stockQuantity als Anfangsbestand gebucht. Schreiben verlangt das Modul Produktkatalog (403 FEATURE_DISABLED).
Berechtigung: products:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema ProductInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Product | Das angelegte Produkt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/products/{id}
Ein Produkt abrufen
Berechtigung: products:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Product | Das Produkt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/products/{id}
Produkt ändern
Ändert nur die gesendeten Felder. Den Bestand ändern Sie über POST /v1/products/{id}/stock-movements.
Berechtigung: products:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema ProductUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | Product | Das geänderte Produkt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/products/{id}/stock-movements
Lagerbewegung buchen
Zugang (in), Abgang (out) oder Inventur (correction: quantity ist der gezählte Bestand, gebucht wird die Differenz). Nur bei Produkten mit trackStock.
Berechtigung: products:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema StockMovementInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Product | Das Produkt mit neuem Bestand. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Projekte
GET/v1/projects
Projekte auflisten
Seitenweise, aufsteigend nach id. Projekte gehören zum Modul Zeiterfassung; ist es im Konto aus, antworten alle Projekt-Endpunkte mit 403 FEATURE_DISABLED.
Berechtigung: projects:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | active | completed | archived | Nur Projekte mit diesem Status. |
customerId | Query | string (uuid) | Nur Projekte dieses Kunden. |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/projects
Projekt anlegen
Neue Projekte starten mit status: active. Der Kunde muss bereits existieren.
Berechtigung: projects:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema ProjectInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Project | Das Projekt wurde angelegt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/projects/{id}
Ein Projekt abrufen
Berechtigung: projects:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Project | Das Projekt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/projects/{id}
Projekt ändern
Geändert werden nur die gesendeten Felder. Abschließen mit status: completed, statt Löschen status: archived. null entfernt Datum oder Budget.
Berechtigung: projects:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema ProjectUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | Project | Das geänderte Projekt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/projects/{id}/milestones
Meilensteine eines Projekts
Meilensteine bzw. Abschläge in ihrer Reihenfolge, mit Betrag und Abrechnungsstand.
Berechtigung: projects:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Die Meilensteine. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/projects/{id}/summary
Fortschritt eines Projekts
Budget, erfasste Zeiten, abgerechneter Betrag, Meilensteine und Aufgaben auf einen Blick. Enthält bewusst keine Kosten, Margen oder Stundensätze.
Berechtigung: projects:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | ProjectSummary | Der Projektfortschritt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/projects/{id}/acceptances
Abnahmeprotokolle eines Projekts
Alle Abnahmeprotokolle, aufsteigend nach protocolDate. Ohne Unterschriftsbilder; das unterschriebene Dokument liefert der PDF-Endpunkt.
Berechtigung: projects:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Die Abnahmeprotokolle. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/projects/{id}/acceptances/{acceptanceId}/pdf
Abnahmeprotokoll als PDF herunterladen
Protokoll mit Mängelliste und Unterschriften. Dateiname Abnahme_<protocolDate>.pdf.
Berechtigung: projects:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
acceptanceId Pflicht | Pfad | string (uuid) | ID des Abnahmeprotokolls aus GET /v1/projects/{id}/acceptances. |
Antworten
| Status | Inhalt | Bedeutung |
200 | PDF | Das PDF (Content-Disposition: attachment). |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Aufgaben
GET/v1/tasks
Aufgaben auflisten
Seitenweise, aufsteigend nach id, mit Teilschritten. Ohne status kommen offene und erledigte Aufgaben.
Berechtigung: tasks:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
status | Query | open | done | all | open, done oder all (Standard). |
customerId | Query | string (uuid) | Nur Aufgaben dieses Kunden. |
projectId | Query | string (uuid) | Nur Aufgaben dieses Projekts. |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/tasks
Aufgabe anlegen
Optional einem Kunden, Projekt und einer Person zugeordnet. Unbekannte Verweise antworten mit 422 und details.field.
Berechtigung: tasks:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema TaskInput
Antworten
| Status | Inhalt | Bedeutung |
201 | Task | Die Aufgabe wurde angelegt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/tasks/{id}
Eine Aufgabe abrufen
Berechtigung: tasks:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | Task | Die Aufgabe mit Teilschritten. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/tasks/{id}
Aufgabe ändern
Geändert werden nur die gesendeten Felder. status: done erledigt die Aufgabe; bei einer Wiederholung legt KostenKlar die nächste an. null löst Zuordnungen bzw. entfernt Datum und Aufwand.
Berechtigung: tasks:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema TaskUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | Task | Die geänderte Aufgabe. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/tasks/{id}/checklist
Teilschritt hinzufügen
Hängt einen Teilschritt am Ende an.
Berechtigung: tasks:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema ChecklistItemInput
Antworten
| Status | Inhalt | Bedeutung |
201 | ChecklistItem | Der Teilschritt wurde angelegt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/tasks/{id}/checklist/{itemId}
Teilschritt ändern
Titel ändern oder mit done abhaken.
Berechtigung: tasks:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
itemId Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema ChecklistItemUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | ChecklistItem | Der geänderte Teilschritt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Zeiterfassung
GET/v1/time-entries
Zeitbuchungen auflisten
Seitenweise, aufsteigend nach id. Gelöschte Buchungen fehlen. Ohne Stundensätze, Kosten und Mitarbeiter. Zeitbuchungen gehören zum Modul Zeiterfassung; ist es im Konto aus, antworten die Endpunkte mit 403 FEATURE_DISABLED.
Berechtigung: time-entries:read
Parameter
| Name | Ort | Typ | Beschreibung |
limit | Query | integer | Datensätze pro Seite (1 bis 100, Standard 50). |
cursor | Query | string | Der Wert nextCursor der vorigen Antwort. |
updatedSince | Query | string (date-time) | Nur Datensätze, die seit diesem Zeitpunkt geändert wurden (ISO 8601). |
projectId | Query | string (uuid) | Nur Buchungen dieses Projekts. |
customerId | Query | string (uuid) | Nur Buchungen dieses Kunden. |
from | Query | string (date) | Erster Tag (einschließlich), bezogen auf den Beginn der Buchung in Europe/Berlin. |
to | Query | string (date) | Letzter Tag (einschließlich). |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Eine Seite mit Datensätzen. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/time-entries
Zeitbuchung anlegen
Bucht für den Kontoinhaber (sein Mitarbeiterprofil) mit denselben Prüfungen wie die App: Beginn nicht in der Zukunft, keine Überschneidung, Woche nicht eingereicht, höchstens 16 Stunden. Stundensatz und Kosten kommen aus dem Mitarbeiterprofil. Ohne Mitarbeiterprofil: 422. Webhook time-entry.created.
Berechtigung: time-entries:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema TimeEntryInput
Antworten
| Status | Inhalt | Bedeutung |
201 | TimeEntry | Die angelegte Buchung. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/time-entries/{id}
Eine Zeitbuchung abrufen
Berechtigung: time-entries:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | TimeEntry | Die Zeitbuchung. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/time-entries/{id}
Zeitbuchung ändern
Nur offene Buchungen (editable: true). Ändert nur die gesendeten Felder; das Ende rechnet KostenKlar aus Beginn, Dauer und Pause neu.
Berechtigung: time-entries:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema TimeEntryUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | TimeEntry | Die geänderte Buchung. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
Kalender
GET/v1/calendar/busy
Belegte Zeiten
Alle eigenen Termine des Kontos, die den Zeitraum berühren, ohne abgesagte (cancelled). Serien sind in einzelne Termine ausgeklappt. Fristen aus Rechnungen, Aufgaben usw. zählen nicht. Bewusst ohne Titel und Inhalte. Ganztägige Termine reichen von 00:00 Uhr des ersten bis 00:00 Uhr nach dem letzten Tag in Europe/Berlin. Sortiert nach Beginn. Der Zeitraum darf höchstens 62 Tage umfassen. Kalender ist ein Modul; ist es im Konto aus, antworten alle Kalender-Endpunkte mit 403 FEATURE_DISABLED.
Berechtigung: calendar:read
Parameter
| Name | Ort | Typ | Beschreibung |
from Pflicht | Query | string (date-time) | Beginn des Zeitraums (ISO 8601 mit Uhrzeit). |
to Pflicht | Query | string (date-time) | Ende des Zeitraums (ausschließlich), nach from, höchstens 62 Tage später. |
Antworten
| Status | Inhalt | Bedeutung |
200 | object | Die belegten Zeiten. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
POST/v1/calendar/events
Termin anlegen
Legt einen Termin mit Uhrzeit an (keine Serie, nicht ganztägig), standardmäßig als tentative. Das Ende muss nach dem Beginn liegen, höchstens 12 Stunden. Es gelten die Grenzen des Tarifs (Free-Plan: Zahl künftiger Termine, 403 FREE_PLAN_CALENDAR_LIMIT_REACHED). Eine Verknüpfung (linkType und linkId nur gemeinsam) muss auf einen eigenen Kunden bzw. ein eigenes Projekt zeigen, sonst 422 mit details.field: linkId.
Berechtigung: calendar:write
Parameter
| Name | Ort | Typ | Beschreibung |
Idempotency-Key Pflicht | Header | string | Eindeutiger Wert pro Anfrage, 8 bis 100 Zeichen (Buchstaben, Ziffern, ., :, _, -). Eine Wiederholung mit demselben Key und Inhalt liefert die gespeicherte Antwort statt einen zweiten Datensatz zu erzeugen. |
Body (JSON)
Schema CalendarEventInput
Antworten
| Status | Inhalt | Bedeutung |
201 | CalendarEvent | Der Termin wurde angelegt. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
409 | Error | Die erste Anfrage mit diesem Idempotency-Key läuft noch (API_IDEMPOTENCY_IN_PROGRESS). Kurz warten und mit demselben Key wiederholen. |
422 | Error | Der Idempotency-Key wurde bereits mit anderem Inhalt verwendet (API_IDEMPOTENCY_MISMATCH), oder der Kunde beziehungsweise ein Produkt der Rechnung existiert nicht (NOT_FOUND, details.field nennt das Feld). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
GET/v1/calendar/events/{id}
Einen Termin abrufen
Berechtigung: calendar:read
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Antworten
| Status | Inhalt | Bedeutung |
200 | CalendarEvent | Der Termin. Bei Serien die Zeiten des ersten Termins. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |
PATCH/v1/calendar/events/{id}
Termin ändern
Geändert werden nur die gesendeten Felder. Absagen mit status: cancelled. Wird nur start gesendet, bleibt die Dauer erhalten. Höchstens 12 Stunden. Serien und das Verschieben ganztägiger Termine antworten mit 400.
Berechtigung: calendar:write
Parameter
| Name | Ort | Typ | Beschreibung |
id Pflicht | Pfad | string (uuid) | |
Body (JSON)
Schema CalendarEventUpdate
Antworten
| Status | Inhalt | Bedeutung |
200 | CalendarEvent | Der geänderte Termin. |
400 | Error | Die Anfrage ist ungültig (Format, Pflichtfeld, unbekanntes Feld, ungültiger Cursor oder fehlender Idempotency-Key). |
401 | Error | Schlüssel fehlt, ist ungültig, widerrufen oder abgelaufen (API_KEY_INVALID, API_KEY_EXPIRED). |
403 | Error | Dem Schlüssel fehlt die Berechtigung (API_SCOPE_MISSING) oder die API ist für das Konto nicht freigeschaltet (API_NOT_AVAILABLE). |
404 | Error | Den Datensatz gibt es nicht. Fremde Datensätze liefern ebenfalls 404, nie 403. |
422 | Error | Ein Verweis im Body existiert nicht (NOT_FOUND, details.field nennt das Feld, z. B. customerId). |
429 | Error | Zu viele Anfragen (API_RATE_LIMITED). Der Header Retry-After nennt die Wartezeit in Sekunden. |