APIs / Flights
Airports, airlines, two and a half thousand scheduled flights and their bookings — the live-board one.
Fifty real airports, six invented airlines, flights over a two-week window around the seed’s "today" (2026-09-01), and six thousand bookings with passengers and seats. The live stream runs a departures board: flights boarding, departing, delayed and landing. POST a booking and the hub picks a seat. 6,056 records in all.
In Sonda: Import → From a URL with the OpenAPI address and the whole API lands as a project, one request per operation with example bodies. No keys, no headers to add. More on each protocol.
_note and X-Sondahub-Write: simulated. A GET afterwards will not find what you wrote.curl https://api.sondahub.com/v1/flights
Every list answers { "data": [...], "meta": { "page", "limit", "total", "pages" } } with X-Total-Count and Link headers (next, prev, first, last). These options work on every collection and every nested route:
| Option | Meaning | Example |
|---|---|---|
page, limit | Paging, 1-based; limit 1–200, default 20. offset works too. | ?page=3&limit=50 |
sort | Comma list of fields, - for descending. Default id here. | ?sort=-lat,id |
field=value | Equals. Booleans as true/false, null for missing. | ?id=1 |
_ne _gt _gte _lt _lte | Not equal and comparisons, on numbers, dates and strings. | ?lat_gte=10&lat_lt=100 |
_like | Contains, case-insensitive. | ?iata_like=an |
_in | Any of a comma list. | ?id_in=1,2,3 |
_null | true: missing; false: present. | ?city_null=true |
a.b=value | Inside a JSON field, dotted. | ?passenger.first_name=… |
q | Search across the text fields. | ?q=alpine |
fields | Only these fields back. | ?fields=id,iata |
expand | Embed related records. | ?expand=… |
A name that is not a field answers 400 and lists the fields. Writes answer 422 with one line per problem, 404 for a missing id, 405 with an Allow header for a verb a route does not take.
Airports by IATA code. 50 records — the file.
| Field | Type | Notes |
|---|---|---|
idread-only | int | Assigned by the server. Seed records keep their ids across restarts; records you create continue after the seed. |
created_atread-only | datetime | When the record was created (ISO 8601, UTC). |
updated_atread-only | datetime | When the record last changed. |
iatarequired | string | |
namerequired | string | |
city | string | |
country | string | |
timezone | string | |
lat | float | |
lon | float | |
terminals | int |
curl "https://api.sondahub.com/v1/flights/airports?lat_gte=10&limit=3"
curl https://api.sondahub.com/v1/flights/airports/1
curl -X POST https://api.sondahub.com/v1/flights/airports \
-H "Content-Type: application/json" \
-d '{"iata":"MIA","name":"A name","country":"US"}'
curl -X PATCH https://api.sondahub.com/v1/flights/airports/1 \
-H "Content-Type: application/json" \
-d '{"lat":42.5}'
curl -X DELETE https://api.sondahub.com/v1/flights/airports/1
Carriers. 6 records — the file.
| Field | Type | Notes |
|---|---|---|
idread-only | int | Assigned by the server. Seed records keep their ids across restarts; records you create continue after the seed. |
created_atread-only | datetime | When the record was created (ISO 8601, UTC). |
updated_atread-only | datetime | When the record last changed. |
coderequired | string | |
namerequired | string | |
alliance | string | |
fleet_size | int |
Relations: flights → the flights whose airline_id is this airline. Use ?expand=flights to embed them, or the routes below.
curl "https://api.sondahub.com/v1/flights/airlines?fleet_size_gte=1&limit=3"
curl https://api.sondahub.com/v1/flights/airlines/1
curl "https://api.sondahub.com/v1/flights/airlines/1/flights?limit=5"
curl -X POST https://api.sondahub.com/v1/flights/airlines \
-H "Content-Type: application/json" \
-d '{"code":"SH","name":"A name"}'
curl -X PATCH https://api.sondahub.com/v1/flights/airlines/1 \
-H "Content-Type: application/json" \
-d '{"fleet_size":2}'
curl -X DELETE https://api.sondahub.com/v1/flights/airlines/1
A scheduled flight. Times are ISO with the airport’s UTC offset applied, so a departure reads like the board. Filter by route with ?origin=MIA&destination=EZE, by day with ?departure_date=2026-09-02. 2,500 records — the file.
| Field | Type | Notes |
|---|---|---|
idread-only | int | Assigned by the server. Seed records keep their ids across restarts; records you create continue after the seed. |
created_atread-only | datetime | When the record was created (ISO 8601, UTC). |
updated_atread-only | datetime | When the record last changed. |
numberrequired | string | |
airline_idrequired | int → airlines | |
originrequired | string | IATA code. |
destinationrequired | string | |
origin_airport_id | int → airports | |
destination_airport_id | int → airports | |
departure_date | date | Local date at the origin. |
scheduled_departurerequired | datetime | |
scheduled_arrival | datetime | |
estimated_departure | datetime | |
actual_departure | datetime | |
status | enum | scheduled boarding departed in_air landed delayed cancelled diverted |
delay_minutes | int | min 0 |
gate | string | |
terminal | string | |
aircraft | string | |
duration_minutes | int | |
distance_km | int | |
seats_total | int | |
seats_availableread-only | int | |
base_fare | float | USD, economy. |
Relations: airline → one airline through airline_id; origin_airport → one airport through origin_airport_id; destination_airport → one airport through destination_airport_id; bookings → the bookings whose flight_id is this flight. Use ?expand=airline,origin_airport,destination_airport,bookings to embed them, or the routes below.
curl "https://api.sondahub.com/v1/flights/flights?status=boarding&delay_minutes_gte=1&expand=airline&limit=3"
curl https://api.sondahub.com/v1/flights/flights/1?expand=airline
curl "https://api.sondahub.com/v1/flights/flights/1/bookings?limit=5"
curl -X POST https://api.sondahub.com/v1/flights/flights \
-H "Content-Type: application/json" \
-d '{"number":"SH 1042","airline_id":1,"origin":"MIA","destination":"EZE","scheduled_departure":"2026-09-30T12:00:00Z","status":"scheduled","gate":"D14","aircraft":"A321neo"}'
curl -X PATCH https://api.sondahub.com/v1/flights/flights/1 \
-H "Content-Type: application/json" \
-d '{"status":"boarding"}'
curl -X DELETE https://api.sondahub.com/v1/flights/flights/1
A seat on a flight. POST {"flight_id","passenger":{...},"cabin"} and the hub assigns a seat and a record locator. Cancel with PATCH {"status":"cancelled"}. 3,500 records — the file.
passenger.first_name and last_name, refuses cancelled or departed flights and sold-out ones (409), picks a free seat in the cabin when you give none, prices the fare from the flight, and mints a six-character locator. Cancelling gives the seat back.| Field | Type | Notes |
|---|---|---|
idread-only | int | Assigned by the server. Seed records keep their ids across restarts; records you create continue after the seed. |
created_atread-only | datetime | When the record was created (ISO 8601, UTC). |
updated_atread-only | datetime | When the record last changed. |
locatorread-only | string | Six-character record locator, unique. |
flight_idrequired | int → flights | |
passengerrequired | json { first_name, last_name, email, document? } | |
seat | string | Assigned by the hub on POST when omitted. |
cabin | enum | economy premium business first |
status | enum | confirmed checked_in boarded cancelled no_show |
fare | float | min 0 |
currency | string | |
bags | int | min 0, max 5 |
frequent_flyer | string | |
special_requests | json string[] | |
booked_at | datetime | |
checked_in_at | datetime |
Relations: flight → one flight through flight_id. Use ?expand=flight to embed them, or the routes below.
curl "https://api.sondahub.com/v1/flights/bookings?cabin=premium&fare_gte=10&expand=flight&limit=3"
curl https://api.sondahub.com/v1/flights/bookings/1?expand=flight
curl -X POST https://api.sondahub.com/v1/flights/bookings \
-H "Content-Type: application/json" \
-d '{"flight_id":1,"passenger":{"first_name":"Ada","last_name":"Lovelace","email":"[email protected]"},"seat":"14C","cabin":"economy","status":"confirmed"}'
curl -X PATCH https://api.sondahub.com/v1/flights/bookings/1 \
-H "Content-Type: application/json" \
-d '{"cabin":"premium"}'
curl -X DELETE https://api.sondahub.com/v1/flights/bookings/1
The same stream two ways: the world's own activity, one tick a second, generated for your connection alone. Both push JSON text messages; SSE names each one with event: and numbers it with id:. ?topics=a,b narrows either.
| Topic | What arrives | How often |
|---|---|---|
board | The departures board: a flight boarding, departing, delayed, landing or cancelled. | 3 s |
bookings | A seat being booked or checked in on a seed flight. | 6 s |
wss://api.sondahub.com/v1/flights/ws?topics=board
> {"type":"hello","api":"flights","topics":[…],"subscribed":[…]}
> {"type":"event","topic":"board","api":"flights","ts":"…","data":{…}}
< {"type":"subscribe","topics":["board"]} # narrow to some topics
< {"type":"ping"} # → {"type":"pong"}
< anything else # → echoed back as {"type":"echo"}
curl -N "https://api.sondahub.com/v1/flights/events?topics=board"
retry: 3000
id: 1
event: board
data: {"type":"event","topic":"board",…}
One endpoint, https://api.sondahub.com/v1/flights/graphql: POST {"query", "variables"} or GET ?query=. Introspection is on, so Sonda's GraphQL mode loads the schema; the SDL is a click away. Every collection is a paged query with the same filter, sort and q options as REST (operators as suffixes: price_lt), a by-id query, relation fields both ways, and create, update, replace and delete mutations — simulated like every write, with the note in extensions.
curl https://api.sondahub.com/v1/flights/graphql -H "Content-Type: application/json" -d '{"query": "{ flights(limit: 3, sort: \"-id\", filter: { status: scheduled }) { total data { id number airline_id origin airline { code } bookings(limit: 2) { id } } } }"}'
{
flights(limit: 3, sort: "-id", filter: { status: scheduled }) {
total
data {
id number airline_id origin
airline { code }
bookings(limit: 2) { id }
}
}
}