Rate limiting
Endpoints that act on behalf of visitors are rate limited per IP address. Read endpoints are not, but should be cached.
Loupe applies rate limits to protect the actions visitors take, such as booking a room or writing to the library, from abuse. Read endpoints have no fixed quota today. That is not an invitation to poll: we may introduce limits as usage grows, and well-behaved integrations will not notice them.
Limited endpoints
Limits use a token bucket per client IP address. Each bucket starts full and refills at a constant rate; a request spends one token, and an empty bucket answers 429.
| Action | Endpoint | Burst | Refill |
|---|---|---|---|
| Create a reservation | POST /api/public/bookables/{id}/reservation | 10 | 1 per minute |
| Start a conversation | POST /api/public/threads/start | 5 | 1 every 12 minutes |
| Reply to a conversation | POST /api/public/threads/reply | 10 | 1 every 6 minutes |
| Catalogue item details | POST /api/public/ils/items | 120 | 60 per minute |
| Sign in | POST /api/authentication/login (failed attempts) | 5 | 1 every 10 minutes |
Because limits are per IP address, a server that relays many visitors' bookings through one address shares a single bucket. If your integration creates reservations or registrations on behalf of many people, talk to us first.
Handling 429
A limited request returns 429 Too Many Requests. Some endpoints add a Retry-After header with the number of seconds to wait; respect it when present. Otherwise, back off exponentially, starting at a few seconds. There are no X-RateLimit-* headers.
Avoiding limits
Cache what changes rarely
Organization profiles, pages, rooms and map definitions change a few times a day at most. Cache them for minutes, not seconds. For maps, send the ETag back in If-None-Match: an unchanged map costs a 304 and no download.
Poll sparingly
Loupe does not send webhooks yet. If you mirror events or reservations, refresh on a schedule (every few minutes is plenty) and only fetch the pages you need, using filters such as date ranges.
Fetch less
Ask for one organization, one date range, one bookable. Use the item endpoint (/item?slug=…) instead of downloading a whole collection to find one entry.