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.

ActionEndpointBurstRefill
Create a reservationPOST /api/public/bookables/{id}/reservation101 per minute
Start a conversationPOST /api/public/threads/start51 every 12 minutes
Reply to a conversationPOST /api/public/threads/reply101 every 6 minutes
Catalogue item detailsPOST /api/public/ils/items12060 per minute
Sign inPOST /api/authentication/login (failed attempts)51 every 10 minutes

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.