Errors
Every error comes with the same JSON body:
{"code": "bbox_too_large", "detail": "bbox sides must be at most 20°"}
| Field | Meaning |
|---|---|
code |
Fixed machine code. It is the contract: new codes may be added, an existing code never changes its meaning. Branch on it |
detail |
Text for humans. It may change; never branch on it, only log it |
errors |
Field validation only (request_invalid, 422): which field was refused and why |
The list of every code, endpoint by endpoint, is generated from the OpenAPI document: Error codes.
Status codes and retries
| HTTP | Meaning | Retry? |
|---|---|---|
| 304 | If-None-Match matched, nothing changed |
No need, use what you have |
| 400–422 | The request or its authentication is wrong | No; fix the request |
| 401, 403 | Key missing, invalid, revoked or out of scope | No (Authentication) |
| 404 | Not found (region, pack, share) | No |
| 409 | State conflict (e.g. a deleted flight) | No |
| 429 | Rate limit or quota | Yes, after Retry-After (Rate limits) |
| 5xx | Temporary server problem | Yes, with exponential back-off; honour Retry-After when present |
Writing endpoints such as the upload are idempotent: repeating a request opens no new record (the same IGC file always gives the same flight_id). You can therefore safely resend after a network error or a 5xx.
Caching and 304
Read endpoints return a strong ETag and Cache-Control: private, max-age=60. Ask the same query with If-None-Match: <etag> and you get 304 when the result did not change. Authentication is checked before the 304.