Travel trade
Sell African Wings flights in your platform
Our partner API gives tour operators, DMCs and booking platforms such as TripsNStay live prices and bookings for private charters, whale watching and scenic flights, and empty legs across Southern Africa.
Getting started
- Email safari@africanwings.co.za to agree commercial terms and commission.
- We send your API key and webhook secret privately.
- Call
GET /pingto check the key, thenGET /productsto load airports, aircraft and flights.
Base URL: https://www.africanwings.co.za/api/v1/partner · Machine-readable spec: openapi.yaml · All prices in ZAR.
Authentication
Send your key on every request, server to server. Never place it in browser code.
curl https://www.africanwings.co.za/api/v1/partner/ping \
-H "X-API-Key: awk_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Authorization: Bearer awk_live_… also works.
Endpoints
| Method | Path | What it does |
|---|---|---|
| GET | /ping | Checks your key and shows your commission. |
| GET | /products | Airports (ICAO codes), aircraft, scenic flights and live empty legs. |
| GET | /feed?format=json|csv | Flat product list with retail and net prices. |
| POST | /quote | Price a charter, scenic flight or empty leg. |
| GET | /availability?productId=&date= | Seats left per departure time for a scenic flight. |
| POST | /bookings | Create a booking request. Supports Idempotency-Key. |
| GET | /bookings/{ref} | Read a booking you created. |
| POST | /bookings/{ref}/cancel | Cancel a booking you created. |
Quote a charter
Charters are sold per aircraft. The response lists every aircraft with available, flight time, distance, total (retail) and netTotal (your price). Unavailable aircraft include a reason.
POST /quote
{
"product": "charter",
"from": "FACT", // Cape Town
"to": "FAPG", // Plettenberg Bay
"date": "2026-12-04",
"returnDate": null, // or "2026-12-07"
"adults": 2, "children": 0, "infants": 0
}
{ "ok": true, "data": {
"type": "charter", "from": "FACT", "to": "FAPG", "seatsNeeded": 2,
"pricesConfirmed": false, "commissionPct": 10,
"options": [
{ "aircraftId": "c182", "aircraft": "Cessna 182", "seats": 3, "available": true,
"flightMinutes": 126, "distanceKm": 436, "total": 28600, "netTotal": 25740,
"pricePerHead": 9540, "breakdown": { … } },
…
] } }
When pricesConfirmed is false, prices are indicative and the final price is confirmed with the booking.
Create a booking
Send the same fields as the quote plus the chosen aircraftId, the lead guest and passengers. We always recalculate the price. Use Idempotency-Key so a retry never creates a second booking.
POST /bookings
Idempotency-Key: TNS-48213-1
{
"product": "charter", "from": "FACT", "to": "FAPG", "date": "2026-12-04",
"adults": 2, "aircraftId": "pa31", "departureTime": "09:30",
"partnerReference": "TNS-48213",
"contact": { "name": "Amira Khan", "email": "amira@example.com", "phone": "+971 50 123 4567" },
"passengers": [ { "name": "Amira Khan", "weightKg": 64 }, { "name": "Omar Khan", "weightKg": 82 } ],
"notes": "Transfer to Kurland lodge"
}
201 Created
{ "ok": true, "data": { "ref": "AW7K3MQX", "status": "requested", "total": 47300,
"netTotal": 42570, "partnerReference": "TNS-48213", … } }
Passenger weights matter on light aircraft. Send them whenever you can; we ask for them before confirming if missing.
Whale & scenic flights
Scenic flights are sold per seat or as a private aircraft at fixed times. Check seats first, then quote or book with the slot.
GET /availability?productId=whale-30&date=2026-11-02
POST /bookings
{ "product": "scenic", "productId": "whale-30", "date": "2026-11-02", "slot": "09:00",
"seats": 2, "private": false, "partnerReference": "TNS-50110",
"contact": { … }, "passengers": [ … ] }
Empty legs use "product": "emptyleg" with the legId from /products. Their price is fixed.
Booking lifecycle
| Status | Meaning |
|---|---|
requested | Received. We are checking aircraft, crew and airfields. |
confirmed | Reserved. Final price and payment terms are in the webhook message. |
paid | Payment received. |
completed | Flown. |
cancelled | Cancelled by you or by us. |
Webhooks
Give us an HTTPS address and we POST every status change to it. Verify the signature with your webhook secret.
POST https://your-platform.example/hooks/african-wings
X-AW-Event: booking.confirmed
X-AW-Signature: sha256=5f1c…
{ "event": "booking.confirmed", "sentAt": "2026-11-28T10:02:11+02:00",
"booking": { "ref": "AW7K3MQX", "status": "confirmed", "partnerReference": "TNS-48213", … } }
// Node.js check
const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers['x-aw-signature']));
Reply with any 2xx status. You can also poll GET /bookings/{ref}.
Product feed
GET /feed returns every sellable product: popular charter routes per aircraft, scenic flights per seat and private, and live empty legs. Each has a stable sku, retailPrice and netPrice. Use ?format=csv for an extranet upload.
sku,type,name,from,to,date,time,maxGuests,durationMin,priceBasis,retailPrice,netPrice,currency,indicative
CHT-FACT-FAPG-PA31,charter,Private charter Cape Town (CPT) to Plettenberg Bay (PBZ) by Piper PA-31 Navajo,FACT,FAPG,,,6,90,"per aircraft, one way",47300,42570,ZAR,yes
Errors & limits
Errors return "ok": false with a code, a readable message and, for validation, a fields map.
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | Missing or wrong API key. |
| 404 | not_found | Unknown endpoint, product or booking. |
| 409 | unavailable | Seats, slot or empty leg no longer available. |
| 422 | invalid_request | A field is missing or wrong; see fields. |
| 429 | rate_limited | More than 240 requests a minute. |
Questions: safari@africanwings.co.za