Errors & rate limits
Error format
Every non-2xx response uses one envelope:
{
"ok": false,
"error": { "code": "RATE_LIMITED", "message": "…", "details": {} },
"request_id": "a1b2c3d4…"
}
Always include the request_id when contacting support — it lets us find your
exact request.
Status codes
| HTTP | Example code | Meaning |
|---|---|---|
| 400 / 422 | INVALID_REQUEST | Body malformed or a field is out of bounds |
| 401 | AUTH_REQUIRED, KEY_EXPIRED | Missing/invalid/expired key |
| 403 | FORBIDDEN | Key not scoped for this engine |
| 404 | NOT_FOUND | No such resource (e.g. unknown drone key) |
| 409 | IDEMPOTENCY_KEY_CONFLICT | Same idempotency key, different body |
| 413 / 422 | PAYLOAD_TOO_LARGE, PAYLOAD_OVER_LIMIT | Body or payload too large |
| 429 | RATE_LIMITED, QUOTA_EXCEEDED | Too many requests, or quota exhausted |
| 504 | ENGINE_TIMEOUT | Analysis exceeded the 30s deadline |
| 500 | INTERNAL_ERROR | Unexpected server error |
The SDKs raise a typed exception per status (e.g. RateLimitError,
ValidationError, AuthenticationError) carrying code and request_id.
Rate limits
Per-second limits are reported on responses:
X-RateLimit-Limit: 10 # requests/second for your plan
X-RateLimit-Remaining: 7 # tokens left in the burst bucket
X-RateLimit-Reset: 1 # seconds until the bucket refills
Retry-After: 1 # (on 429 only) seconds to wait
Quotas
When your plan has a daily/monthly ceiling, it's reported too:
X-Quota-Monthly-Limit: 50000
X-Quota-Monthly-Remaining: 49993
X-Quota-Monthly-Reset: 1719792000 # epoch seconds at rollover
Retries & idempotency
The SDKs automatically retry 429 and 5xx with backoff that honors
Retry-After. For your own retries on POST, send an Idempotency-Key
header (8–128 chars) so a retried request is processed at most once:
curl https://api.noxdren.com/v1/rangeiq/analyze \
-H "X-API-Key: ndx_..." \
-H "Idempotency-Key: 8f3c…" \
-H "Content-Type: application/json" \
-d '{ "user_lat": 37.5, "user_lon": -122.3, "selected_drone_key": "dji_mavic_3" }'
A replayed key returns the original response (X-Idempotent-Replay: true) and
doesn't consume extra quota.