SkyWings
Flight Booking Platform
SkyWings is a flight booking web application built with Django and integrated with the Duffel API for flight-related services and Paystack for payment processing. The project demonstrates my ability to combine a server-side web framework, external travel APIs, and payment infrastructure into an end-to-end booking workflow.
Technology
The problem
Flight availability and pricing are not data you own. They come from an external travel provider, they are quoted with an expiry, and they are not a reservation until the booking is actually confirmed. Building a booking flow means handling third-party authentication, translating an unfamiliar response model into something usable, and making sure a payment is only ever requested against a price the backend has verified and held.
Approach
- 01
Kept the Duffel integration server-side. API credentials never reach the browser, and search and pricing logic live in Django where they can be tested and versioned independently of the interface.
- 02
Treated search and booking as separate concerns. Search returns candidates; booking is a distinct, validated step against a specific itinerary — the separation matters because search is cheap and idempotent while booking is neither.
- 03
Made the price authoritative on the server. The amount submitted to the payment gateway is the amount the backend holds, not a figure forwarded from the client, so a tampered request cannot change what is charged.
- 04
Verified the booking before taking payment, so a confirmed seat exists before funds are requested rather than after.
- 05
Built the interface with HTML, CSS and Bootstrap so the booking flow stays readable and usable on the devices travellers actually use, while Django handles the external calls.
Architecture
- 01
Search request
The user submits origin, destination and dates. The Django backend queries the Duffel API and translates the response into a normalised result model.
- 02
Itinerary selection
A chosen result becomes a server-held itinerary with a verified fare, rather than a set of values the client is trusted to carry forward.
- 03
Booking confirmation
The booking is confirmed against the Duffel API before any payment is requested, so a failed reservation never reaches the payment step.
- 04
Payment
The verified amount is sent to Paystack from the backend. The client initiates the payment but cannot influence the amount charged.
- 05
Confirmation
The result of the transaction is recorded against the itinerary so booking state and payment state remain consistent.
The verified fare lives on the server. The client can start a payment; it cannot decide what the payment is for.
Key features
Challenges
Integrating a third-party API you do not control
Travel API responses are deeply nested, token-authenticated, and they change. Isolating the integration behind a service layer meant the rest of the application worked with a normalised model, and a change in the external contract stayed a small, contained edit.
Payment against a price that can expire
A fare quoted at search time is not guaranteed at checkout. Holding the verified amount server-side and confirming the booking before requesting payment is what stops a payment from being attempted against a price that no longer exists.
What I learned
Any third-party integration eventually breaks. The design decision that matters is not how well it works on the day it is built, but whether the failure is contained to one module with a clear shape when the external API changes.