Skip to main content
Most error responses follow this shape:
Sometimes additional fields are included for context for example unknown_vocabulary errors include valid_values so you can correct the value without reading docs. Validation errors from Pydantic (unknown body keys, wrong types) follow FastAPI’s standard 422 shape. Branch on error_code, surface message to humans, log the rest.

Two exceptions to the envelope shape

Some endpoints return a plain string in detail rather than the { error_code, message } object. Today this applies to:
  1. 404 Not Found on the by-id endpoints (GET /teardowns/{id}, PATCH /teardowns/{id}, DELETE /teardowns/{id}, and the matching /sales-lease-exchange/{id} routes). The body is literally:
    or:
    There is no error_code or message field branch on the HTTP status 404 instead.
  2. 400 from the transition endpoint when the state-machine rejects a move (e.g. trying to complete a teardown that is still in active_starting). The body is a plain string from the state-machine layer:
    Same pattern: no error_code, branch on the 400 status and the action you sent.
For everything else listed in the table below, the { error_code, message, ... } envelope is the rule.

Quick remediation matrix

Detailed explanations

We return this same code whether the key doesn’t exist, was revoked, or matched a fingerprint but failed status checks. The single response prevents an attacker from probing the keyspace.From your side: if you minted the key recently and it suddenly stops working, the most likely cause is that the minter was deactivated (which auto-revokes their keys within an hour, but the 401 starts immediately). Less likely: the key was rotated by another org admin.
The API key already implies an org. Sending a different org id in X-Organization-Id is, by construction, never a legitimate user error either the wrong value got pasted into your ERP config, or something more interesting is happening. We alert on every occurrence.Fix: re-paste the Organization ID from the Settings → API Access page where you minted the key.
Two different switches:
  • api_access_disabled: API access was turned off for your org specifically. Has nothing to do with billing.
  • subscription_required: your subscription is past_due / canceled / expired / not yet active. Resolve billing.
Both can be true at once. If both checks would fail, the subscription one fires first.
The full list of valid values is in the response body under valid_values:
Match is case-insensitive a320-200 and A320-200 both work. Whitespace at the edges is stripped.
The status field accepts exactly three values:
  • Starting
  • In process
  • Completed
Case-sensitive. starting, in progress, STARTING all return 422. We picked strict matching so the OpenAPI docs show the three values as a real enum IDE autocomplete and linters can see them.
Validation errors from the schema layer use FastAPI’s standard 422 shape. Example for an unknown body key:
loc tells you exactly which key was bad. Common offenders: registration (use tail_number), location_country (use country), estimated_teardown_date (use start_date), aircraft_type_id (use the name, not the UUID).
The response includes a Retry-After header in seconds. Wait at least that long before retrying. Exponential backoff on top is good practice the limit window resets gradually.If you’re hitting bucket A (the 600 req/min per-key limit) regularly, your ERP is probably retrying too aggressively. Mint a second key for batch jobs that need their own budget.
500 is an unexpected server-side bug. 502 storage_unavailable is a Supabase Storage upstream issue.For both: retry the request with backoff. If it persists for more than a minute, capture the request id (returned in the x-request-id response header) and email support@teardowns.aero with the id + a description.

What we don’t return

A few common shapes you might expect that the API deliberately doesn’t use:
  • Plain text errors. Every error has a structured JSON body. No bare strings. No HTML pages.
  • Different shapes for different error families. The shape is always { "detail": { "error_code", "message", ...optional fields } } (for business errors) or FastAPI’s default 422 shape (for schema errors).
  • success: true/false envelopes. Successes return the resource directly. Branch on HTTP status, not a wrapper field.