{
  "openapi": "3.0.3",
  "info": {
    "title": "Skyloom Travel — Partner API",
    "version": "1.0.0",
    "description": "Search flights and create bookings end-to-end against a prepaid balance held with Skyloom. Booking, payment and ticketing happen on skyloomtravel.uk. See API_DOC.md for the full guide. Internal pricing/ticketing mechanics are not part of this contract."
  },
  "servers": [
    { "url": "https://skyloomtravel.uk/api/v1", "description": "Production" }
  ],
  "security": [ { "bearerAuth": [] } ],
  "tags": [
    { "name": "auth" },
    { "name": "flights" }
  ],
  "paths": {
    "/ping": {
      "post": {
        "tags": ["auth"],
        "summary": "Verify your key",
        "responses": {
          "200": {
            "description": "Key is valid",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "boolean", "example": true },
                "message": { "type": "string", "example": "pong" },
                "data": { "type": "object", "properties": {
                  "partner": { "type": "string" },
                  "partner_id": { "type": "integer" },
                  "can_book": { "type": "boolean" }
                } }
              }
            } } }
          },
          "401": { "$ref": "#/components/responses/AuthError" }
        }
      }
    },
    "/flights/search": {
      "post": {
        "tags": ["flights"],
        "summary": "Search flights",
        "requestBody": {
          "required": true,
          "content": { "application/x-www-form-urlencoded": { "schema": {
            "type": "object",
            "required": ["origin", "destination", "departure_date", "adults"],
            "properties": {
              "origin": { "type": "string", "example": "IST", "description": "IATA code" },
              "destination": { "type": "string", "example": "ASB", "description": "IATA code" },
              "departure_date": { "type": "string", "format": "date", "example": "2026-07-15" },
              "type": { "type": "string", "enum": ["oneway", "round"], "default": "oneway" },
              "return_date": { "type": "string", "format": "date", "description": "Required when type=round" },
              "adults": { "type": "integer", "minimum": 1, "example": 1 },
              "children": { "type": "integer", "default": 0 },
              "infants": { "type": "integer", "default": 0 },
              "currency": { "type": "string", "default": "USD", "enum": ["USD", "EUR", "GBP"], "example": "USD", "description": "Offer prices are returned in this currency. Supported: USD, EUR, GBP (others rejected with INVALID_PARAMS). Ask Skyloom to enable more." },
              "class_type": { "type": "string", "enum": ["economy", "business", "first"], "default": "economy" }
            }
          } } }
        },
        "responses": {
          "200": {
            "description": "Offers (array for oneway; {outbound,return} for round) or NO_RESULTS",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "boolean" },
                "message": { "type": "string" },
                "data": {
                  "oneOf": [
                    { "type": "array", "items": { "$ref": "#/components/schemas/Offer" } },
                    { "type": "object", "properties": {
                      "outbound": { "type": "array", "items": { "$ref": "#/components/schemas/Offer" } },
                      "return": { "type": "array", "items": { "$ref": "#/components/schemas/Offer" } }
                    } }
                  ]
                }
              }
            } } }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/AuthError" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/flights/book": {
      "post": {
        "tags": ["flights"],
        "summary": "Create a booking for an offer",
        "requestBody": {
          "required": true,
          "content": { "application/x-www-form-urlencoded": { "schema": {
            "type": "object",
            "required": ["offer_id", "passengers"],
            "properties": {
              "offer_id": { "type": "string", "description": "From a recent search (valid 30 min)", "example": "OFR-46d2eadfb2-IST-ASB" },
              "passengers": { "type": "string", "description": "JSON array of passenger objects (type, title, first_name, last_name, dob, gender, nationality, passport_number, passport_expiry). At least one adult.", "example": "[{\"type\":\"adult\",\"title\":\"Mr\",\"first_name\":\"John\",\"last_name\":\"Doe\",\"dob\":\"1990-05-20\",\"gender\":\"M\",\"nationality\":\"GB\",\"passport_number\":\"123456789\",\"passport_expiry\":\"2031-01-01\"}]" },
              "contact_email": { "type": "string", "format": "email" },
              "contact_phone": { "type": "string" },
              "contact_first_name": { "type": "string" },
              "contact_last_name": { "type": "string" },
              "issue_ticket": { "type": "string", "enum": ["0", "1"], "default": "1", "description": "1 issues the ticket immediately; 0 holds the PNR without ticketing" }
            }
          } } }
        },
        "responses": {
          "200": {
            "description": "Booking created",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "boolean" },
                "message": { "type": "string" },
                "data": { "$ref": "#/components/schemas/BookingState" }
              }
            } } }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/AuthError" },
          "402": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/AuthError" },
          "410": { "$ref": "#/components/responses/Error" },
          "502": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/flights/booking/{booking_ref_no}": {
      "get": {
        "tags": ["flights"],
        "summary": "Booking status",
        "parameters": [
          { "name": "booking_ref_no", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Booking status",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "boolean" },
                "message": { "type": "string" },
                "data": { "$ref": "#/components/schemas/BookingState" }
              }
            } } }
          },
          "401": { "$ref": "#/components/responses/AuthError" },
          "404": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "description": "Authorization: Bearer <your API key>" }
    },
    "responses": {
      "Error": {
        "description": "Error envelope",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "AuthError": {
        "description": "Authentication error",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "status": { "type": "boolean", "example": false },
          "error": { "type": "object", "properties": {
            "code": { "type": "string", "enum": ["AUTH_MISSING_KEY", "AUTH_INVALID_KEY", "INVALID_PARAMS", "NO_RESULTS", "OFFER_EXPIRED", "INSUFFICIENT_DEPOSIT", "RATE_LIMIT", "SUPPLIER_TIMEOUT", "SUPPLIER_ERROR"] },
            "message": { "type": "string" }
          } }
        }
      },
      "Fare": {
        "type": "object",
        "properties": {
          "base_fare": { "type": "number" },
          "taxes": { "type": "number" },
          "surcharges": { "type": "number" },
          "service_fee": { "type": "number" },
          "markup": { "type": "number", "description": "Always 0.00 (contract field)" },
          "total": { "type": "number" },
          "currency": { "type": "string" },
          "per_passenger": { "type": "object", "properties": {
            "adult": { "type": "number" }, "child": { "type": "number" }, "infant": { "type": "number" }
          } },
          "tax_breakdown": { "type": "array", "items": { "type": "object" } }
        }
      },
      "Segment": {
        "type": "object",
        "properties": {
          "origin": { "type": "string" },
          "destination": { "type": "string" },
          "departure": { "type": "string" },
          "arrival": { "type": "string" },
          "duration_minutes": { "type": "integer" },
          "airline": { "type": "string" },
          "flight_number": { "type": "string" },
          "aircraft": { "type": "string" },
          "cabin_class": { "type": "string" },
          "baggage_allowance": { "type": "string" }
        }
      },
      "Offer": {
        "type": "object",
        "properties": {
          "offer_id": { "type": "string", "description": "Valid 30 minutes; pass to /flights/book" },
          "supplier": { "type": "string" },
          "airline": { "type": "string" },
          "flight_number": { "type": "string" },
          "class_type": { "type": "string" },
          "available_seats": { "type": "integer" },
          "fare": { "$ref": "#/components/schemas/Fare" },
          "segments": { "type": "array", "items": { "$ref": "#/components/schemas/Segment" } },
          "booking_url": { "type": "string" }
        }
      },
      "BookingState": {
        "type": "object",
        "properties": {
          "booking_ref_no": { "type": "string" },
          "pnr": { "type": "string", "nullable": true },
          "ticket_number": { "type": "string", "nullable": true },
          "status": { "type": "string", "enum": ["ticketed", "ticketing_pending", "held", "cancelled", "pending"] },
          "payment_status": { "type": "string" },
          "total": { "type": "number" },
          "currency": { "type": "string" },
          "booked_at": { "type": "string" }
        }
      }
    }
  }
}
