Skip to content

Rate Limits and Retries

OpenAPI limits excessive request frequency to protect service and device communication stability. Clients should not depend on fixed quotas and must handle rate-limit responses correctly.

When a Request Is Limited

A rate-limited request returns:

  • HTTP status 429
  • Error code RATE_LIMITED
  • A Retry-After response header in seconds
  • data.retryAfterSeconds, with the same meaning as Retry-After
  • data.rateLimitScope, identifying the rate-limit bucket rather than an API Client permission

Real-time refresh and device control are protected more strictly than ordinary queries. When changing multiple relays, send them in one relays array instead of splitting them into consecutive requests.

409 DEVICE_BUSY is different from rate limiting: it means that another operation is currently communicating with the device. Wait for that operation to finish and do not retry concurrently. 429 RATE_LIMITED means that requests are too close together or the accumulated quota was exceeded; retry after the delay in the response.

Requests rejected with 429 do not consume additional quota or extend the current window. Service instances using the same API Client share endpoint quotas; continuous concurrent retries can consume the newly available quota immediately after the window resets.

Idempotency-Key

Idempotency-Key is a unique request key generated by the caller for one command request.

Use it when the HTTP connection closes or the client times out before receiving a valid OpenAPI response. If the client cannot determine whether the request was accepted, it can retry the identical request with the same key without creating a duplicate command.

A command object's TIMEOUT status is a terminal result for the original command; it is not an HTTP request timeout. Reusing the same key returns the same commandId and result without sending another device command. Generate a new key only after deciding to perform a new physical operation. For operations with side effects, confirm device state and assess duplicate-execution risk first.

Rules:

  • Generate a new Idempotency-Key for each new command request
  • Reuse the original key when retrying because no definitive OpenAPI response was received
  • Do not reuse a key for another device, command, or request body
  • Idempotency-Key is not an access token and is not used for authentication

Client Handling

  • After 429, retry after the delay in Retry-After or data.retryAfterSeconds
  • After 409 DEVICE_BUSY, wait for the current device operation to finish and retry with backoff
  • For 500 INTERNAL_ERROR, use bounded exponential backoff
  • Retries of commands with side effects must reuse the original Idempotency-Key
  • Coordinate backoff across service instances to avoid another simultaneous burst
  • Except for DEVICE_BUSY, do not retry 400, 401, 403, 404, 409, or 422 without changing the request or credentials

Response Example

http
HTTP/1.1 429 Too Many Requests
Retry-After: 1
json
{
  "code": "RATE_LIMITED",
  "message": "Too many requests",
  "requestId": "req_001",
  "data": {
    "retryAfterSeconds": 1,
    "rateLimitScope": "endpoint",
    "limit": 30,
    "windowSeconds": 60
  }
}

The legacy data.scope field remains temporarily for compatibility. New clients should use data.rateLimitScope. Missing permissions return 403 AUTH_SCOPE_DENIED with data.requiredScope and are unrelated to rate-limit scopes.

Docs buildVersion v1.3.6-20260720-180213-70
Copyright © 2026 WLTE