Für Entwickler

Die Floowa-API

Eine REST-API mit JSON, persönliche API-Tokens und signierte Webhooks. Die Referenz ist öffentlich; zum Ausprobieren brauchen Sie ein Floowa-Konto.

Anmeldung

Ein Administrator legt unter Einstellungen → API-Zugänge ein Token an, wählt die Rechte je Funktion und ein Ablaufdatum (30, 90 oder 365 Tage oder unbegrenzt). Das Token wird nur einmal angezeigt.

Authorization: Bearer <token>
Accept: application/json

Basis-URL: https://www.floowa.de/api/v1

  • Jede Anfrage läuft in der Firma des Token-Inhabers und darf nie mehr, als das Token und die eigenen Rechte des Inhabers erlauben.
  • Die API ist in allen Paketen enthalten; Endpunkte gebuchter Module stehen zur Verfügung, sobald das Modul aktiv ist.
  • Fehlermeldungen kommen in der Sprache des Headers Accept-Language (sonst Englisch).

Grenzen und Verhalten

Grenzen und Verhalten
Rate-Limit 120 Anfragen pro Minute und Token; darüber antwortet die API mit HTTP 429.
Listen Listen kommen seitenweise; mit per_page holen Sie bis zu 100 Einträge pro Seite.
Sicher wiederholen Mit dem Header Idempotency-Key liefert eine wiederholte Anfrage 24 Stunden lang dieselbe Antwort, statt etwas doppelt anzulegen.
API-Stand Jede Antwort trägt den Header Floowa-Api-Revision mit dem Datum der letzten API-Änderung.

Webhooks und Signatur

Jede Zustellung ist ein POST mit JSON an Ihre HTTPS-Adresse, mit den Headern X-Floowa-Event, X-Floowa-Delivery und X-Floowa-Signature.

Die Signatur hat die Form t=<Zeitstempel>,v1=<Signatur>. v1 ist ein HMAC-SHA256 über „<Zeitstempel>.<Rohdaten>“ mit Ihrem Signatur-Schlüssel. Vergleichen Sie zeitkonstant und verwerfen Sie alte Zeitstempel.

Antwortet Ihr Server nicht mit einem 2xx-Status, versucht Floowa es nach 1, 5 und 30 Minuten und nach 2 Stunden erneut. Nach 20 Fehlversuchen in Folge wird der Webhook deaktiviert.

Beispiel einer Zustellung

{
    "id": "8f2c3a1e-5b7d-4c1a-9e2f-0a1b2c3d4e5f",
    "event": "absence.requested",
    "created_at": "2026-10-28T09:15:00+01:00",
    "data": {
        "id": "01a1…",
        "employee_id": "01a0…",
        "absence_type_id": "01a0…",
        "start_date": "2026-11-02",
        "end_date": "2026-11-06",
        "half_day_start": false,
        "half_day_end": false,
        "days": 5,
        "status": "pending"
    }
}

Signatur prüfen (PHP)

$header = $_SERVER["HTTP_X_FLOOWA_SIGNATURE"] ?? "";
parse_str(str_replace(",", "&", $header), $parts);
$body = file_get_contents("php://input");
$expected = hash_hmac("sha256", $parts["t"] . "." . $body, $secret);

if (! hash_equals($expected, $parts["v1"] ?? "") || abs(time() - (int) $parts["t"]) > 300) {
    http_response_code(400);
    exit;
}

Alle Ereignisse in verständlichen Worten

Diese Ereignisse meldet Floowa per Webhook
Ereignis Wann Technischer Name
Mitarbeiter angelegt Ein Mitarbeiter wird angelegt – von Hand, per Import oder über die API. employee.created
Mitarbeiter geändert Die Stammdaten eines Mitarbeiters ändern sich. employee.updated
Mitarbeiter gelöscht Ein Mitarbeiter wird gelöscht. employee.deleted
Abwesenheit beantragt Jemand beantragt Urlaub oder eine andere Abwesenheit. absence.requested
Abwesenheit genehmigt Ein Antrag wird genehmigt oder eine Abwesenheit direkt eingetragen. absence.approved
Abwesenheit abgelehnt Ein Antrag wird abgelehnt. absence.rejected
Abwesenheit storniert Ein Antrag oder eine Abwesenheit wird zurückgezogen. absence.cancelled
Zeit erfasst Ein Zeiteintrag entsteht – beim Einstempeln, beim Nachtragen oder am Terminal. time_entry.created
Zeit geändert Ein Zeiteintrag ändert sich, zum Beispiel beim Ausstempeln. time_entry.updated
Zeit gelöscht Ein Zeiteintrag wird gelöscht. time_entry.deleted
Monat abgeschlossen Ein Monat wird in der Lohnvorbereitung abgeschlossen. payroll.closed
Monat wieder geöffnet Ein abgeschlossener Monat wird für Korrekturen wieder geöffnet. payroll.reopened
Schicht veröffentlicht Eine Schicht wird mit dem Schichtplan veröffentlicht. shift.published
Schicht geändert Eine veröffentlichte Schicht ändert sich. shift.changed
Schicht gestrichen Eine veröffentlichte Schicht wird gelöscht. shift.deleted

Änderungsprotokoll

Alle Änderungen an der API mit Datum und Hinweis auf nicht abwärtskompatible Änderungen. Maschinenlesbar unter GET /api/v1/changelog.

