{
  "openapi": "3.1.0",
  "info": {
    "title": "Flight API — Historical flight status API",
    "version": "1.0",
    "description": "Query any past flight by number and date. Actual departure and arrival times, block time, aircraft and delay minutes — one REST endpoint, one settled record.\n\nAll timestamps are ISO 8601 with a Z offset in UTC. Every response is JSON carrying a boolean `success` discriminator, with `data` on success and `message` on failure.",
    "contact": {
      "name": "Flight API",
      "url": "https://flight-api.dev/docs"
    },
    "license": {
      "name": "Commercial",
      "url": "https://flight-api.dev/terms"
    }
  },
  "servers": [
    {
      "url": "https://flight-api.dev"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyHeader": []
    }
  ],
  "tags": [
    {
      "name": "Flights",
      "description": "Historical flight resolution."
    },
    {
      "name": "Operations",
      "description": "Credential inspection and liveness."
    }
  ],
  "paths": {
    "/api/v1/flights/status": {
      "get": {
        "operationId": "flightStatus",
        "summary": "Resolve a historical flight",
        "description": "Resolves one flight on one date and returns the selected record. Settled disruptions are replayed from storage.",
        "tags": [
          "Flights"
        ],
        "responses": {
          "200": {
            "description": "Resolved. `data.selected` may still be null when the flight was not found.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlightStatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Query validation failed. `message` names the offending field.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "No active plan on the account, or the subscription is canceled or past due. No credit is taken.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key or account disabled.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Request allowance for the current window is exhausted and overage is not enabled. No credit is taken.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Resolve failed. Safe to retry.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "flightNumber",
            "in": "query",
            "required": true,
            "description": "IATA flight designator. Trimmed and upper-cased server-side. Aliases: flight, number.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 12
            }
          },
          {
            "name": "flightDate",
            "in": "query",
            "required": true,
            "description": "Scheduled departure date in UTC. A full ISO timestamp is truncated to the date. Aliases: date.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "origin",
            "in": "query",
            "required": false,
            "description": "Disambiguates codeshares and repeated flight numbers. Aliases: originIata, from.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{3}$"
            }
          },
          {
            "name": "destination",
            "in": "query",
            "required": false,
            "description": "Disambiguates codeshares and repeated flight numbers. Aliases: destinationIata, dest, to.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{3}$"
            }
          },
          {
            "name": "refresh",
            "in": "query",
            "required": false,
            "description": "Skip the persisted record and resolve the flight again from scratch.",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "0",
                "true",
                "false",
                "yes",
                "no"
              ]
            }
          },
          {
            "name": "screenshot",
            "in": "query",
            "required": false,
            "description": "Attach a rendered proof image of the record as base64. Never persisted. Aliases: includeScreenshot.",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "0",
                "true",
                "false",
                "yes",
                "no"
              ]
            }
          }
        ]
      }
    },
    "/api/v1/account": {
      "get": {
        "operationId": "account",
        "summary": "Inspect the calling key",
        "description": "Returns the account and key behind the supplied credential, its lifetime request count and the credit position for the current window. Unmetered — this call costs nothing.",
        "tags": [
          "Flights"
        ],
        "responses": {
          "200": {
            "description": "Key is valid.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "No active plan, or the subscription is canceled or past due.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key or account disabled.",
            "headers": {
              "X-Credits-Included": {
                "description": "Requests included in the current window. `unlimited` on internal accounts.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Used": {
                "description": "Requests consumed so far in the current window, including this one.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Remaining": {
                "description": "Requests left before the ceiling. Reaches zero one request before a 429.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Overage": {
                "description": "Requests taken beyond the included allowance. Zero unless overage is enabled.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Credits-Period-End": {
                "description": "When the current window closes and the allowance resets.",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "health",
        "summary": "Liveness probe",
        "description": "Unauthenticated. Returns immediately.",
        "tags": [
          "Operations"
        ],
        "responses": {
          "200": {
            "description": "Service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key prefixed `flt_`, sent as `Authorization: Bearer`."
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "An API key prefixed `flt_`."
      }
    },
    "schemas": {
      "FlightStatusResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "data": {
            "type": "object",
            "properties": {
              "flightNumber": {
                "type": "string",
                "description": "Echoed back, normalised to upper case."
              },
              "flightDate": {
                "type": "string",
                "description": "Echoed back as `YYYY-MM-DD`."
              },
              "originIata": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Resolved departure airport."
              },
              "destinationIata": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Resolved arrival airport."
              },
              "selected": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The normalised record. Null when nothing was found.",
                "properties": {
                  "found": {
                    "type": "boolean",
                    "description": "The flight was matched."
                  },
                  "complete": {
                    "type": "boolean",
                    "description": "Enough timings were present to settle the record."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "delayed",
                      "cancelled",
                      "diverted",
                      "on_time",
                      "not_found"
                    ],
                    "description": "Classified outcome."
                  },
                  "isDelayed": {
                    "type": "boolean",
                    "description": "Arrival delay greater than zero."
                  },
                  "isCancelled": {
                    "type": "boolean",
                    "description": "Flight never operated."
                  },
                  "isDiverted": {
                    "type": "boolean",
                    "description": "Landed somewhere other than the destination."
                  },
                  "delayMinutes": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Arrival delay in minutes."
                  },
                  "departureDelayMinutes": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Departure delay in minutes."
                  },
                  "scheduledDeparture": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "scheduledArrival": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "estimatedDeparture": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "estimatedArrival": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "actualDeparture": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "actualArrival": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "airline": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "`name`, `iata`, `icao`."
                  },
                  "aircraft": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "`registration`, `iata`, `icao`, `icao24`, `label`."
                  },
                  "flightIata": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Normalised IATA designator."
                  },
                  "flightIcao": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Normalised ICAO designator."
                  },
                  "statusRaw": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Raw status string, unmodified."
                  }
                }
              },
              "flightDelay": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Delay and disruption verdict with its rationale, when timings were available."
              },
              "meta": {
                "type": "object",
                "description": "Timing, cache and persistence state.",
                "properties": {
                  "durationMs": {
                    "type": "number",
                    "description": "Wall clock for the whole resolve. `0` on a cache hit."
                  },
                  "startedAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "finishedAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "ISO 8601, UTC."
                  },
                  "cached": {
                    "type": "boolean",
                    "description": "Served from the persisted record instead of a live resolve."
                  },
                  "persisted": {
                    "type": "boolean",
                    "description": "This response was written to the record table."
                  },
                  "recordId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Always null on the public endpoint."
                  }
                }
              }
            }
          }
        }
      },
      "AccountResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "data": {
            "type": "object",
            "properties": {
              "accountId": {
                "type": "string"
              },
              "accountSlug": {
                "type": "string"
              },
              "keyId": {
                "type": "string"
              },
              "keyName": {
                "type": "string"
              },
              "keyPrefix": {
                "type": "string"
              },
              "unlimited": {
                "type": "boolean"
              },
              "requestCount": {
                "type": "integer"
              },
              "credits": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Credit position for the current window. Null on unmetered internal accounts.",
                "properties": {
                  "included": {
                    "type": "integer"
                  },
                  "used": {
                    "type": "integer"
                  },
                  "remaining": {
                    "type": "integer"
                  },
                  "overage": {
                    "type": "integer"
                  },
                  "periodEnd": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "service": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "properties": {
          "success": {
            "const": false
          },
          "message": {
            "type": "string",
            "description": "Human-readable failure reason."
          }
        }
      }
    }
  }
}