Skip to main content

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

HTTPExample codeMeaning
400 / 422INVALID_REQUESTBody malformed or a field is out of bounds
401AUTH_REQUIRED, KEY_EXPIREDMissing/invalid/expired key
403FORBIDDENKey not scoped for this engine
404NOT_FOUNDNo such resource (e.g. unknown drone key)
409IDEMPOTENCY_KEY_CONFLICTSame idempotency key, different body
413 / 422PAYLOAD_TOO_LARGE, PAYLOAD_OVER_LIMITBody or payload too large
429RATE_LIMITED, QUOTA_EXCEEDEDToo many requests, or quota exhausted
504ENGINE_TIMEOUTAnalysis exceeded the 30s deadline
500INTERNAL_ERRORUnexpected 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.