Public API - Übersicht Admin
📕 Für Administratoren und Entwickler - Diese Dokumentation beschreibt die spiritflow Public API für die programmatische Integration mit externen Systemen.
Überblick
Die spiritflow Public API ermöglicht die programmatische Integration von Aufgaben, Kunden, Projekten, Rechnungen und weiteren Ressourcen in externe Systeme. Die API ist REST-basiert und gibt JSON-Antworten zurück.
Basis-URL:
https://app.spiritflow.team/api/v1
Datumsformat: Alle Zeitstempel werden im ISO 8601-Format in UTC zurückgegeben (Beispiel: 2025-03-01T10:30:00Z). Datumsfelder ohne Uhrzeit (z.B. dueDate bei Projekten) werden als YYYY-MM-DD dargestellt.
Mandantenisolation: Jeder API-Key ist an genau einen Mandanten gebunden. Anfragen werden automatisch auf die Daten des jeweiligen Mandanten beschränkt. Es ist nicht möglich, über die API auf Daten eines anderen Mandanten zuzugreifen.
Authentifizierung
Die Public API authentifiziert alle Anfragen über einen API-Key, der als HTTP-Header übermittelt wird.
Header-Format
X-API-Key: sf_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
API-Key erstellen
API-Keys werden in der spiritflow-Anwendung unter Einstellungen > Integrationen > API-Keys erstellt. Nur Tenant-Administratoren können API-Keys erstellen und verwalten.
Pro Mandant sind maximal 10 API-Keys zulässig.
Sicherheitshinweis: Der vollständige API-Key wird nur einmalig bei der Erstellung angezeigt. Bewahren Sie ihn sicher auf. Es ist nicht möglich, den Schlüssel später erneut einzusehen.
Fehler bei Authentifizierung
| Situation | HTTP-Status | Fehlercode |
|---|---|---|
| API-Key fehlt oder leer | 401 | UNAUTHORIZED |
| API-Key ungültig oder widerrufen | 401 | INVALID_API_KEY |
| API-Key abgelaufen | 401 | API_KEY_EXPIRED |
| IP-Adresse nicht erlaubt | 403 | IP_NOT_ALLOWED |
| Scope fehlt | 403 | ACCESS_DENIED |
Response-Format
Alle Antworten folgen einem einheitlichen Hullformat.
Erfolg - Einzelobjekt
{
"data": {
"id": 42,
"title": "Webseite für Firma XYZ erstellen",
"status": "IN_PROGRESS"
},
"meta": {
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-03-01T10:30:00Z"
}
}
Erfolg - Liste mit Pagination
{
"data": [
{
"id": 42,
"title": "Webseite für Firma XYZ erstellen",
"status": "IN_PROGRESS"
},
{
"id": 43,
"title": "Logo-Design überarbeiten",
"status": "PLANNED"
}
],
"pagination": {
"page": 0,
"size": 20,
"totalElements": 57,
"totalPages": 3
},
"meta": {
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-03-01T10:30:00Z"
}
}
Fehler
{
"error": {
"code": "NOT_FOUND",
"message": "Task with ID 999 not found for this tenant.",
"status": 404,
"details": {
"id": 999
}
},
"meta": {
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-03-01T10:30:00Z"
}
}
Pagination
Alle Listen-Endpunkte unterstützen Pagination über Query-Parameter:
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
page | Integer | 0 | Seitennummer (0-basiert) |
size | Integer | 20 | Einträge pro Seite (max. 100) |
sort | String | abhaengig vom Endpunkt | Sortierfeld und Richtung, Format: feld,richtung |
Beispiele für sort:
createdAt,desc- Neueste zuersttitle,asc- Alphabetisch aufsteigenddueDate,asc- Fruehestes Fälligkeitsdatum zuerst
Scopes
Jeder API-Key trägt eine oder mehrere Berechtigungen (Scopes). Die verfügbaren Scopes sind:
| Scope | Beschreibung | Erlaubte Operationen |
|---|---|---|
tasks:read | Aufgaben lesen | GET-Anfragen auf /api/v1/tasks |
tasks:write | Aufgaben schreiben | POST, PUT, PATCH, DELETE auf /api/v1/tasks |
customers:read | Kunden lesen | GET-Anfragen auf /api/v1/customers |
customers:write | Kunden schreiben | POST, PUT, DELETE auf /api/v1/customers |
projects:read | Projekte lesen | GET-Anfragen auf /api/v1/projects |
projects:write | Projekte schreiben | POST, PUT, DELETE auf /api/v1/projects |
invoices:read | Rechnungen lesen | GET-Anfragen auf /api/v1/invoices (nur lesend) |
interactions:read | Interaktionen lesen | GET-Anfragen auf /api/v1/customers/{id}/interactions |
interactions:write | Interaktionen schreiben | POST auf /api/v1/customers/{id}/interactions |
cti:read | CTI-Daten lesen | GET-Anfragen auf /api/v1/cti/lookup und /api/v1/cti/device-mappings |
cti:write | CTI-Events senden | POST auf /api/v1/cti/events/incoming-call |
users:read | Benutzer lesen | GET-Anfragen auf /api/v1/users |
users:write | Benutzer anlegen | POST auf /api/v1/users, POST auf /api/v1/users/{id}/avatar |
time_entries:read | Zeiteinträge lesen | GET-Anfragen auf /api/v1/time-entries |
time_entries:write | Zeiteinträge schreiben | POST, PUT, DELETE auf /api/v1/time-entries |
vacation:read | Urlaubsanträge lesen | GET-Anfragen auf /api/v1/vacation-requests |
vacation:write | Urlaubsanträge erstellen | POST auf /api/v1/vacation-requests |
sick_leave:read | Krankmeldungen lesen | GET-Anfragen auf /api/v1/sick-leaves |
sick_leave:write | Krankmeldungen erstellen | POST auf /api/v1/sick-leaves |
tags:read | Tags lesen | GET-Anfragen auf /api/v1/tags |
tags:write | Tags erstellen | POST auf /api/v1/tags |
receipts:read | Belege lesen | GET-Anfragen auf /api/v1/receipts |
receipts:write | Belege erstellen und bearbeiten | POST, PATCH auf /api/v1/receipts |
webhooks:read | Webhooks lesen | GET-Anfragen auf /api/v1/webhooks |
webhooks:write | Webhooks verwalten | POST, PUT, DELETE auf /api/v1/webhooks |
tenant:read | Mandantendaten lesen | GET-Anfragen auf /api/v1/tenant |
tenant:write | Mandantendaten ändern | PUT-Anfragen auf /api/v1/tenant |
DSGVO-Hinweis: Die CTI-Scopes (cti:read, cti:write) ermöglichen den Zugriff auf Kundendaten (Telefonnummern, Namen) durch externe Systeme. Stellen Sie sicher, dass die CTI-Middleware in Ihrem Auftragsverarbeitungsvertrag (AVV) abgedeckt ist.
DSGVO-Hinweis: Krankmeldungen (sick_leave:read, sick_leave:write) sind Gesundheitsdaten und unterliegen besonderem Schutz gemäß DSGVO. Dieser Scope ist bewusst vom Urlaubs-Scope getrennt und sollte nur für Systeme vergeben werden, die diese Daten zwingend benötigen.
Hinweis: tasks:write schließt NICHT automatisch tasks:read ein. Für vollständigen Zugriff benötigen Sie beide Scopes. Gleiches gilt für alle anderen Ressourcen mit getrennten Lese- und Schreib-Scopes.
Sonderregel: Der Endpunkt GET /api/v1/projects/{id}/tasks erfordert sowohl projects:read als auch tasks:read.
Fehler-Codes
Alle Fehlermeldungen werden im einheitlichen Fehlerformat zurückgegeben (siehe Response-Format).
| HTTP-Status | Code | Beschreibung |
|---|---|---|
| 400 | VALIDATION_ERROR | Eingabefehler: Pflichtfeld fehlt, Wert ungültig oder Längenbeschraenkung überschritten |
| 400 | BAD_REQUEST | Allgemeiner Fehler in der Anfrage |
| 401 | UNAUTHORIZED | API-Key fehlt |
| 401 | INVALID_API_KEY | API-Key ungültig oder widerrufen |
| 401 | API_KEY_EXPIRED | API-Key ist abgelaufen |
| 403 | IP_NOT_ALLOWED | IP-Adresse des Aufrufers ist nicht in der Whitelist des API-Keys |
| 403 | ACCESS_DENIED | API-Key hat nicht den erforderlichen Scope für diese Operation |
| 404 | NOT_FOUND | Ressource nicht gefunden oder nicht zu diesem Mandanten gehoerig |
| 409 | CONFLICT | Konflikt mit aktuellem Zustand der Ressource (z.B. Überlappung bei Urlaubsanträgen) |
| 422 | VIRUS_DETECTED | Hochgeladene Datei wurde als infiziert erkannt und abgelehnt |
| 429 | RATE_LIMIT_EXCEEDED | Rate Limit überschritten |
| 500 | INTERNAL_ERROR | Interner Serverfehler |
| 503 | VIRUS_SCAN_FAILED | Virenscanner ist derzeit nicht verfügbar |
| 503 | VIRUS_SCAN_TIMEOUT | Virenscanner hat nicht rechtzeitig geantwortet |
Rate Limiting
Die Public API begrenzt die Anzahl der Anfragen pro API-Key.
Limit: 1.000 Anfragen pro Minute pro API-Key
Response-Header
Bei jeder Antwort werden folgende Header mitgeliefert:
| Header | Beschreibung |
|---|---|
X-RateLimit-Limit | Maximale Anfragen pro Minute |
X-RateLimit-Remaining | Verbleibende Anfragen im aktuellen Zeitfenster |
X-RateLimit-Reset | Unix-Timestamp, wann das Zeitfenster zurückgesetzt wird |
Antwort bei Rate Limit Überschreitung
Wenn das Rate Limit überschritten wird, antwortet der Server mit HTTP 429 Too Many Requests:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. You have sent too many requests. Please wait before retrying.",
"status": 429,
"details": {
"retryAfterSeconds": 30
}
},
"meta": {
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-03-01T10:30:00Z"
}
}
Empfehlung: Implementieren Sie Exponential Backoff in Ihrer Anwendung, um bei einem 429-Fehler nicht sofort erneut anzufragen. Warten Sie nach dem ersten Fehler z.B. 1 Sekunde, nach dem zweiten 2 Sekunden, nach dem dritten 4 Sekunden usw. Der retryAfterSeconds-Wert in der Fehlerantwort gibt an, nach wie vielen Sekunden das Rate Limit zurückgesetzt wird.