Grundlagen
Rate-Limits
Jeder Schlüssel darf standardmäßig 120 Anfragen je 60-Sekunden-Fenster senden. Jede Antwort zeigt, wie viel vom Fenster übrig ist.
Standard und Stufe je Schlüssel
Das Standardlimit beträgt 120 Anfragen pro Minute und Schlüssel. Braucht eine Integration mehr, stellt STRYK auf Anfrage eine andere Stufe für diesen Schlüssel ein; das Hotel sieht sie in Kanäle → API beim Schlüssel, kann sie dort aber nicht ändern. Die gültige Stufe liefern GET /me (rateLimit.limit) und der Header RateLimit-Limit jeder Antwort. Bei einer Rotation übernimmt der neue Schlüssel die Stufe.
Header
| Header | Bedeutung |
|---|---|
RateLimit-Limit | Anfragen je Fenster für diesen Schlüssel, standardmäßig 120 |
RateLimit-Remaining | Verbleibende Anfragen im aktuellen Fenster |
RateLimit-Reset | Sekunden bis zum Ende des Fensters |
Retry-After | Nur bei 429: Sekunden bis zur nächsten Anfrage |
HTTP/1.1 200 OK
Content-Type: application/json
RateLimit-Limit: 120
RateLimit-Remaining: 87
RateLimit-Reset: 23
X-Request-Id: 3c2b1a09-f8e7-4d6c-b5a4-938271605f4e
Cache-Control: no-storeHTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
RateLimit-Limit: 120
RateLimit-Remaining: 0
RateLimit-Reset: 17
Retry-After: 17Backoff
Bei 429 wartest du Retry-After Sekunden. Bei 5xx oder Netzwerkfehlern wartest du mit exponentiellem Backoff und Jitter. Wiederhole Schreibzugriffe mit demselben Idempotency-Key.
// Retries 429 and 5xx with Retry-After or exponential backoff plus jitter.
export async function fetchWithRetry(url, options, maxAttempts = 5) {
for (let attempt = 1; ; attempt += 1) {
const response = await fetch(url, options);
const retryable = response.status === 429 || response.status >= 500;
if (!retryable || attempt === maxAttempts) return response;
const retryAfter = Number(response.headers.get('Retry-After'));
const backoff = Math.min(30, 2 ** attempt) + Math.random();
await new Promise((resolve) => setTimeout(resolve, (retryAfter > 0 ? retryAfter : backoff) * 1000));
// POST/PATCH: send the same Idempotency-Key again, so a retry cannot create a duplicate.
}
}import random
import time
import requests
def request_with_retry(method, url, max_attempts=5, **kwargs):
for attempt in range(1, max_attempts + 1):
response = requests.request(method, url, timeout=30, **kwargs)
retryable = response.status_code == 429 or response.status_code >= 500
if not retryable or attempt == max_attempts:
return response
retry_after = response.headers.get("Retry-After", "")
delay = int(retry_after) if retry_after.isdigit() else min(30, 2 ** attempt) + random.random()
time.sleep(delay) # keep the same Idempotency-Key header on POST/PATCHUnter dem Limit bleiben
limit=200undupdated_sinceverwenden, statt alles neu zu lesen.- Kategorien, Raten und Hotelprofil cachen; sie ändern sich selten.
- Webhooks statt Polling einzelner Buchungen nutzen.
- Zeitgesteuerte Jobs verteilen, nicht alle zur vollen Minute starten.
- Einen Schlüssel je Integration verwenden. Schlüssel teilen sich kein Fenster, aber mehrere Schlüssel für ein System erschweren die Fehlersuche.
Wiederholte Anfragen mit ungültigen Schlüsseln werden je IP-Adresse gebremst, unabhängig von diesen Grenzen.