Rate Limits
Mosler's APIs are designed for the request volumes of real hospitality operations — bulk check-ins, channel-manager bursts, and end-of-day reconciliation. To keep the platform responsive for everyone, requests are subject to fair-use limits, and well-behaved clients should be built to handle being throttled gracefully.
This page documents the contract your integration should code against. Specific numeric thresholds are tuned per company and per endpoint and may change; never hard-code a fixed limit. Build against the
429signal instead.
The 429 contract
When a client exceeds its allowance, Mosler responds with HTTP 429 Too Many Requests instead of processing the call. A 429 is not an error in your payload — the request was well-formed; it simply arrived too fast. The correct response is to wait and retry, not to change the request.
When present, a Retry-After header tells you how long to wait before retrying:
| Header | Meaning |
|---|---|
Retry-After | Seconds to wait before the next attempt (HTTP-standard). |
If no Retry-After is present, fall back to exponential backoff (below).
Handling 429 correctly
Implement exponential backoff with jitter. Honour Retry-After when given; otherwise double the delay each attempt and add a small random offset so a fleet of clients doesn't retry in lockstep.
async function callWithBackoff(doRequest, { maxRetries = 5 } = {}) {
let attempt = 0;
for (;;) {
const res = await doRequest();
if (res.status !== 429) return res;
if (attempt >= maxRetries) {
throw new Error('Rate limit retries exhausted');
}
// Honour Retry-After if the server sent it, else back off exponentially.
const retryAfter = Number(res.headers.get('retry-after'));
const base =
Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000
: Math.min(1000 * 2 ** attempt, 30000);
const jitter = Math.random() * 250;
await new Promise((r) => setTimeout(r, base + jitter));
attempt++;
}
}
Designing to stay under the limit
The most reliable way to avoid 429s is to not generate unnecessary traffic in the first place:
- Prefer callbacks over polling. If you subscribe to access callbacks, you don't need to poll event status in a tight loop. Push beats pull at scale.
- If you must poll, poll slowly. A booking that's
QUEUEDwon't becomeCOMPLETEDin 50 ms. Poll on the order of seconds, with backoff, and stop once you reach a terminal status. - Batch your reads. Use the paginated list-events endpoint with a sensible
pageSizerather than fetching one event at a time. - Spread bulk operations. When importing a day's reservations, pace the writes instead of firing thousands of requests in one burst.
- Reuse connections. Keep-alive avoids per-request TLS overhead and smooths throughput.
What counts against you
Limits are applied per API key. Because keys are company-scoped, one company's traffic never consumes another's allowance. If you run several integrations under separate keys, each has its own budget — which is another reason to use one key per integration.
When you need more headroom
If your legitimate volume is consistently bumping the limit — a large portfolio onboarding, a migration, or a seasonal spike — reach out to your Mosler contact rather than working around it with parallel keys. Limits can be raised for known, trusted workloads.