Event Connectors

Rate Limits & Fair Use

The per-IP rate limit on the collection endpoints, the 429 + Retry-After contract, the X-RateLimit headers, and how a well-behaved client should respond

To keep the API responsive for everyone, the expensive list/search endpoints are rate-limited per client IP at the edge. The limit is generous — a normal integration paging through data at a sane cadence will never hit it — and it exists only to stop a single source from overwhelming the search surface.

Most integrations never see a 429. If yours does, it is almost always a tight loop that should be paginating, caching reference data, or spreading its requests out — see Responding correctly.

What is limited

The limit applies to the root collection / search endpoints:

GET /events, GET /locations, GET /routes, GET /eventgroups, GET /venues, and GET /dictionary.

Not limited:

  • Asset/image requests (/api/assets/*) — cached and safe to fetch in volume (but see self-hosting images).
  • Detail reads by id, such as GET /events/{id} — cheap single-item lookups.
  • Health checks (/actuator/health).

The policy

ScopePer client IP ($binary_remote_addr at the edge)
Sustained rate20 requests/second
Burst40 requests absorbed above the sustained rate
On exceed429 Too Many Requests + a Retry-After header

The exact policy is echoed on responses from the limited endpoints:

HTTP/1.1 200 OK
X-RateLimit-Limit: 20
X-RateLimit-Policy: 20;w=1;burst=40
  • X-RateLimit-Limit — the sustained per-second limit.
  • X-RateLimit-Policy — the full policy in RateLimit header style: 20;w=1 (20 requests per 1-second window) with burst=40.

There is no live X-RateLimit-Remaining count. The headers above are static and describe the policy, not your current remaining budget. Do not try to parse a remaining count from them — instead, back off when you receive a 429, using Retry-After.

The 429 response

When you exceed the limit, the request is rejected with 429 (not 503 — this is throttling, not an outage) and a Retry-After telling you how long to wait, in seconds:

HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-RateLimit-Limit: 20
X-RateLimit-Policy: 20;w=1;burst=40

Responding correctly

A well-behaved client treats 429 as normal backpressure, not an error:

  1. Respect Retry-After. On a 429, wait the number of seconds it gives before retrying — ideally with exponential backoff and jitter if you keep getting throttled. Never hot-loop retries.
  2. Paginate instead of over-fetching. Pull data in pages of size ≤ 2000 rather than hammering the list endpoint — see Paginate a Result Set.
  3. Sync incrementally. If you keep your own datastore in step, poll only what changed with an incremental lastupdated sync at a 5–15 minute cadence, rather than re-listing everything continuously.
  4. Cache reference data. The dictionary/ontology endpoints change on the order of weeks — fetch them once and cache, don't re-request them on every run.
  5. Spread load. Avoid firing all your requests in one tight burst at the top of the minute; a steady trickle stays comfortably under the limit.

Following the incremental sync and pagination recipes keeps you well within the limit by design.

See the API Reference for the full endpoint list.

On this page