Rate limits
Two windows, both counted per key: requests per minute, and requests per UTC day. Both are charged on every request, so staying under the minute limit all day still spends the daily allowance.
The windows
| Tier | Per minute | Per UTC day | Max rows |
|---|---|---|---|
| Trial | 30 | 1,000 | 25 |
| Live | 60 | 10,000 | 50 |
| Partner | 600 | 250,000 | 200 |
The daily window rolls over at 00:00 UTC, not in your timezone. “Max rows” is the cap on limit; a larger value is clamped rather than refused.
Headers
Every served response carries where the minute window stands. The daily window is reported alongside it under its own names, because one set of headers cannot describe two windows and nobody has standardised a second.
- X-RateLimit-Limitinteger
- Requests allowed in the current minute.
- X-RateLimit-Remaininginteger
- Left in the current minute.
- X-RateLimit-Resetinteger
- Seconds until the minute rolls over.
- X-RateLimit-Daily-Limitinteger
- Requests allowed today.
- X-RateLimit-Daily-Remaininginteger
- Left today.
- Retry-Afterinteger
- Seconds to wait. Sent only with a
429, and it is the one number to back off on — seconds until the minute rolls over for a minute-window refusal, seconds until UTC midnight for a daily one.
The rate-limit headers are omitted entirely when loso’s limiter cannot be reached. Absent rather than zero or guessed: an unknown remaining count has no honest integer, and a wrong one ends up in somebody’s backoff logic. Treat a missing header as no information, not as a limit of zero.
Handling a 429
A refusal names the window it belongs to, which is the difference between “slow down” and “come back tomorrow”. Retrying a daily refusal on a short backoff burns the rest of the day against a counter that will not move.
{ "detail": "Over the per-minute limit of 60 requests." }# curl honours Retry-After with --retry; cap the wait so a daily
# refusal does not block the shell until midnight.
curl "https://api.locally-social.com/api/v1/events?city=Charlotte&state=NC" \
-H "Authorization: Bearer $LOSO_API_KEY" \
--retry 3 --retry-max-time 120Staying under
Three things that cost nothing and change the arithmetic:
- Ask for full pageslimit
limitdefaults to 25. Raising it to the tier cap cuts the request count for the same rows by half or more.- Poll with updated_sincetimestamp
- Re-reading a city every hour costs a full walk;
updated_sincenarrows it to rows that changed. Read its caveats in the reference before relying on it as your only sync. - Separate noisy jobskeys
- Limits are per key. A backfill on its own key cannot throttle the request path serving your users.