Exportschnittstelle
Diese Seite beschreibt, wie ein Kunde oder ein von ihm beauftragter Zielanbieter das vollständige Exportpaket abruft. Sie richtet sich an Entwicklerinnen und Entwickler. Die allgemeinverständliche Fassung steht unter Datenexport und Anbieterwechsel. Formatfassung: 1.0.
Was ein Export ist — und was nicht
Ein Export erstellt eine Kopie. Er beendet keinen Vertrag, kündigt nichts und löst keine Löschung aus. Anbieterwechsel und Löschung sind eigene Vorgänge, die der Kunde ausdrücklich auswählt. Ein Abruf über diese Schnittstelle verändert am Konto nichts außer dem Abrufzähler des benutzten Zugangs.
Authentifizierung
Es gibt keinen unauthentifizierten Zugang. Zwei Wege sind möglich:
- Sitzung — der angemeldete Kontoinhaber lädt direkt herunter.
- Export-Token — der Kontoinhaber erzeugt einen Zugang und gibt ihn an den Zielanbieter weiter. Das Token ist 32 Byte Zufall (base64url) und wird serverseitig nur als SHA-256 gespeichert; es wird genau einmal ausgeliefert und lässt sich nicht erneut anzeigen.
Ein Token ist ausschließlich an das Konto gebunden, das es erzeugt hat. Es gibt keinen Parameter, mit dem sich ein anderes Konto ansprechen ließe.
Ablauf
# 1) Zugang erzeugen (als angemeldeter Kontoinhaber)
curl -X POST https://kurzhand.de/api/export/jobs \
-H "content-type: application/json" \
-d '{"gueltigkeit_minuten": 60, "max_abrufe": 3}'
# Antwort (gekürzt) — das Token erscheint nur hier:
# { "success": true, "data": {
# "id": "…", "token": "…", "download_url": "https://kurzhand.de/api/export/paket?token=…",
# "laeuft_ab_am": "2026-08-03T12:00:00.000Z", "max_abrufe": 3 } }
# 2) Paket abrufen (Zielanbieter, ohne Konto bei kurzhand)
curl -L -o kurzhand-export.zip "https://kurzhand.de/api/export/paket?token=…"
# 3) Zugang widerrufen, sobald der Wechsel abgeschlossen ist
curl -X POST https://kurzhand.de/api/export/jobs/widerruf \
-H "content-type: application/json" -d '{}'Endpunkte
| Endpunkt | Authentifizierung | Wirkung |
|---|---|---|
POST /api/export/jobs | Sitzung des Kontoinhabers | Legt einen Exportzugang an und liefert das Token genau einmal zurück. Optionaler Body: gueltigkeit_minuten (5–1440, Standard 60), max_abrufe (1–10, Standard 3). |
GET /api/export/jobs | Sitzung des Kontoinhabers | Listet die eigenen Exportzugänge mit Status, Ablauf, Abrufzahl, Größe und Prüfsumme. Ohne Tokens. |
POST /api/export/jobs/widerruf | Sitzung des Kontoinhabers | Widerruft einen Zugang (Body: {"id": "…"}) oder ohne Body alle offenen Zugänge. Wirkt sofort. |
GET /api/export/paket?token=… | Export-Token | Liefert das vollständige Paket als ZIP. Auch mit angemeldeter Sitzung und ohne Token aufrufbar. |
GET /api/export-data | Sitzung des Kontoinhabers | Nur die Datensätze als JSON, ohne Dateien. Gleicher Inhalt wie data.json im Paket. |
Aufbau des Pakets
Das Paket ist ein ZIP-Archiv ohne Komprimierung (Methode STORE, Dateinamen in UTF-8). Es wird gestreamt ausgeliefert; die Reihenfolge ist data.json, dann die Dateien, zuletzt manifest.json.
kurzhand-export-JJJJ-MM-TT.zip
├── data.json alle Datensätze, nach Bereichen gegliedert
├── manifest.json jede Datei mit Typ, Größe, SHA-256 und Bezug
├── dateien/logos/ Firmenlogo
├── dateien/angebote/ Angebots-PDF
├── dateien/rechnungen/ Rechnungs-PDF und E-Rechnungs-XML
├── dateien/abnahmen/ Abnahmefotos
└── dateien/auftragsfotos/ AuftragsfotosDie Dateipfade innerhalb der Ordner entsprechen den ursprünglichen Speicherpfaden ohne die vorangestellte Kontokennung. Gleiche Dateinamen bekommen einen Zähler angehängt, damit beim Entpacken nichts überschrieben wird.
Aufbau von data.json
{
"exportiert_am": "2026-08-03T10:00:00.000Z",
"format_version": "1.0",
"nutzer": { "id": "…", "email": "…" },
"hinweise": {
"vollstaendigkeit": "…",
"entfernte_felder": "…",
"nicht_enthalten": { … },
"unvollstaendige_bereiche": [],
"fehlerhafte_bereiche": []
},
"bereiche": {
"kunden": [ { … } ],
"angebote": [ { … } ],
…
}
}Die Felder innerhalb eines Bereichs entsprechen eins zu eins den Spalten der jeweiligen Tabelle. Sie sind nicht umbenannt — ein Zielanbieter sieht die Rohstruktur und muss nicht raten, welche Umbenennung was bedeutet.
Datenkategorien
Das Paket enthält die folgenden Bereiche, soweit im Konto vorhanden:
| Bereich in data.json | Quelle |
|---|---|
profil | profiles |
kunden | kunden |
angebote | angebote |
rechnungen | rechnungen |
leistungen | leistungen |
materialien | materialien |
vorlagen | vorlagen |
auftraege | auftraege |
activity | activity |
erinnerungen | reminders |
agent_tasks | agent_tasks |
abonnements | subscriptions |
angebot_signaturen | angebot_signaturen |
rechnungsnummern_nachweis | invoice_numbers |
serienrechnungen | recurring_invoices |
auftrag_serien | auftrag_serien |
auftrag_fotos | auftrag_fotos |
abnahmen | abnahmen |
abnahme_maengel | abnahme_maengel |
abnahme_fotos | abnahme_fotos |
abnahme_signaturen | abnahme_signaturen |
zeiteintraege | zeiteintraege |
zeiteintrag_aenderungen | zeiteintrag_aenderungen |
ki_guthaben | ai_credits |
ki_nutzung | ai_usage |
ki_bestaetigungen | ai_confirm_tokens_used |
ki_provenienz | ki_provenienz |
team_mitglieder | team_mitglieder |
team_mitglied_episoden | team_mitglied_episoden |
team_audit_log | team_audit_log |
team_einladungen | team_einladungen |
urlaubsanspruch | urlaubsanspruch |
abwesenheiten | abwesenheiten |
zeit_korrektur_antraege | zeit_korrektur_antraege |
auftrag_berichte | auftrag_berichte |
dokument_freischaltungen | document_unlocks |
rechtstext_einbeziehungen | legal_acceptance_log |
unternehmerbestaetigungen | b2b_bestaetigungen |
support_tickets | support_tickets |
support_ticket_nachrichten | support_ticket_messages |
produkt_ereignisse | product_events |
lead_funnel_importe | lead_funnel_imports |
mail_eingaenge | mail_eingaenge |
debitor_nummernkreis | debitor_nummernkreis |
ausgehende_email_jobs | outbound_email_jobs |
abgelehnte_buchungen_land | billing_country_rejections |
dokumentlink_protokoll | document_link_audit |
exportauftraege | export_jobs |
newsletter_abonnement | newsletter_subscribers |
Prüfsummen
Zu jeder enthaltenen Datei steht im Manifest der SHA-256 des Dateiinhalts in Hexadezimalschreibweise. Nach dem Abruf lässt sich damit prüfen, ob das Paket vollständig übertragen wurde. Zusätzlich wird der SHA-256 des gesamten Archivs berechnet und am Exportauftrag hinterlegt; er ist über GET /api/export/jobs abrufbar.
shasum -a 256 kurzhand-export-2026-08-03.zipFehlende Dateien
Kann eine Datei nicht gelesen werden, bricht der Export nicht ab. Sie erscheint im Manifest mit "status": "fehlt" samt Grund. So ist die Lücke sichtbar, statt dass ein scheinbar vollständiges Paket entsteht.
Grenzen
- Keine feste Zeilengrenze je Bereich; die Daten werden seitenweise vollständig geholt.
- Das Archiv ist auf 4 GiB begrenzt (ZIP ohne ZIP64). Darüber bricht der Export mit einer klaren Meldung ab.
- Höchstens fünf offene Exportzugänge je Konto gleichzeitig.
- Gültigkeit eines Zugangs: 5 Minuten bis 24 Stunden. Abrufe: 1 bis 10.
- Rate-Limit auf allen Exportendpunkten.
- Die Antwort wird gestreamt; eine Wiederaufnahme abgebrochener Downloads (Range-Requests) gibt es nicht.
Was nicht enthalten ist
- Zugriffstokens, Passwort-Hashes und Schlüssel. Sie sind Zugangsmittel, keine Nutzdaten; ein Export würde fremde Zugriffe auf Ihre Dokumente ermöglichen.
- Interne Support-, Vertriebs- und Bewertungsvermerke der Rolsing & Kokorin GbR (admin_*, leads). Sie sind eigene Aufzeichnungen des Anbieters und nicht vom Kunden bereitgestellt. Auskunft dazu auf Anfrage an datenschutz@kurzhand.de.
- Protokolle des internen Entwicklungswerkzeugs (agent_logs, agent_messages). Sie haben keinen Bezug zu Ihrem Konto.
- Rohereignisse des Zahlungsdienstleisters (billing_webhook_events). Ihre Abonnement- und Zahlungsdaten sind unter „abonnements" enthalten; die Originalbelege liegen bei Stripe.
- Das Cookie-Einwilligungsprotokoll. Es ist an eine pseudonyme Kennung im Browser gebunden und nicht Ihrem Konto zugeordnet.
- Daten anderer Betriebe. Alle Abfragen sind an Ihr Konto gebunden und zusätzlich durch Row Level Security begrenzt.
- E-Mail-Anhänge aus dem Mail-Eingang. kurzhand speichert davon nur Metadaten (Dateiname, Typ, Größe); die Datei selbst wird für die Auswertung nur vorübergehend abgerufen und nicht abgelegt.
Fehlerbehandlung
| HTTP | code | Bedeutung |
|---|---|---|
| 401 | nicht angemeldet | Kein Token übergeben und keine gültige Sitzung. |
| 403 | unbekannt | Das Token gehört zu keinem Zugang. Es wird nicht verraten, ob es je existiert hat. |
| 403 | widerrufen | Der Zugang wurde vom Kontoinhaber widerrufen. |
| 403 | abgelaufen | Die Gültigkeitsdauer ist verstrichen. |
| 403 | aufgebraucht | Die vereinbarte Zahl der Abrufe ist erreicht. |
| 409 | zu_viele_offene_exporte | Es sind bereits fünf Zugänge offen. Erst einen widerrufen. |
| 429 | — | Rate-Limit. Später erneut versuchen. |
| 500 | — | Serverfehler. Der Auftrag wird als fehlgeschlagen vermerkt und kann erneut abgerufen werden. |
Fehlerantworten haben stets die Form {"success": false, "error": "…", "code": "…"}.
Protokollierung
Anlegen, Abruf, Abschluss, Fehlschlag und Widerruf eines Exportzugangs werden protokolliert. Das Protokoll enthält keine Tokens und keine Exportinhalte. Wird ein Konto gelöscht, werden offene Exportzugänge automatisch widerrufen — ein Token soll das Konto nicht überdauern.
Bei technischen Problemen
Schreib uns an hallo@kurzhand.de. Nenne dabei die Kennung des Exportauftrags (nicht das Token) und den Zeitpunkt des Abrufs. Für Fragen zum Datenschutz: datenschutz@kurzhand.de.
