Skip to main content

Rate Limits

Rate limits protect the API from abuse and ensure fair usage across all tenants. Every endpoint enforces a limit on how many requests a single user can make within a given time window.

Strategies​

The API uses three different rate limiting strategies depending on the endpoint:

Sliding Window​

Used by most endpoints. A sliding window tracks requests over a rolling time period.

  • If the limit is 10 requests per 60 seconds, each request is timestamped.
  • When a new request arrives, the system counts how many requests were made in the last 60 seconds.
  • If the count exceeds the limit, the request is rejected with a 429 status.

This provides a smoother experience compared to fixed windows — there is no "reset cliff" where all capacity is restored at once.

Token Bucket​

Used by the telemetry endpoint for GPS data ingestion. The token bucket allows short bursts while enforcing a sustained rate.

ParameterGlobalPer-IMEI
Bucket capacity180 tokens90 tokens
Refill rate30 tokens/sec15 tokens/sec
Cost1 token per 20 GPS points1 token per 20 GPS points

In practice this means:

  • Sustained throughput: ~600 GPS points/second globally, ~300 points/second per device
  • Burst capacity: up to 3,600 GPS points in a single request (180 tokens × 20 points)
  • A batch of 100 GPS points costs 5 tokens. If the bucket is empty, the request is rejected until tokens refill

Login Brute-Force​

Used exclusively by the login endpoint to prevent credential stuffing attacks.

  • Limit: 5 attempts per 30-second window
  • Block duration: 60 seconds after exceeding the limit
  • During the block period, all login attempts from the same source are rejected immediately
danger

After 5 failed login attempts within 30 seconds, your account is blocked for 60 seconds. There is no way to bypass this block — you must wait for it to expire.

Rate Limit Policies by Endpoint Group​

GroupStrategyLimitWindow
Loginlogin-bruteforce5 attempts30s window, 60s block
Telemetrytoken-bucket180 capacity30 refill/sec
Fleet — Devicessliding-window30 req60 sec
Fleet — Driverssliding-window30 req60 sec
Reports — AVLsliding-window10 req60 sec
Reports — GT Analyticssliding-window10 req60 sec
Reports — GT Operationssliding-window10 req60 sec
Reports — Generalsliding-window10 req60 sec
Reports — CPMsliding-window10 req60 sec
Reports — Portalsliding-window10 req60 sec
Accountssliding-window10 req60 sec
Clientssliding-window10 req60 sec
Workflow (read)sliding-window30 req60 sec
Workflow (write: start/cancel/complete/reassign)sliding-window10 req60 sec
Kanban (read)sliding-window30 req60 sec
Kanban (write)sliding-window10 req60 sec
Supplier Portal (read)sliding-window30 req60 sec
Supplier Portal (write)sliding-window10 req60 sec

Response Headers​

Every API response includes rate limit information in the headers:

HeaderDescriptionPresent on
X-RateLimit-LimitMaximum requests allowed in the current windowAll responses
X-RateLimit-RemainingRequests remaining in the current windowAll responses
X-RateLimit-ResetUnix timestamp (seconds) when the window resetsAll responses
Retry-AfterSeconds to wait before retrying429 responses only
note

The login endpoint is the exception: when it returns a 429, it sends only the Retry-After header and no X-RateLimit-* headers. Every other endpoint includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Reading headers proactively​

Don't wait for a 429 to react — monitor X-RateLimit-Remaining on every response and throttle your requests before hitting the limit:

const response = await fetch(
`https://${TENANT}/apidev/v1/fleet/devices?limit=25`,
{ headers }
);

const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'), 10);
const resetAt = parseInt(response.headers.get('X-RateLimit-Reset'), 10);

if (remaining <= 2) {
const waitMs = (resetAt - Math.floor(Date.now() / 1000)) * 1000;
console.warn(`Rate limit almost exhausted. ${remaining} left. Pausing ${waitMs}ms...`);
await new Promise((resolve) => setTimeout(resolve, waitMs));
}

Handling 429 Responses​

When you receive a 429 Too Many Requests, use the Retry-After header to wait the exact required time. For a full exponential backoff implementation that handles both 429 and 500 errors, see the Retry Strategy in Error Handling.

Quick inline example:

# Check headers on any response
curl -s -D - \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
"https://$TENANT/apidev/v1/fleet/devices?limit=5" \
| grep -i "x-ratelimit\|retry-after"

# X-RateLimit-Limit: 30
# X-RateLimit-Remaining: 28
# X-RateLimit-Reset: 1743782520

Scope and Concurrency​

Rate limits are scoped per tenant, per user. Key rules:

QuestionAnswer
Do different users share a limit?No. Each user has independent limits.
Can I use multiple API keys to bypass limits?No. Limits are tied to the user, not the key.
Can I use multiple user accounts to parallelize?Technically yes, but this is considered abuse and may result in tenant-level throttling. If you need higher throughput, contact your account manager to discuss a custom rate limit plan.
Do read and write operations share a limit?It depends on the group. For most groups, GET and POST/PUT/DELETE share one window. For Workflow, Kanban, and Supplier Portal, reads (30 req/min) and writes (10 req/min) are tracked as separate windows.