Flowdue API v1
Die Flowdue-API stellt Authentifizierung, Invite-Register und Lead-Erfassung für das Frontend bereit – per Cookie-Session und CSRF-Schutz.
X-CSRF-Token-Headerfeld plus Cookies (credentials: "include").Authentifizierung
Anmeldung per E-Mail + Passwort gegen POST /auth/login. Bei Erfolg setzt der Server zwei HttpOnly-Cookies: accessToken (15 Minuten, Path=/) und refreshToken (7 Tage, Path=/api/v1/auth/refresh). Der Access-Token kann alternativ als Authorization: Bearer-Header gesendet werden.
X-CSRF-Token: <Wert aus _csrf-Cookie> 401 INVALID_CREDENTIALS – ohne zu verraten, ob E-Mail, Passwort oder Kontostatus falsch sind.Basis-URL
https://localhost/api/v1 (lokal, produktiv eigene Domain) Alle Endpunkte liefern ausschließlich JSON. Fehler folgen dem Format aus Fehler.
Rate-Limits
| Limit | Wert |
|---|---|
| Global | 100 / 15 Minuten pro IP |
| Login / Admin-Login | 5 / 15 Minuten pro E-Mail + IP |
| Register | 3 / Stunde |
| Reset-Password | 5 / 15 Minuten |
| Leads | 10 / Stunde |
Bei Überschreitung antwortet die API mit HTTP 429 und dem Code RATE_LIMITED.
Fehler
Fehler werden einheitlich im folgenden Format zurückgegeben:
{
"success": false,
"code": "INVALID_CREDENTIALS",
"message": "E-Mail oder Passwort ist ungültig."
} | HTTP | Code | Bedeutung |
|---|---|---|
| 400 | VALIDATION_ERROR / EMAIL_MISMATCH / INVALID_TOKEN | Ungültige Eingabe oder abgelaufener Link |
| 401 | INVALID_CREDENTIALS / UNAUTHORIZED | Login falsch oder keine Session |
| 403 | FORBIDDEN / INVALID_CSRF | Keine Berechtigung oder CSRF fehlt |
| 404 | INVITE_NOT_FOUND | Einladung unbekannt |
| 409 | INVITE_USED / EMAIL_EXISTS | Einladung verbraucht oder Mail vergeben |
| 410 | INVITE_EXPIRED | Einladung abgelaufen (48h) |
| 428 | NEED_RECONSENT | Datenschutz erneut zustimmen |
| 429 | RATE_LIMITED | Rate-Limit überschritten |
Auth
/api/v1/auth/csrf-tokenSetzt das lesbare _csrf-Cookie (5h). Antwort: { success: true }.
/api/v1/auth/loginBody: { email, password }. Antwort 200: { success: true, user } plus Cookies. Konten mit Status pending werden mit 401 abgelehnt.
/api/v1/auth/admin-loginWie Login, lässt aber nur role: admin durch (sonst generisch 401).
/api/v1/auth/verifySession-Boot (Auth nötig). Antwort: { user, features }.
/api/v1/auth/refreshRotiert das Refresh-Token (liest refreshToken-Cookie, braucht CSRF-Header). Wiederverwendung sperrt alle Sessions.
/api/v1/auth/logoutMeldet die aktuelle Session ab (Auth nötig). POST /auth/logout-all beendet alle Sessions des Users.
/api/v1/auth/forgot-passwordBody: { email }. Antwort immer generisch (kein User-Enumeration). Token 1h gültig.
Body (JSON)
POST /api/v1/auth/reset-password
{ "token": "…", "password": "Neues!Passwort1" } Setzt ein neues Passwort (starke Regeln wie Register) und meldet alle Sessions ab. Kein Auto-Login.
/api/v1/auth/re-consentBody: { email, password, acceptPrivacyVersion }. Login-Weiterführung bei aktualisierter Datenschutzerklärung.
Register & Invites
Registrierung ist ausschließlich per Einladung möglich (48h, einmalig, an E-Mail gebunden).
/api/v1/auth/invite/:tokenPrüft einen Invite-Link. Antwort 200: { email, expiresAt }.
/api/v1/auth/registerBody: { inviteToken, firstName, lastName, company, email, password, acceptTerms }. Passwort: min. 12 Zeichen, Groß-/Kleinbuchstaben, Zahl, Sonderzeichen. Antwort 201, Status pending – kein Auto-Login.
Antwort (201)
{
"success": true,
"user": { "id": "…", "email": "…", "status": "pending", … }
}Admin
Alle Admin-Endpunkte brauchen eine Admin-Session (role: admin).
/api/v1/admin/invitesBody: { email }. Erzeugt eine Einladung, Antwort mit inviteLink (/register?invite=…).
Leads
/api/v1/leadsErstgespräch-Anfrage (10/h). Body: { firstname, lastname, company, role, phone, email, tool, invoices, revenue }.
Code-Beispiele
cURL – Login + Verify
# 1. CSRF-Cookie holen
curl -c jar.txt https://localhost/api/v1/auth/csrf-token
CSRF=$(grep _csrf jar.txt | awk '{print $NF}')
# 2. Login
curl -b jar.txt -c jar.txt -X POST https://localhost/api/v1/auth/login \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: $CSRF" \
-d '{"email":"admin@flowdue.local","password":"…"}'
# 3. Session prüfen
curl -b jar.txt https://localhost/api/v1/auth/verify JavaScript (fetch)
const res = await fetch("https://localhost/api/v1/auth/verify", {
credentials: "include",
});
const { user } = await res.json();
console.log(user); Admin – Invite erzeugen
const res = await fetch("https://localhost/api/v1/admin/invites", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json", "X-CSRF-Token": csrf },
body: JSON.stringify({ email: "neu@beispiel.de" }),
});
const { inviteLink } = await res.json();