Rate limits
Hapana applies a leaky-bucket rate limit at the API gateway with two layers — a per-member cap and the endpoint category. Both must allow the request.
Per-member limits
Member API calls are rate-limited per authenticated member, inheriting the parent brand's tier. The tier caps total requests per hour across all endpoints for that member.
| Tier | Requests / hour | Audience |
|---|---|---|
| Basic | 3,600 (60 / min) | Single-location operators; default tier |
| Premium | 36,000 (600 / min) | Multi-location brands |
| Pro | 180,000 (3,000 / min) | White-label partners and high-volume integrations |
Endpoint category limits
Independent of the per-member cap, each endpoint category has its own per-hour limit. This protects expensive endpoints from being starved by cheap ones.
| Category | Requests / hour | Examples |
|---|---|---|
| Read | 1,000 | GET /public-api/v2/member/profile, GET /public-api/v2/member/schedule |
| Write | 200 | POST /public-api/v2/member/bookings, POST /public-api/v2/member/check-in |
Response headers
Every response includes the current bucket state. Cache these — don't recompute on every call.
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Total requests allowed in the current window |
X-RateLimit-Remaining | Requests left in the current window |
X-RateLimit-Reset | Unix epoch seconds when the window resets |
X-RateLimit-Category | Which endpoint category was applied (read, write) |
Retry-After | Seconds to wait before retrying — only present on 429 responses |
When you hit a limit
The API responds with HTTP 429 Too Many Requests and a Retry-After header. Back off, wait the indicated seconds, and retry. Don't retry tighter than Retry-After — successive immediate retries don't reset the bucket and may trigger a longer cooldown at the gateway.
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1745601234
X-RateLimit-Category: readRecommended client behaviour
- Read
X-RateLimit-Remainingon every response and slow down before you hit zero. - On a 429, sleep for
Retry-Afterseconds and retry once. If it 429s again, exponential backoff with jitter. - Cache immutable resources (site details, package definitions) rather than re-fetching on every request — it keeps you well inside your bucket.
