SaaS-Partner-API: Rate Limits, API-Keys und Versionierung für ein Drittanbieter-Ökosystem
In dem Moment, in dem ein SaaS-Produkt eine öffentliche API für Drittanbieter-Entwickler öffnet, ändern sich die Regeln. Eine interne API muss nur die Fehler des eigenen Frontend-Teams überstehen. Eine SaaS-Partner-API muss Fremde überstehen: Integratoren, die zu aggressiv wiederholen, vergessen, einen 429er zu behandeln, eine Response-Struktur hardcoden, die man im nächsten Quartal ändern will, oder einen Webhook-Handler ausliefern, der stillschweigend Events verliert. Die meisten Teams, die zum ersten Mal eine Partner-API bauen, unterschätzen, wie viel der Arbeit defensives Design statt Feature-Arbeit ist.
Dieser Beitrag behandelt die fünf Bausteine, die eine Partner-API operativ solide machen: API-Key-Verwaltung, Rate Limiting, Versionierung, Webhooks und Observability. Die Beispiele nutzen Symfony, aber die zugrunde liegenden Entscheidungen gelten unabhängig vom Framework.
API-Key-Verwaltung: Erzeugung, Speicherung und Rotation
Ein API-Key ist eine Anmeldeinformation und sollte mit derselben Sorgfalt behandelt werden wie ein Passwort. Die drei Teile, bei denen die meisten Teams Fehler machen, sind Erzeugung, Speicherung und Rotation.
Erzeuge Keys mit einer kryptografisch sicheren Zufallsquelle, nicht mit uniqid() oder allein einer UUID. Ein gängiges Muster ist ein öffentliches Präfix für den Lookup (damit sich in Logs identifizieren lässt, welcher Key eine Anfrage gestellt hat, ohne irgendetwas zu entschlüsseln), gefolgt von einem langen zufälligen Secret: etwa pk_live_ plus 32 zufällige Bytes, base62-kodiert. Symfonys random_bytes() kombiniert mit einem base62-Encoder deckt das ohne zusätzliche Abhängigkeiten ab.
Speichere niemals den rohen Key. Speichere einen Hash davon, genau wie bei einem Passwort, mit password_hash() und einem starken Algorithmus, oder einem schnellen Keyed Hash wie HMAC-SHA256, wenn du bei hohem Request-Volumen Lookups brauchst und dafür einen Teil der Brute-Force-Resistenz von bcrypt gegen Geschwindigkeit eintauschen kannst (der Key selbst trägt bereits genug Entropie, dass dieser Trade-off für API-Anmeldeinformationen vertretbar ist, anders als bei Nutzerpasswörtern). Wenn eine Anfrage eintrifft, hashe den übergebenen Key und suche den Hash, nicht den Klartext.
Rotation muss ohne Downtime für den Partner funktionieren. Der praktische Ansatz ist, jedem Partner-Account zu erlauben, gleichzeitig zwei aktive Keys zu halten: einen primären und einen sekundären. Wenn eine Rotation ansteht, erzeuge einen neuen sekundären Key, lass den Partner seine Integration aktualisieren, und widerrufe den alten Key erst, wenn Traffic auf dem neuen sichtbar ist, oder nach einer festen Übergangsfrist. Ein Ein-Key-Modell, das in dem Moment stirbt, in dem man neu generiert, zwingt jede Rotation in ein Support-Ticket.
Begrenze Keys auf das, was sie können sollen. Ein Key, der Bestelldaten lesen kann, muss nicht auch Rückerstattungen auslösen können. Symfonys Security Voters passen dafür genau: hänge jedem Key bei der Erstellung eine Menge an Scopes an und prüfe sie in einem Voter, statt if ($key->hasScope())-Prüfungen über die Controller zu verstreuen.
Rate Limiting, das fair ist, nicht nur streng
Eine Partner-API braucht Rate Limiting aus zwei unterschiedlichen Gründen: um die eigene Infrastruktur vor dem Bug eines Partners zu schützen, und um gutartige Partner voreinander zu schützen. Ein einziges globales Rate Limit erfüllt keinen der beiden Zwecke gut.
Limitiere pro API-Key, nicht pro IP. Partner rufen die API oft von geteilter Infrastruktur, Load Balancern oder Serverless-Funktionen mit wechselnden ausgehenden IPs auf, sodass IP-basierte Limits missbräuchliche Keys hinter einem großen IP-Pool übersehen oder mehrere unabhängige Partner, die sich eine IP teilen, zu Unrecht drosseln.
Ein Sliding-Window-Zähler ist für die meisten Partner-APIs der richtige Algorithmus. Ein festes Fenster (Reset jede Stunde zur vollen Stunde) erlaubt einem Partner, das doppelte Limit zu überschreiten, indem er die Grenze trifft: ein volles Kontingent in der letzten Sekunde eines Fensters sendet und ein weiteres volles Kontingent in der ersten Sekunde des nächsten. Ein Sliding Window, implementiert mit einer sortierten Menge in Redis, indiziert nach API-Key, verfolgt die tatsächlichen Request-Zeitstempel im nachlaufenden Zeitraum und vermeidet diesen Grenzfall. Symfony liefert mit der Rate-Limiter-Komponente eine eingebaute Sliding-Window-Policy, gestützt von Redis oder einem anderen unterstützten Cache-Adapter, sodass es keine eigene Implementierung braucht.
Erlaube zusätzlich zur Dauerrate einen Burst. Ein Partner, der nach einem vorübergehenden Ausfall auf seiner Seite einen Rückstand an Datensätzen synchronisiert, muss eine kurze Anfragespitze senden können, ohne gegen eine Wand zu laufen, solange sein Durchschnitt innerhalb des vereinbarten Limits bleibt. Ein Token Bucket über dem Sliding Window übernimmt das: eine feste Anzahl Tokens füllt sich mit stetiger Rate nach, und Anfragen zehren vom Bucket, sodass kurze Bursts abgefedert werden, während dauerhafte Überlastung nicht durchgeht.
Wenn du eine Anfrage drosselst, sag es klar. Gib einen 429-Statuscode mit einem Retry-After-Header zurück, der angibt, wie viele Sekunden zu warten sind, und liefere das verbleibende Kontingent in X-RateLimit-Remaining bei jeder Antwort, nicht nur bei gedrosselten, damit gut geschriebene Integrationen abbremsen können, bevor sie das Limit treffen, statt danach.
Versionierung: eine Strategie wählen und konsequent bleiben
Es gibt drei gängige Wege, eine öffentliche API zu versionieren, und die Wahl ist weniger wichtig als konsequent bei einer zu bleiben und sie überall gleich anzuwenden.
URL-Versionierung, die Version im Pfad wie /v2/orders, ist für Partner am sichtbarsten und am einfachsten in einem Reverse Proxy oder in Symfonys Routing-Konfiguration zu routen, da man ein ganzes Präfix auf einen anderen Controller-Namespace zeigen lassen kann. Der Nachteil ist, dass sie ganze doppelte Routenbäume fördert, sogar für Endpunkte, die sich eigentlich nicht geändert haben.
Header-Versionierung, etwa Api-Version: 2026-06-01 zu senden, hält URLs stabil und erlaubt es, Ressourcen unabhängig zu versionieren statt die ganze API auf einmal, aber Partner vergessen leicht, den Header zu setzen, und es ist schwerer, manuell im Browser oder mit einem schnellen curl-Befehl während der Integration zu testen.
Content Negotiation, Versionierung über den Medientyp im Accept-Header, ist im strengen REST-Sinn am korrektesten, aber in der Praxis am seltensten, und die meisten Partner-Entwickler werden sie nicht erwarten.
Für die meisten SaaS-Partner-APIs ist URL-Versionierung die pragmatische Wahl, gerade weil sie für einen Drittanbieter-Entwickler am einfachsten zu verstehen ist, ohne die Dokumentation genau zu lesen, und das zählt für die Adoption mehr als architektonische Reinheit. Egal, wofür man sich entscheidet: verpflichte dich, die vorherige Version für ein festgelegtes Deprecation-Fenster zu unterstützen, veröffentliche das Deprecation-Datum in den Response-Headern der alten Version, und ändere niemals stillschweigend eine Response-Struktur innerhalb einer Version. Wenn sich die Bedeutung eines Feldes ändern muss, ist das eine neue Version, kein Patch.
Webhooks: Zuverlässigkeit ist das ganze Feature
Ein Webhook-System, das gelegentlich Events verliert, ist schlimmer als gar keine Webhooks, weil Partner Geschäftslogik auf der Annahme aufbauen, dass jedes Event ankommt.
Jede Webhook-Zustellung braucht eine Retry-Policy mit exponentiellem Backoff, denn dass der Endpunkt eines Partners kurz nicht erreichbar ist, ist normal und sollte ihn das Event nicht dauerhaft kosten. Ein vernünftiger Standard sind einige wenige Retries über ein paar Stunden verteilt, dann wird die Zustellung als fehlgeschlagen markiert und in einem Dashboard sichtbar gemacht, das der Partner prüfen kann. Symfony Messengers Retry-Strategie, pro Transport konfiguriert, übernimmt die Backoff-Planung ohne eigene Cron-Jobs.
Signiere jede Payload mit einer HMAC-Signatur, berechnet mit einem partnerspezifischen Secret und als Header neben der Anfrage gesendet. So kann der Partner prüfen, dass eine Anfrage, die vorgibt, dein Webhook zu sein, tatsächlich von dir kam und nicht wiederholt oder gefälscht wurde, und es ist auf beiden Seiten eine zweizeilige Implementierung: du signierst mit hash_hmac('sha256', $payload, $secret), sie verifizieren auf dieselbe Weise.
Mach Zustellungen von Partnerseite aus idempotent, indem du eine eindeutige Event-ID in jede Payload aufnimmst, und ermutige Partner, anhand dieser ID zu deduplizieren, denn Retries werden gelegentlich dazu führen, dass dasselbe Event zweimal zugestellt wird, selbst wenn auf deiner Seite alles korrekt funktioniert hat.
Dokumentation und Observability
Dokumentation ist das, was aus einer technisch korrekten API eine macht, die Integratoren tatsächlich nutzen können, ohne ein Support-Ticket zu öffnen. Die Details, die am meisten zählen, sind die, die generische API-Referenzgeneratoren gerne auslassen: wie ein 429-Response-Body aussieht, was mit einem Webhook passiert, wenn der Endpunkt des Partners einen 500er zurückgibt, und ein durchgerechnetes Beispiel des kompletten Authentifizierungs-Flows mit einem echten (Test-Modus-)Key. Wolf-Tech hat festgestellt, dass Partner-Integrationen spürbar schneller gehen, wenn die Docs kopierbare Request-Beispiele in mindestens zwei Sprachen enthalten, da nicht jeder Partner-Entwickler in PHP arbeitet.
Auf deiner Seite muss Observability pro Partner aufgeschlüsselt werden, nicht nur aggregiert. Verfolge Request-Volumen, Latenz und Fehlerrate segmentiert nach API-Key, denn eine einzelne fehlerhafte Integration, gemittelt über die gesamten API-Metriken, kann sich in einem gesund aussehenden Dashboard verstecken, während sie für einen Partner still versagt. Ein Latenz-Spike, der den Key eines einzelnen Partners betrifft, ist ein ganz anderer Incident als eine plattformweite Verlangsamung, und dein Monitoring sollte die beiden auf einen Blick unterscheiden können.
Das Fundament gleich beim ersten Mal richtig legen
Eine Partner-API ist eine langfristige Verpflichtung. Sobald externe Entwickler dagegen bauen, wird jede Design-Entscheidung, von der Frage, wie Keys begrenzt sind, bis hin zur gewählten Versionierungsstrategie, teuer zu ändern. Wolf-Tech baut und reviewt Partner-APIs für SaaS-Teams im Rahmen von Custom Software Development und prüft bestehende Partner-Integrationen im Rahmen von Code Quality Consulting, wenn eine früh im Produktleben gebaute API mit dem Maßstab mithalten muss, den sie inzwischen bedient.
Wenn dein Team eine Partner-API plant oder eine übernimmt, die langsam in die Jahre kommt, melde dich unter hello@wolf-tech.io oder finde mehr von unseren Engineering-Notizen auf wolf-tech.io.

