OAuth 2.1 statt API-Key
Wer fremde finisma-Konten anspricht (ein n8n-Workflow, ein Chat-Connector, eine eigene Anwendung), sollte keinen Key abtippen lassen. Über OAuth klickt der Nutzer einmal auf „Erlauben“ und die Anwendung bekommt ein Token, das sie selbst erneuert. Der Nutzer sieht die Verbindung in seinem Konto und kann sie dort jederzeit trennen.
Der Ablauf ist Authorization Code mit PKCE (S256), ohne code_challenge lehnt der Server ab. Endpunkte findet ein Client selbst über die Discovery-Dokumente:
https://finisma.de/.well-known/oauth-authorization-server https://finisma.de/.well-known/oauth-protected-resource
Anwendung registrieren
Für eine Integration, die Sie selbst betreiben, legen Sie die Anwendung im Konto an (Abschnitt „Eigene Anwendungen (OAuth)“). Dort erhalten Sie client_id und client_secret, sehen Ihre Anwendungen in einer Liste und können sie jederzeit wieder sperren.
Chat-Connectoren wie ChatGPT oder Claude brauchen das nicht: sie registrieren sich selbst über RFC 7591, weil sie ihre Redirect URL mitbringen und keine Zugangsdaten haben, mit denen sie sich ausweisen könnten. Für eigene Clients steht derselbe Endpunkt offen. Die Redirect URL muss exakt der entsprechen, die die Anwendung später schickt.
curl -X POST https://finisma.de/api/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "Mein n8n",
"redirect_uris": ["https://n8n.example.com/rest/oauth2-credential/callback"]
}'Die Antwort enthält client_id und client_secret. Wer einen öffentlichen Client baut (Browser, Desktop, Chat-Connector), schickt zusätzlich "token_endpoint_auth_method": "none" und bekommt kein Secret; abgesichert wird dann allein über PKCE.
Ablauf
- Nutzer auf
/api/oauth/authorizeschicken, mitclient_id,redirect_uri,response_type=code,code_challenge,code_challenge_method=S256,stateundscope. - Nach der Zustimmung kommt der Code an die Redirect URL zurück. Er ist fünf Minuten gültig und genau einmal einlösbar.
- Code an
/api/oauth/tokentauschen (mitcode_verifier). Zurück kommen ein Access-Token (fnso_…, eine Stunde gültig) und ein Refresh-Token (180 Tage). - Abgelaufene Access-Tokens über
grant_type=refresh_tokenerneuern. Das alte Refresh-Token verfällt dabei (Rotation), es gilt immer nur das neueste.
Scopes: invoice:verify und invoice:create. Fehlt der passende Scope, antwortet die API mit 403 und insufficient_scope, auch dann, wenn das Konto die Funktion an sich hätte. Ein Token beenden: POST /api/oauth/revoke mit token und client_id.
Wo das Token danach verwendet wird: REST-API-Referenz und MCP-Connector. Beide akzeptieren denselben Bearer-Token wie einen API-Key.