Skip to main content

Rate limits and quotas

API usage is bounded by your plan. Two limits apply, both set by the tier on your partner account (and, for a sub-account key, the sub-account's tier as well, whichever is lower):

  • Requests per minute: a short-term ceiling on how fast a single key can call the API.
  • Daily request quota: a longer-term cap on total calls per day.

Your exact numbers depend on your plan. Contact your account manager if you need higher limits.

When you hit a limit

A request that exceeds the per-minute rate receives:

HTTP 429 Too Many Requests
Retry-After: 30
{ "error": { "code": "rate_limited", "message": "API rate limit exceeded." } }

Wait for the number of seconds in the Retry-After header before trying again. Responses also carry X-RateLimit-Limit and X-RateLimit-Remaining headers so a well-behaved client can slow down before it hits the wall.

tip

Back off, do not hammer. When you receive a 429, pause and retry after Retry-After seconds. Retrying immediately in a tight loop just keeps you rate-limited.

Poll efficiently with conditional requests

The fastest way to stay within quota is to not ask for data you already have. The latest-value endpoint supports conditional requests:

  1. Call GET /devices/{id}/latest. Read the ETag header from the response and store it.
  2. On your next call, send that value back as If-None-Match.
  3. If nothing has changed, ioX-Pulse replies 304 Not Modified with an empty body.
# First call: capture the ETag
curl -D - -H "Authorization: Bearer $KEY" \
https://portal.example.com/api/v1/devices/0011223344556677/latest
# ... ETag: "e2cb84...d40"

# Next call: revalidate cheaply
curl -H "Authorization: Bearer $KEY" \
-H 'If-None-Match: "e2cb84...d40"' \
https://portal.example.com/api/v1/devices/0011223344556677/latest
# -> HTTP 304 Not Modified

A 304 is small and fast. It still counts as a request, so it does not let you poll infinitely, but it makes a polling loop far lighter than re-fetching the full body every time.

The better answer: do not poll

Conditional requests make polling cheap, but the best pattern for real-time and latest-value data is to not poll at all. Webhook delivery, where ioX-Pulse pushes each event to your endpoint as it arrives, is the recommended approach for those use cases. See the overview for the push-versus-pull guidance.

Conditional requests keep a polled latest value cheap when you cannot use a webhook. Reserve the pull API itself for history, exports, and ad-hoc reads, which is what it is built for.