{
  "openapi": "3.1.0",
  "info": {
    "title": "AwardSecrets Award Availability API",
    "version": "1.0.0",
    "description": "Live business/first/economy AWARD (points/miles) seat availability from global airline inventory via GDS. Returns real, bookable award space that consumer airline websites and scraper-based tools often miss.\n\nIMPORTANT — this is a LITERAL search: each call checks exactly ONE origin airport, ONE destination airport, ONE airline, and ONE date. It does NOT accept lists, ranges, or vague inputs. If the user is flexible (multiple airports, a date range, 'any airline', 'sometime in August'), you must resolve to ONE concrete value for each field and make SEPARATE calls — one per combination — then aggregate the results yourself. Do not attempt to pass comma-separated values, arrays, or month names; they will be rejected.\n\nThe response contains facts only (carrier, flight number, route, times, cabin, seat count). It does NOT include pricing or mileage cost.",
    "contact": {
      "name": "AwardSecrets",
      "url": "https://awardsecrets.com"
    }
  },
  "servers": [
    {
      "url": "https://awardsecrets.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api.php": {
      "post": {
        "operationId": "searchAwardAvailability",
        "summary": "Search award seat availability for one route, one airline, one date",
        "description": "Returns available AWARD seats (redeemable with points/miles) for a SINGLE origin, SINGLE destination, SINGLE airline, and SINGLE date. Use the 2-letter IATA airline code (e.g. VS=Virgin Atlantic, CX=Cathay Pacific, QR=Qatar, JL=Japan Airlines, IB=Iberia, NH=ANA, AF=Air France). For flexible searches, call this once per concrete (origin, destination, airline, date) combination. Each call consumes one unit of the API key's quota.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search completed (may or may not have found seats; check the 'found' field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters (e.g. a field was missing, malformed, or contained multiple values instead of one).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "API key quota exhausted. No more calls available until the balance is topped up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "API key is not permitted to use this product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed; use POST."
          },
          "502": {
            "description": "Upstream search backend error (the quota unit is automatically refunded)."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Provide your API key as: Authorization: Bearer ak_live_xxxxx"
      }
    },
    "schemas": {
      "SearchRequest": {
        "type": "object",
        "required": ["origin", "destination", "airline", "date"],
        "additionalProperties": false,
        "properties": {
          "origin": {
            "type": "string",
            "pattern": "^[A-Za-z]{3}$",
            "description": "ONE origin airport, as a 3-letter IATA code (e.g. 'JFK'). Exactly one airport — not a list, not a city name, not a region.",
            "examples": ["JFK"]
          },
          "destination": {
            "type": "string",
            "pattern": "^[A-Za-z]{3}$",
            "description": "ONE destination airport, as a 3-letter IATA code (e.g. 'LHR'). Exactly one airport.",
            "examples": ["LHR"]
          },
          "airline": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{2}$",
            "description": "ONE airline, as a 2-letter IATA code (e.g. 'VS' for Virgin Atlantic, 'CX' Cathay Pacific, 'QR' Qatar Airways, 'JL' Japan Airlines, 'IB' Iberia, 'NH' ANA, 'AF' Air France). Exactly one airline — not a list, not an alliance, not 'any'. To check multiple airlines, make multiple calls.",
            "examples": ["VS"]
          },
          "date": {
            "type": "string",
            "format": "date",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
            "description": "ONE departure date in YYYY-MM-DD format (e.g. '2026-08-05'). Exactly one date — not a range, not a month name. To check multiple dates, make multiple calls.",
            "examples": ["2026-08-05"]
          },
          "cabin": {
            "type": "string",
            "enum": ["business", "first", "economy"],
            "default": "business",
            "description": "Cabin to search. Defaults to 'business' if omitted.",
            "examples": ["business"]
          },
          "passengers": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9,
            "default": 1,
            "description": "Number of seats needed (1-9). Defaults to 1.",
            "examples": [1]
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok"],
            "description": "'ok' on a completed search."
          },
          "trace_id": {
            "type": "string",
            "description": "Unique request id (for support/debugging)."
          },
          "quota_remaining": {
            "type": "integer",
            "description": "API calls left on this key after this request."
          },
          "query": {
            "type": "object",
            "description": "Echo of the resolved search parameters.",
            "properties": {
              "origin": { "type": "string" },
              "destination": { "type": "string" },
              "airline": { "type": "string" },
              "date": { "type": "string" },
              "cabin": { "type": "string" },
              "passengers": { "type": "integer" }
            }
          },
          "found": {
            "type": "boolean",
            "description": "True if any award seats were found."
          },
          "flight_count": {
            "type": "integer",
            "description": "Total number of flight segments returned."
          },
          "dates": {
            "type": "array",
            "description": "Results grouped by date (one entry for a literal single-date search).",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "description": "The searched date (YYYY-MM-DD)."
                },
                "flights": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Flight"
                  }
                }
              }
            }
          }
        }
      },
      "Flight": {
        "type": "object",
        "description": "One flight segment with available award space. Facts only — no pricing, no fare codes.",
        "properties": {
          "carrier": {
            "type": "string",
            "description": "Marketing carrier (2-letter IATA code), e.g. 'VS'."
          },
          "flight_number": {
            "type": "string",
            "description": "Full flight number, e.g. 'VS4'."
          },
          "operated_by": {
            "type": ["string", "null"],
            "description": "Operating carrier if different from the marketing carrier (codeshare), e.g. 'DL'. Null if operated by the marketing carrier."
          },
          "origin": {
            "type": "string",
            "description": "Segment origin airport (IATA). May differ from the requested origin when a nearby co-terminal airport had availability."
          },
          "destination": {
            "type": "string",
            "description": "Segment destination airport (IATA). On a connection, intermediate segments show the connecting points."
          },
          "depart": {
            "type": "string",
            "description": "Departure datetime, ISO 8601 local time (e.g. '2026-08-05T18:00')."
          },
          "arrive": {
            "type": "string",
            "description": "Arrival datetime, ISO 8601 local time (e.g. '2026-08-06T06:20')."
          },
          "equipment": {
            "type": "string",
            "description": "Aircraft equipment code (e.g. '351' = A350-1000)."
          },
          "cabin": {
            "type": "string",
            "enum": ["business", "first", "economy", "premium_economy"],
            "description": "Cabin of the available award space."
          },
          "seats": {
            "type": "integer",
            "description": "Number of award seats available in this cabin on this segment."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["error"]
          },
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          },
          "trace_id": {
            "type": ["string", "null"],
            "description": "Request id, when available."
          }
        }
      }
    }
  }
}