2026-11-02 · 2. November 2026

  • Neu Sollzeit-Einstellungen an Mitarbeitern: Antworten enthalten effective_weekly_hours (eigene Wochenstunden oder der Firmenstandard; null ohne feste Sollzeit), no_fixed_hours (keine feste Sollzeit, z. B. Geschäftsführung oder Vertrauensarbeitszeit) und working_time_law_exempt (keine Arbeitszeitgesetz-Prüfungen, z. B. GmbH-Geschäftsführer oder leitende Angestellte). POST und PUT nehmen no_fixed_hours und working_time_law_exempt optional entgegen; neue employment_type managing_director (Geschäftsführung). weekly_hours bleibt unverändert. GET /employeesGET /employees/{id}POST /employeesPUT /employees/{id}

2026-10-30 · 30. Oktober 2026

  • Neu Inventar-Prüfungen und Pflichtqualifikationen über Inventar: GET /qualifications liefert required_inventory_category_ids und die neue Kategorie check (Kontrolle, ohne Dokument); GET /employees/{id}/qualifications liefert requirement_reasons (warum eine Qualifikation Pflicht ist – Einheit oder ausgegebener Gegenstand); GET /inventory-items/{id} enthält inspections mit due_on, last_done_on und status (ok, due_soon, overdue). GET /qualificationsGET /employees/{id}/qualificationsGET /inventory-items/{id}
  • Neu Abwesenheiten: POST /absences/{id}/cancel nimmt optional reason entgegen und storniert auch genehmigte Abwesenheiten; Antworten enthalten cancel_requested_at (offener Stornierungsantrag eines Mitarbeiters) und cancel_reason. Einen offenen Stornierungsantrag entscheidet POST /absences/{id}/decision (approve = stornieren, reject = Abwesenheit behalten). POST /absences/{id}/cancelGET /absences
  • Geändert Projektnamen müssen nur noch je Kunde eindeutig sein; derselbe Name ist bei verschiedenen Kunden erlaubt. Projekte ohne Kunde bleiben untereinander eindeutig. POST /time-projectsPUT /time-projects/{id}

2026-10-29 · 29. Oktober 2026

  • Neu Projektzeit pro Eintrag: Zeiteinträge nehmen customer_id (Kunde ohne Projekt) und parts (Aufteilung auf mehrere Projekte/Kunden mit minutes oder start/end) entgegen; GET /time-allocations liefert customer_id, label, started_at/ended_at und kind part, Filter customer_id. POST /time-entriesPUT /time-entries/{id}GET /time-allocations
  • Neu Organisationseinheiten: clock_web und clock_app (true/false, null = wie übergeordnet) legen fest, ob Mitarbeitende dieser Einheit im Browser bzw. in der App stempeln dürfen. GET /org-unitsPOST /org-unitsPUT /org-units/{id}
  • Entfernt nicht abwärtskompatibel Die freie Tageszuordnung PUT /employees/{id}/time-allocations/{date} entfällt – bitte die Aufteilung über parts am Zeiteintrag senden. Bestehende freie Zuordnungen wurden dem längsten Eintrag des Tages zugeordnet. PUT /employees/{id}/time-allocations/{date}

2026-10-28 · 28. Oktober 2026

  • Neu Projektzeit getrennt von der Anwesenheit: GET /time-allocations liefert, welchem Projekt die Zeit eines Tages zugeordnet ist; PUT /employees/{id}/time-allocations/{date} setzt die freien Zuordnungen eines Tages. time_project_id an Zeiteinträgen bleibt erhalten und erzeugt automatisch eine verknüpfte Zuordnung. GET /time-allocationsPUT /employees/{id}/time-allocations/{date}

2026-10-26 · 26. Oktober 2026

  • Neu Lohnvorbereitung: neues Objekt surcharges_3b je Mitarbeiter mit Zuschlagsminuten nach § 3b EStG (night_25, night_40, sunday_50, holiday_125, holiday_150). Die Felder night und holiday bleiben als Summen erhalten. GET /payroll/{month}
  • Geändert nicht abwärtskompatibel Lohnvorbereitung: sunday zählt keine Feiertage mehr, dafür die Stunden 0–4 Uhr am Montag nach einer am Sonntag begonnenen Schicht. holiday enthält zusätzlich 24.12. und 31.12. ab 14 Uhr. Pausen werden anteilig abgezogen. GET /payroll/{month}
  • Datenschutz/Sicherheit nicht abwärtskompatibel Abwesenheiten: Wer nur Leserechte hat, sieht vertrauliche Abwesenheitsarten (z. B. Krankheit) als neutrale Abwesenheit – absence_type_id, type, note und decision_note sind dann null, das neue Feld type_hidden ist true. Die Lohnauswertung fasst solche Tage in der Spalte type_hidden zusammen. GET /absencesGET /reports/payroll
  • Neu Neuer Endpunkt GET /changelog und Header Floowa-Api-Revision an jeder Antwort. GET /changelog

2026-10-23 · 23. Oktober 2026

  • Neu Erste Version der API v1: Organisation, Personal, Dokumente, Qualifikationen, Inventar, Lohnabrechnungen, Zeiterfassung inkl. Stempeluhr und Freigabe, Projekte und Kunden, Abwesenheiten, Feiertage, Auswertungen, Lohnvorbereitung, Idempotency-Key und Webhooks.

Packen wir's an. Servus und willkommen bei Floowa.