Concepts
Rate limits
By default each key may send 120 requests per 60-second window. Every response tells you how much of the window is left.
Default and per-key tier
The default limit is 120 requests per minute per key. If an integration needs more, STRYK sets a different tier for that key on request; the hotel sees it with the key in Channels → API but cannot change it there. GET /me (rateLimit.limit) and the RateLimit-Limit header of every response return the tier in force. A rotated key keeps the tier.
Headers
| Header | Meaning |
|---|---|
RateLimit-Limit | Requests per window for this key, 120 by default |
RateLimit-Remaining | Requests left in the current window |
RateLimit-Reset | Seconds until the window ends |
Retry-After | Only on 429: seconds to wait before the next request |
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
On 429, wait Retry-After seconds. On 5xx or network errors, wait with exponential backoff and jitter. Repeat writes with the same 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/PATCHStaying within the limit
- Use
limit=200andupdated_sinceinstead of reading everything again. - Cache room types, rate plans and the hotel profile; they change rarely.
- Use webhooks instead of polling single bookings.
- Spread scheduled jobs; do not start all of them at minute zero.
- Use one key per integration. Keys do not share a window, but several keys for one system make problems harder to trace.
Repeated requests with invalid keys are slowed down per IP address, independent of these limits.