{
  "openapi": "3.1.0",
  "info": {
    "title": "OSPIPO fixed-fare quote API",
    "version": "2026-10-28",
    "summary": "Fixed private transfer fares and free pickup times, read-only, no authentication.",
    "description": "OSPIPO is a NSW-licensed premium airport transfer service (Booking Service Provider BSP-462516). This API returns the published fixed fare for any trip in the service area and the times that are free on a date — the same engine as the booking form on https://ospipo.com.au, Ospi and the MCP connector. Service area: Sydney Airport (SYD, T1 International and T2/T3 Domestic), Western Sydney International Airport (WSI), the Sydney CBD and every Greater Sydney suburb; the Illawarra and the NSW South Coast to Jervis Bay, St Georges Basin and Sussex Inlet; the Southern Highlands; the Blue Mountains and the Central West to Bathurst and Orange; the Central Coast, Lake Macquarie, Newcastle, Port Stephens, Maitland and the Hunter Valley; Canberra and Queanbeyan — within about 250 km of Sydney Airport. Fares are fixed and all-inclusive (motorway tolls, GST and the NSW Point to Point levy), per car for up to 4 passengers, with no surge at any hour. Payment is in advance by a secure payment link after OSPIPO confirms; cancellation before pickup is free, with a full refund. A return is both legs less 10%, rounded to the nearest five dollars. To book, use the MCP connector (https://ospipo.com.au/mcp), the booking form at https://ospipo.com.au/ or WhatsApp +61 435 162 311. Plain-text facts for AI assistants: https://ospipo.com.au/llms.txt",
    "contact": {
      "name": "OSPIPO",
      "email": "bookings@ospipo.com.au",
      "url": "https://ospipo.com.au/contact"
    },
    "termsOfService": "https://ospipo.com.au/terms"
  },
  "servers": [
    {
      "url": "https://ospipo.com.au"
    }
  ],
  "paths": {
    "/api/quote": {
      "get": {
        "operationId": "quoteFare",
        "summary": "The fixed fare for a private transfer",
        "description": "Pass a pickup and a drop-off as place names or addresses (\"Kiama NSW\", \"Sydney Airport T1\", \"Western Sydney International Airport\", \"Sydney CBD\", \"Castle Hill NSW\"). A route outside the service area returns ok=false with outside_service_area=true; a trip with both ends far from Sydney returns a rule ending in _on_request — OSPIPO confirms that price directly. Never estimate a fare yourself.",
        "parameters": [
          {
            "name": "pickup",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Kiama NSW"
          },
          {
            "name": "dropoff",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Sydney Airport"
          },
          {
            "name": "trip_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "one_way",
                "return"
              ],
              "default": "one_way"
            }
          },
          {
            "name": "wait_hours",
            "in": "query",
            "required": false,
            "description": "Return trips only: the driver waits on standby at the destination, whole hours",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 5
            }
          },
          {
            "name": "distance_km",
            "in": "query",
            "required": false,
            "description": "Road distance, only for an address the engine cannot place by name",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Priced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "description": "pickup and dropoff are required"
          },
          "422": {
            "description": "Not priced: outside the service area, priced on request, or the address was not matched",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          }
        }
      }
    },
    "/api/availability": {
      "get": {
        "operationId": "checkAvailability",
        "summary": "Free pickup times on a date (Sydney time)",
        "description": "With date only: the blocked ranges and the 15-minute slots for that day. With date and time (or date_time): whether that pickup time is free and the next free time. Bookings need at least 3 hours' notice. No personal data is returned.",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-11-20"
          },
          {
            "name": "time",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{2}:\\d{2}$"
            },
            "example": "05:30"
          },
          {
            "name": "date_time",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Availability",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Pass ?date=YYYY-MM-DD"
          }
        }
      }
    },
    "/api/plan": {
      "get": {
        "operationId": "planPickup",
        "summary": "Pickup time for a departing flight (Ospi)",
        "description": "OSPIPO's published rule (the same as Ospi on the website and plan_pickup in the MCP connector): at the terminal 90 minutes before a domestic flight with checked bags (Jetstar 100), 1 hour with hand luggage only, 3 hours international, never before the terminal opens (T1 3:00am, T2/T3 4:00am); minus the drive, 10 minutes to load and the weekday-peak allowance; rounded down to the quarter hour. With flight_date: whether that pickup slot is free for the whole trip (and the nearest earlier free times). Also the fixed fare. No personal data in or out.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Kiama"
          },
          {
            "name": "airport",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "SYD",
                "WSI"
              ]
            },
            "description": "Sydney Airport (default) or Western Sydney International"
          },
          {
            "name": "flight_date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-11-20"
          },
          {
            "name": "flight_time",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{2}:\\d{2}$"
            },
            "example": "06:00"
          },
          {
            "name": "airline",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "qantas, virgin, jetstar, another airline, or a flight number (QF400)"
          },
          {
            "name": "international",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "checked_bags",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "false for hand luggage only"
          }
        ],
        "responses": {
          "200": {
            "description": "plan (pickup_time, pickup12, pickup_date, at_terminal12, terminal, steps), slot, fare, summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "422": {
            "description": "Outside the service area, or the place or time could not be read"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Quote": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "true when the route is priced"
          },
          "route": {
            "type": "string",
            "description": "The route as priced, e.g. \"Kiama → Sydney Airport\""
          },
          "trip_type": {
            "type": "string",
            "enum": [
              "one_way",
              "return"
            ]
          },
          "total_aud": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The fixed fare to pay, AUD (the return total for a return)"
          },
          "one_way_fare_aud": {
            "type": [
              "integer",
              "null"
            ]
          },
          "return_leg_fare_aud": {
            "type": [
              "integer",
              "null"
            ]
          },
          "return_breakdown": {
            "type": [
              "string",
              "null"
            ]
          },
          "wait_hours": {
            "type": "integer"
          },
          "wait_aud": {
            "type": "integer"
          },
          "approx_km": {
            "type": [
              "number",
              "null"
            ]
          },
          "pricing_rule": {
            "type": [
              "string",
              "null"
            ],
            "description": "Which published rule set the fare (fixed fare, formula, on request ...)"
          },
          "currency": {
            "type": "string",
            "const": "AUD"
          },
          "includes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "payment": {
            "type": "string"
          },
          "outside_service_area": {
            "type": "boolean"
          },
          "note": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "currency"
        ]
      }
    }
  },
  "externalDocs": {
    "description": "Book inside an AI assistant: the OSPIPO MCP connector",
    "url": "https://ospipo.com.au/mcp"
  }
}
