Overview
This page is the reference for how the autorouter API reports errors, and lists every error — HTTP status code plus, where one exists, a stable machine-readable code — that each endpoint can return. It complements the API overview, which covers the general HTTP status codes used across the whole API.
The error response
When a request fails, the API returns a non-2xx HTTP status code. In most (but not all — see below) cases the response body is a JSON object of the form:
{
"error": "human readable error message",
"code": "STABLE_MACHINE_READABLE_CODE",
"data": null,
"retryable": false
}
- error is a human-readable message intended for display or logging. It is not guaranteed to remain stable between requests or API versions — do not branch your application logic on its exact text.
- code is a stable, machine-readable identifier you can safely branch on in your application (for example
DUPLICATE_FILINGorFILING_VALIDATION_FAILED). Where an endpoint below lists acodefor a given condition, that code is part of the documented, versioned contract. Some endpoints do not yet supply acodefor every error condition; where none is listed, only the HTTP status code is guaranteed andcodewill benull. - data carries optional detail — a list of IFPS errors, what an upstream system answered, the identifiers of a conflicting record. It is
nullwhenever there is nothing further to report, which is the normal case. The contents ofdataare not part of the contract unless the field is marked † below. Unmarked content is diagnostic: its presence, its shape and its field names may change in any release, without notice and without an API version change, and two endpoints returning the samecodemay put different things there. Log it, show it, use it while debugging — but do not branch application logic on it. A field marked † is different: whenever that condition is reported it is present, keeps its name, type and meaning, and will not be removed or repurposed without an API version change. Build on those freely. If you find yourself depending on something unmarked, tell us — we will either mark it or give it a better place. - retryable tells you whether repeating the identical request can succeed. It is
trueonly for momentary infrastructure conditions — an engine restarting, a host briefly at capacity, an upstream system not answering — andfalsewhenever the outcome is a property of the request itself, so that repeating it would fail the same way. Prefer this over inferring retryability from the status code: several conditions return 502 or 503 but are permanent. It is present on every JSON error response.
So the contract is the HTTP status, the code, retryable, and the † fields of data. error is what you put in front of a person, and the rest of data is what you put in a log — those descriptions say what it holds today, not what it will always hold.
A request body sent with a JSON content type is parsed before the request reaches the endpoint. If it is not valid JSON, or is a JSON scalar rather than an object, the API answers 400 with the code INVALID_JSON and quotes the JSON parser’s diagnosis in error. This is reported instead of, not in addition to, the endpoint’s own complaint about a missing field — a body that does not parse carries no fields at all, whatever it appears to contain. Take particular care to escape control characters inside JSON strings: a literal newline in a value, which is easy to introduce by interpolating a text field into a JSON template, makes the entire body unparseable and must be sent as \n.
Retrying
When retryable is true and the status is 503 or 504, the response also carries a Retry-After header giving the number of seconds to wait. Retry with exponential backoff and give up after a few attempts; if a retryable error persists for more than a minute or two, treat it as an outage and open a support ticket rather than continuing to poll.
When retryable is false, repeating the request unchanged is pointless — the request, the flight plan, or the state of the resource has to change first. In particular a routing or parsing failure caused by the flight plan itself (PARSE_FAILED) is never retryable, whereas a failure to reach the engine that would have parsed it (ROUTER_UNREACHABLE, ROUTER_BUSY) always is.
A small number of endpoints — mostly authentication/authorization failures raised by shared middleware — return only the HTTP status code with an empty body, rather than the JSON shape above. This is noted explicitly wherever it applies below. Treat any endpoint that returns 401 or 403 as potentially body-less unless the endpoint’s table says otherwise.
The /oauth2/token endpoint is a deliberate exception: because it implements the OAuth 2.0 specification, its error responses follow the OAuth2 error shape instead of the shape above — see the Authentication section.
HTTP status codes
| Status | Meaning |
|---|---|
| 200 | Request completed successfully. |
| 400 | Invalid request data. Some of the data passed to the call is not valid. |
| 401 | Not authorized. You supplied no credentials, expired credentials, or invalid credentials. Retry with correct credentials. |
| 403 | Access denied. You do not have permission to access the resource or perform the operation. Repeating the request will not help. |
| 404 | Object not found. Most likely an object referenced through the request URL was not found, or could not be accessed due to insufficient privileges. |
| 409 | Conflict. The request could not be completed because it conflicts with the current state of the resource (for example, filing a flight plan that has already been filed). Repeating the request unchanged will not help; the underlying state must change first. |
| 422 | Unprocessable entity. The request was well-formed but failed validation (for example, a flight plan that does not pass IFPS validation or was rejected by Eurocontrol). The response body contains details on what failed. |
| 429 | Too many requests. You have exceeded a rate limit or a plan limit. Wait before retrying. |
| 500 | Internal error processing the request. Please report this along with the scenario that triggered it. |
| 502 | Bad gateway. An upstream system the request depends on (for example Eurocontrol/IFPS, the AFTN gateway) returned an invalid or unexpected response. Do not assume this is temporary — most 502s here are permanent, and retryable is what tells you which one you have. |
| 503 | The server cannot handle the request at this time due to capacity or connectivity issues. Retry later; open a support ticket if this persists. |
| 504 | Gateway timeout. An upstream system the request depends on did not respond in time. The request can be retried. |
Stable error codes
The table below lists every stable code value currently defined, grouped by category, together with the HTTP status it is normally paired with and whether the condition is worth retrying. The Retryable column matches the retryable field of the response body exactly. These are used most extensively by the Flightplans API; a handful are also used by the Routes and Aircraft APIs. Endpoints that reference one of these codes are noted in their section below.
| Code | Status | Retryable | Meaning |
|---|---|---|---|
| Authorization / access | |||
NOT_AUTHORIZED |
403 | no | You are not authorized to perform this operation (for example, no filing privileges, or acting on behalf of a user without delegation). |
FLIGHTPLAN_NOT_FOUND |
404 | no | The referenced flight plan does not exist, or you do not have access to it. |
ROUTE_NOT_FOUND |
404 | no | The referenced route does not exist, or you do not have access to it. |
| Bad request / state | |||
INVALID_JSON |
400 | no | The request body was sent with a JSON content type but is not valid JSON, or is a JSON scalar rather than an object. Can be returned by any endpoint that takes a body; error carries the parser’s diagnosis, for example an unescaped control character inside a string. |
INVALID_BRIEFING |
400 | no | Required briefing information was not supplied when filing. |
INVALID_CUSTOMERREF |
400 | no | The customerref supplied when filing cannot be stored as sent: it is not a string, not valid UTF-8, longer than 64 characters, or contains control characters (a newline, for example). The value is otherwise opaque to us and is stored exactly as sent, which is why an unusable one is refused rather than adjusted. Surrounding whitespace is trimmed, and an empty reference is treated as none at all. |
INVALID_TIME |
400 | no | A supplied time (e.g. departure/arrival time) is invalid. |
EOBT_OUT_OF_RANGE |
400 | no | The requested EOBT is outside the range allowed for the operation. |
PLAN_LIMIT_EXCEEDED |
429 | no | You have reached the maximum number of active flight plans allowed for your account. Waiting does not help — the limit only clears when one of your plans is closed. |
WRONG_STATE |
409 | no | The flight plan is not in a state that allows this operation (for example, sending an arrival message for a plan that is not filed). |
DUPLICATE_FILING |
409 | no | A matching flight plan or route has already been filed/created. Where the duplicate is one we detected ourselves — an AFTN or LVNL filing matching an active plan of yours — data.fplid † is the flight ID of the plan in the way, the same ID the /flightplan/file/{flightid}/… operations take. Where Eurocontrol reports the conflict instead, we look for a live plan of yours matching the flight and include fplid the same way when we find one, but that one is unmarked: the conflict can be a plan filed for the aircraft by somebody else, and Eurocontrol matches a time frame where we match an exact EOBT, so it is not always there. On route creation there is no such id at all. |
ALREADY_CANCELLED |
409 | no | The flight plan was already cancelled (including externally, e.g. by ATC). |
| Validation | |||
VALIDATION_FAILED |
422 | no | The flight plan does not validate under the new parameters (for example, cannot be brought forward to the requested time). |
FILING_VALIDATION_FAILED |
422 | no | The flight plan failed final validation prior to filing. The validator’s output is part of error, one CODE: description per line, and can be shown as it stands; data.ifpserrors currently breaks the same errors up the way an IFPS rejection does, unmarked for now. Filing again with "force": true submits the plan anyway, which may put it into the manual queue at Eurocontrol. |
NOT_IFPS_APPLICABLE |
422 | no | The flight plan does not contain an IFR segment within the Eurocontrol region and cannot be accepted for IFPS filing. |
FILING_REJECTED |
422 | no | Eurocontrol/IFPS rejected the message — the flight plan on filing, or the cancellation, delay, departure or arrival message on the corresponding endpoint. error names every reason IFPS gave, and data.ifpserrors † lists them field by field, see IFPS rejections. |
| Upstream / infrastructure | |||
PARSE_TIMEOUT |
504 | yes | The flight plan parser did not return a result in time. |
PARSE_FAILED |
422 or 502 | no | The flight plan itself could not be parsed — 422 for a structurally invalid plan (e.g. a non-existent airway segment), 502 when the parser accepted it but returned no usable result. Submitting the same plan again gives the same outcome. Where the parser produced structured errors, data carries them as error2, the same structure a successful parse returns them in. This code is never used for a failure to reach the parsing engine; those get ROUTER_UNREACHABLE, ROUTER_BUSY or ROUTER_ERROR. |
EUROCONTROL_ERROR |
502 | no | Eurocontrol/NM B2B returned an invalid, unexpected, or permanently failing response. The NM reply status and its explanation, where NM gave one, are part of error; data repeats them for your log. Please report these — they generally mean something on our side or NM’s needs fixing. |
EUROCONTROL_UNAVAILABLE |
503 | yes | Eurocontrol could not be reached, or reported a momentary condition of its own (SERVICE_UNAVAILABLE, RESOURCE_OVERLOAD, a quota that resets). Nothing was sent — retry shortly, honouring Retry-After. |
AFTN_SEND_FAILED |
502 | no | An AFTN message could not be sent (invalid input, or a permanent gateway failure). |
AFTN_GATEWAY_UNREACHABLE |
503 | yes | The AFTN gateway is temporarily unreachable; nothing was sent. Retry shortly. |
LVNL_SEND_FAILED |
502 | no | A message to LVNL (Dutch ANSP) could not be sent. |
LVNL_PILOT_TEL_MISSING |
422 | no | LVNL requires a pilot telephone number for Dutch VFR departures, and none was supplied on the flight plan. |
REFILE_FAILED |
500 | no | Refiling a modified flight plan failed after the original was already cancelled/changed. |
PERSIST_FAILED |
500 | no | The flight plan was accepted upstream but could not be persisted on our side. |
INTERNAL_ERROR |
500 | no | Generic internal server error. Used when no more specific code applies. |
ROUTER_UNREACHABLE |
503 | yes | The routing or parsing engine could not be reached at all — no engine available, name resolution failure, connection refused, or the connection dropped mid-exchange. Purely an infrastructure condition: there is nothing wrong with your request and the same request will normally succeed once the engine is back. Retry after the interval in Retry-After. |
ROUTER_BUSY |
503 | yes | The routing or parsing engine was reached but is at capacity and refused the work. Retry after the interval in Retry-After. |
ROUTER_TIMEOUT |
504 | yes | The routing engine was reached but did not produce a result in time. |
ROUTER_ERROR |
502 | no | The routing engine returned an unexpected, malformed or invalid response, or rejected what was sent to it. Retrying produces the same result — please report this. |
| Aircraft | |||
AIRCRAFT_CONVERSION_FAILED |
400 | no | The submitted aircraft definition failed validation or could not be converted to the internal format. The error message contains the specific reason. |
Outside of the codes above, most endpoints currently report errors by HTTP status and message only, without a stable code. This is called out per endpoint below.
IFPS rejections
Every message we send to Eurocontrol on behalf of a flight plan — the filing itself, and the cancellation, delay, departure and arrival messages — can be refused by IFPS. That is a property of the request, not an upstream failure: it comes back as 422 with code FILING_REJECTED. The refusal is explained in error, one IFPS code and description per line, and listed field by field in data.ifpserrors †. All five endpoints answer alike:
HTTP 422
{
"error": "Eurocontrol rejected the flight plan:\n(R)PROF204: RS: TRAFFIC VIA LFPT IS ON FORBIDDEN ROUTE",
"code": "FILING_REJECTED",
"data": {
"ifpserrors": [
{"code": "(R)PROF204", "description": "RS: TRAFFIC VIA LFPT IS ON FORBIDDEN ROUTE", "anomalycomment": null}
]
},
"retryable": false
}
ifpserrors † is contractual: it is always present on this code, always a list even when IFPS gave a single reason, and each entry always has a code and a description. The list is empty in the rare case where IFPS refused the message without stating a reason, so handle that rather than assuming a first element. anomalycomment is a free-text remark an IFPS operator may have added and is usually null.
The rest of data is not contractual. On the four endpoints that act on an already filed plan it also names the ifplid the message referred to; filing has none, because nothing was filed.
error is the part to show a pilot: it names every reason IFPS gave, one per line, and needs no assembly — reach for ifpserrors when you want to branch on a specific IFPS code rather than print it.
Two things about IFPS text are worth knowing whichever of the two you read: the code arrives as IFPS writes it, including the severity prefix ((R) for a rejection), and a description may itself contain colons — (R)PROF204: RS: TRAFFIC VIA… above is one code and one description, not two.
Retrying the identical request will be rejected the same way. Depending on the IFPS code, the fix is either to correct the flight plan and file again, or to accept that the flight is in a state that no longer allows the operation (a cancellation for a flight that already departed, for instance).
Errors by API
Authentication
See Authentication via OAuth 2.0 for the full authentication flow. POST /oauth2/token follows the OAuth 2.0 error response shape instead of the standard shape:
{
"error": "invalid_grant",
"error_description": "human readable description"
}
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
POST /oauth2/token |
403 | ratelimited |
Too many failed login attempts; try again later. |
| 403 | validated |
Account needs to be validated. | |
| 403 | activated |
Account has not yet been activated by an administrator. | |
| 403 | privileges |
Account does not have API access privileges (client-credentials grant). | |
| 403 | toomanytokens |
Too many active access tokens outstanding for this account. | |
| 403 | — | Incorrect password, or unknown client/account (standard OAuth2 invalid_client/invalid_grant). |
|
| 400 | — | Malformed token request per the OAuth2 spec (invalid_request, unsupported_grant_type, invalid_scope). |
|
GET /oauth2/authorize |
401 | — | Not authenticated. No response body. |
Every endpoint above that requires a session or bearer token can additionally fail before reaching the handler with:
- 401 — no credentials supplied, or credentials invalid/expired.
- 403 — credentials valid but insufficient privilege for the operation.
These two are raised by shared authentication middleware ahead of every protected endpoint in the API (not just this section) and currently return an empty body — status code only, no JSON, no code.
Aircraft
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
POST /aircraft, PUT /aircraft/{id} |
400 | — | Missing/invalid callsign, manufacturer, model, year, ICAO type, or MTOM. |
| 404 | — | (PUT) Aircraft not found, or not owned by you. | |
| 400 | AIRCRAFT_CONVERSION_FAILED |
Aircraft definition could not be converted. The error message contains the specific reason (e.g. unknown manufacturer, invalid massunitname, invalid propulsion type). | |
| 409 | — | An aircraft with this registration and model already exists. | |
| 500 | INTERNAL_ERROR |
A database error occurred while saving the aircraft. | |
GET /aircraft/{id}, DELETE /aircraft/{id} |
404 | — | Aircraft not found, deleted, or not accessible to you. |
GET /aircraft |
400 | — | Missing pagination parameters. |
PUT /aircraft/{id}/default |
404 | — | Your account record could not be found (does not validate that {id} is a real aircraft). |
GET /aircraft/{id}/performance, POST /aircraft/performance |
400 / 404 | AIRCRAFT_CONVERSION_FAILED / — |
Aircraft not found/accessible (404), or the submitted aircraft definition is invalid (400 with AIRCRAFT_CONVERSION_FAILED). |
| 502 / 503 / 504 | ROUTER_ERROR / ROUTER_UNREACHABLE / ROUTER_TIMEOUT |
The router returned an unexpected reply (502, ROUTER_ERROR, permanent), could not be reached (503, ROUTER_UNREACHABLE, retry) or did not complete the performance computation in time (504, ROUTER_TIMEOUT, retry). |
|
PUT /aircraft/{id}/defaultloading |
404 / 500 | — / INTERNAL_ERROR |
Aircraft not found/accessible, or its stored definition is corrupt. |
Routes
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
POST /router |
400 | — | Invalid optimization target, aircraft definition, or missing/malformed departure, destination, or alternate. |
| 404 | — | Referenced aircraft not found or not accessible. | |
| 422 | PARSE_FAILED |
Departure, destination, and departure time could not all be derived from the supplied flight plan text. Note that the cause is not always the text itself — a supplied aircraft the parser cannot build a profile from fails the same way, and error2 in data says which part the parser objected to. Not retryable: the request has to change. |
|
| 502 / 503 / 504 | ROUTER_ERROR / ROUTER_UNREACHABLE / ROUTER_BUSY / PARSE_TIMEOUT |
Deriving those fields needs the parsing engine, which could not be reached or is at capacity (503, retry), did not answer in time (504, retry), or answered with something unusable (502, permanent). Unlike PARSE_FAILED this says nothing about your flight plan. |
|
| 403 | NOT_AUTHORIZED |
Not authorized to create a route on behalf of the given user. | |
| 409 | DUPLICATE_FILING |
A route with the generated id already exists. | |
PUT /router/hide, PUT /router/{routeid}/hide |
404 | — | Route id not found, or not owned by you. |
PUT /router/{routeid} |
400 | — | Flight plan missing, or the update failed (route id not found or not owned by you — both conditions currently return the same 400). |
PUT /router/{routeid}/longpoll, /stop, /close |
404 | — | Route id not found, or you may not drive its routing session. Delegates need route_create on the authorizer’s account, which they have for any route they requested on its behalf. |
Apart from that 404, PUT /router/{routeid}/longpoll, /stop, and /close respond 200; a routing-engine-side failure is reported as an error field inside the 200 response body rather than as an HTTP error status. Inspect the body on these three endpoints even on success. Alongside error the body carries transient: true means the engine was momentarily unavailable and you should keep polling, since the routing session survives and resumes once the engine is back; false means the failure is permanent and polling should stop.
Flightplans
This is the one part of the API with consistent, stable error codes end to end — see the code table above for what each one means.
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
POST /flightplan/file/{routeid} (file a flight plan) |
403 | NOT_AUTHORIZED |
No filing privileges. |
| 429 | PLAN_LIMIT_EXCEEDED |
Maximum number of active flight plans exceeded. The allowance belongs to the account the plan is filed into, so when a delegate files on somebody’s behalf it is that account’s open plans that count, not the delegate’s. | |
| 400 | INVALID_BRIEFING |
Briefing information missing. | |
| 400 | INVALID_CUSTOMERREF |
The optional customerref in the request body cannot be stored as sent. Raised before the flight plan is submitted anywhere, so a refusal never leaves a plan filed. |
|
| 404 | ROUTE_NOT_FOUND |
Route could not be accessed. | |
| 404 | FLIGHTPLAN_NOT_FOUND |
Refile only (flightid and eobt given in the body): the flight plan being refiled does not exist, or you may not file into the account that owns it. Filing on somebody else’s behalf needs fpl_file or fpl_delaybringforward on their account. |
|
| 504 | PARSE_TIMEOUT |
Flight plan parser poll limit exceeded. | |
| 502 | PARSE_FAILED |
Flight plan parsing failed or returned an unexpected result. Not retryable — the plan has to change. | |
| 502 / 503 | ROUTER_ERROR / ROUTER_UNREACHABLE / ROUTER_BUSY |
The parsing engine could not be reached or is at capacity (503, retry), or answered with something unusable (502, permanent). Distinct from PARSE_FAILED: nothing is wrong with the flight plan. |
|
| 422 | NOT_IFPS_APPLICABLE |
No IFR segment within the Eurocontrol region. | |
| 422 | FILING_VALIDATION_FAILED |
Final validation before filing failed. error carries the validation detail; refile with "force": true to submit anyway. |
|
| 422 | LVNL_PILOT_TEL_MISSING |
Pilot phone number required for Dutch VFR departure. | |
| 502 | EUROCONTROL_ERROR |
Eurocontrol/NM B2B returned an invalid or permanently failing response. | |
| 503 | EUROCONTROL_UNAVAILABLE |
Eurocontrol is temporarily unavailable; nothing was filed. Retry shortly. | |
| 409 | DUPLICATE_FILING |
A matching flight plan — same aircraft, aerodromes and EOBT — is already active. On an AFTN or LVNL filing this is our own check, since neither gateway detects duplicates itself, and data.fplid † is the flight ID of the plan in the way — the same ID the /flightplan/file/{flightid}/… operations take, so a client can cancel or delay it directly. On an NM B2B filing the refusal is Eurocontrol’s own; error then quotes the reason Eurocontrol gave, and data names the blocking plan the same way whenever we can identify one of yours as the cause — unmarked, because we cannot always. Cancelling that plan, or moving its EOBT, clears the condition either way. data also carries the plan’s created timestamp and, where it has one, its customerref. |
|
| 409 | DUPLICATE_FILING |
You already have another active flight plan carrying the same customerref. Unlike the previous condition this check runs for every filing method, including NM B2B, and cannot be skipped with skipduplicatecheck — a customerref is expected to identify one flight for you. data.fplid † is the flight ID of the plan already carrying that reference. Cancel or delay that plan, or file this one with a different reference, to clear the condition. |
|
| 422 | FILING_REJECTED |
IFPS rejected the flight plan. error names the IFPS error codes, see IFPS rejections. |
|
| 500 | PERSIST_FAILED |
Filing succeeded upstream but could not be persisted. | |
| 502 | LVNL_SEND_FAILED |
Sending the LVNL flight plan message failed. | |
| 502 | AFTN_SEND_FAILED |
AFTN filing message could not be sent (permanent failure). | |
| 503 | AFTN_GATEWAY_UNREACHABLE |
AFTN gateway temporarily unreachable; nothing was sent. | |
POST /flightplan/file/{flightid}/cancel |
400 | No reason supplied in the request body. |
|
| 403 | NOT_AUTHORIZED |
No privilege to cancel flight plans. | |
| 404 | FLIGHTPLAN_NOT_FOUND |
Flight plan not found or not accessible. | |
| 409 | ALREADY_CANCELLED |
Flight plan was already cancelled externally. | |
| 422 | FILING_REJECTED |
IFPS refused the cancellation message, typically because the flight is no longer in a state that can be cancelled. error names the IFPS error codes, see IFPS rejections. |
|
| 502 | EUROCONTROL_ERROR |
Eurocontrol returned an error status, or a filing status we cannot act on. | |
| 503 | EUROCONTROL_UNAVAILABLE |
Eurocontrol could not be reached or is temporarily unavailable; the cancellation was not sent. Retry shortly. | |
| 502 | LVNL_SEND_FAILED |
Sending the LVNL cancellation failed. | |
| 502 / 503 | AFTN_SEND_FAILED / AFTN_GATEWAY_UNREACHABLE |
AFTN cancellation message could not be sent. | |
POST /flightplan/file/{flightid}/delay |
403 | NOT_AUTHORIZED |
No privilege to delay flight plans. |
| 404 | FLIGHTPLAN_NOT_FOUND |
Flight plan not found or not accessible. | |
| 400 | EOBT_OUT_OF_RANGE |
New EOBT outside the valid range: it must always be in the future, for flight plans filed through Eurocontrol (NM B2B) no more than 5 days ahead, and for flight plans filed through AFTN or LVNL it must fall on the same UTC day as the current EOBT (the DLA message carries a time but no date). | |
| 504 | PARSE_TIMEOUT |
Re-parse poll limit exceeded. | |
| 502 | PARSE_FAILED |
Re-parsing the flight plan failed. Not retryable — the plan has to change. | |
| 502 / 503 | ROUTER_ERROR / ROUTER_UNREACHABLE / ROUTER_BUSY |
The parsing engine could not be reached or is at capacity (503, retry), or answered with something unusable (502, permanent). Distinct from PARSE_FAILED: nothing is wrong with the flight plan. |
|
| 409 | ALREADY_CANCELLED |
Flight plan was already cancelled externally. | |
| 422 | FILING_REJECTED |
IFPS refused the delay message. error names the IFPS error codes, see IFPS rejections. |
|
| 502 | EUROCONTROL_ERROR |
Eurocontrol returned an error status, or a filing status we cannot act on. | |
| 503 | EUROCONTROL_UNAVAILABLE |
Eurocontrol could not be reached or is temporarily unavailable; the delay was not sent. Retry shortly. | |
| 502 / 503 | LVNL_SEND_FAILED / AFTN_SEND_FAILED / AFTN_GATEWAY_UNREACHABLE |
Sending the delay message failed. | |
POST /flightplan/file/{flightid}/bringforward |
403 | NOT_AUTHORIZED |
No privilege to modify flight plans. |
| 400 | EOBT_OUT_OF_RANGE |
New EOBT outside the valid range. | |
| 404 | FLIGHTPLAN_NOT_FOUND |
Flight plan not found or not accessible. | |
| 504 | PARSE_TIMEOUT |
Re-parse poll limit exceeded. | |
| 502 | PARSE_FAILED |
Re-parsing the flight plan failed. Not retryable — the plan has to change. | |
| 502 / 503 | ROUTER_ERROR / ROUTER_UNREACHABLE / ROUTER_BUSY |
The parsing engine could not be reached or is at capacity (503, retry), or answered with something unusable (502, permanent). Distinct from PARSE_FAILED: nothing is wrong with the flight plan. |
|
| 422 | VALIDATION_FAILED |
Flight plan does not validate at the earlier time. | |
| 409 | ALREADY_CANCELLED |
Flight plan was already cancelled externally. Nothing was changed, and the plan is now marked cancelled here too. | |
| 422 | FILING_REJECTED |
IFPS refused the cancellation message that starts the refile. Nothing was changed. error names the IFPS error codes, see IFPS rejections. |
|
| 502 | EUROCONTROL_ERROR |
Eurocontrol returned an error status, or a filing status we cannot act on, while cancelling. Nothing was changed. | |
| 503 | EUROCONTROL_UNAVAILABLE |
Eurocontrol could not be reached or is temporarily unavailable; the cancellation was not sent and nothing was changed. Retry shortly. | |
| 502 / 503 | LVNL_SEND_FAILED / AFTN_SEND_FAILED / AFTN_GATEWAY_UNREACHABLE |
Sending the cancellation message that starts the refile failed. Nothing was changed. | |
| 500 | REFILE_FAILED |
The original plan was cancelled but the modified plan could not be filed. The original is gone — create a new flight plan. Every failure before this point leaves the original plan untouched and keeps its own status and code. | |
POST /flightplan/file/{flightid}/departure, POST /flightplan/file/{flightid}/arrival |
404 | FLIGHTPLAN_NOT_FOUND |
Flight plan not found or not accessible. |
| 409 | WRONG_STATE |
Flight plan is not in filed state (departure) / is closed (arrival). | |
| 400 | INVALID_TIME |
Invalid departure/arrival time. | |
| 422 | FILING_REJECTED |
IFPS refused the departure or arrival message, for example a DEP for a flight that already departed. error names the IFPS error codes, see IFPS rejections. |
|
| 502 | EUROCONTROL_ERROR |
Eurocontrol returned an error status, or a filing status we cannot act on. | |
| 503 | EUROCONTROL_UNAVAILABLE |
Eurocontrol could not be reached or is temporarily unavailable; the message was not sent. Retry shortly. | |
PUT /flightplan/fpal/verify |
500 | — | Verification could not be run. |
GET /flightplan/fpal/{id} |
400 | — | Invalid document id. |
| 404 | — | Document not found. |
GET /flightplan (parse), GET /flightplan/validate, GET /flightplan/file, and GET /flightplan/file/{flightid} do not raise HTTP-level errors for business-logic failures. GET /flightplan and GET /flightplan/convert do report infrastructure failures, though: 503 with ROUTER_UNREACHABLE when no parsing engine can be reached, 503 with ROUTER_BUSY when the engine is at capacity, 504 with PARSE_TIMEOUT when it does not answer in time, and 502 with ROUTER_ERROR when it answers with something unusable. Only the last of these is permanent.
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
GET /navdata/airport |
400 | — | No search parameters supplied. |
Weather
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
GET /met/gramet |
400 | — | Invalid format, or neither a flight plan nor a waypoint list supplied. |
| 503 | ROUTER_UNREACHABLE / ROUTER_BUSY |
The chart engine could not be reached, is at capacity, or the computed chart could not be fetched back off the host. Retry after the interval in Retry-After. |
|
| 504 | ROUTER_TIMEOUT |
Chart generation did not complete in time. Retryable. | |
| 502 | ROUTER_ERROR |
The engine returned an unexpected reply, or no chart at all, for this input. Not retryable. |
GET /met/metartaf/{icao} responds 200 with metar/taf set to null for an unknown or data-less station rather than a 404 — there is currently no way to distinguish “no data yet” from “invalid station” via the status code. GET /met/modeldate likewise always responds 200, with null if the timestamp could not be determined.
Briefing
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
POST /flightplan/file/{flightid}/briefing, POST /flightplan/{routeid}/briefing (generate a briefing pack) |
400 | — | method or items missing, or method is not one of email/telegram/download. |
| 403 | — | A briefing pack is already being generated for you. | |
| 404 | — | Flight plan/route not found. | |
| 500 | — | The briefing pack could not be queued or generated. | |
GET .../briefing (fetch/generate, blocking) |
404 / 500 | — | Flight plan/route not found, or generation timed out/failed. |
GET .../briefing/{token} (poll/download) |
404 / 500 | — | Not ready yet (404), or generation failed (500). No response body on either. |
Documents
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
GET /pams/id/{docid} |
404 | — | Document id is not numeric or not found, or the file is missing on disk. |
GET /pams/airport/{icao}/package |
404 | — | Invalid ICAO, unknown airport, or no plates available to build a package. |
POST /pams/airport |
400 | — | Request body is not an array, or is not JSON (see note below). |
GET /pams[/{authority}[/{language}[/{aiptype}[/{section}]]]] |
400 | — | A path segment is supplied without the segment(s) before it (e.g. language without authority). |
GET /pams/airport/{icao}/POST /pams/airport respond 200 with an empty list for a malformed airport code rather than an error. A non-JSON request body on POST /pams/airport returns a plain 400 with no response body, rather than the standard JSON error shape.
NOTAMs
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
GET /notam |
400 | — | An itema entry is not a valid 4-character ICAO location indicator pattern. |
Messages
| Endpoint | Status | Code | When it happens |
|---|---|---|---|
GET /message |
400 | — | Invalid timeout (must be 0–300) or limit (must be 1–100). |
POST /message/acknowledge, POST /message/{id}/acknowledge |
400 | — | An id in the request is not a valid non-negative integer. |
Acknowledging an id that doesn’t exist, or that belongs to another user, is currently a silent no-op (200), not an error. GET /message/count has no error conditions.
Every request — regardless of API — is first checked against the requested API version; a missing or unsupported version returns a bodiless 400 before your request reaches any endpoint. See Versioning.
