Introduction
Travsify is one REST API for the entire travel stack — flights, hotels, tours, transfers, e-Visas and insurance. You ship one integration; we keep 6 supplier connections live for you and pay your wallet the difference between supplier price and your selling price.
The one-liner
One line of code. Any language. Live data. Travsify is a plain REST API — every language on Earth can speak HTTP, so the entire travel stack is one HTTP call away. Pick your stack, paste the line, swap in your key. That's the integration.
curl -X POST https://travsify.com/api/v1/flights/search -H "Authorization: Bearer tsk_sandbox_your_key_here" -H "Content-Type: application/json" -d '{"origin":"LOS","destination":"DXB","departure_date":"2026-06-01","adults":1}'5-minute quickstart
You can call the sandbox the moment you sign up — no KYB required to start building.
- 1Create an accountGo to signup. The moment you confirm your email, your sandbox API key is issued automatically.
- 2Grab your sandbox keyOpen Dashboard → API keys. Copy the key that starts with
tsk_sandbox_. - 3Make your first callbash
curl -X POST https://travsify.com/api/v1/flights/search \ -H "Authorization: Bearer tsk_sandbox_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "origin": "LOS", "destination": "DXB", "departure_date": "2026-06-01", "adults": 1 }' - 4Book from the dashboardWant to test a paid booking? Fund your USD wallet (Stripe) or NGN wallet (bank transfer) with $10, then use Dashboard → Book to confirm a real flight or hotel.
tsk_sandbox_totsk_live_and you're in production.Authentication
Every request needs a bearer token in the Authorization header. Two key types — both available from your dashboard:
curl https://travsify.com/api/v1/health \
-H "Authorization: Bearer tsk_sandbox_your_key_here"Wallet & funding
Every booking — sandbox or live, dashboard or API — is paid from your Travsify wallet. No post-paid billing, no surprise invoices. You see exactly what each booking cost before you confirm.
- USD wallet — fund with card via Stripe, withdraw to any USD bank.
- NGN wallet — fund via bank transfer to your dedicated Fincra virtual account, withdraw to any NGN bank.
- Wallet balance is debited automatically on booking; refunds credit back the same way.
- Your partner markup on each booking is paid into your wallet as profit, available for withdrawal.
- Customer books on your site → you call
/orders - We debit provider price + Travsify markup from your wallet
- We credit your partner markup back as wallet profit
- You charge your customer whatever you want — you keep 100% of that
Markups & pricing
Every price you see includes two layers of markup added on top of the supplier base price:
// Every price response includes the breakdown
{
"base_price": 800,
"price": 870,
"price_breakdown": {
"provider_base": 800,
"travsify_markup": 40,
"partner_markup": 30,
"total": 870,
"currency": "USD"
}
}Catalog (live inventory)
One endpoint to populate every dropdown on your frontend — countries, cities, destinations, providers — directly from our live database. Don't copy this data into your own DB. Call it on page load (or cache it for a few minutes) so your selectors always reflect what we currently have inventory for, including new corridors we add.
/api/v1/catalog// Optional: filter to one vertical
GET /api/v1/catalog?vertical=tours
// Verticals: tours | visas | transfers | rentals | insurance{
"data": {
"tours": {
"total_items": 1339,
"countries": [
{ "country": "United Arab Emirates", "cities": ["Abu Dhabi", "Dubai"] }
]
},
"visas": {
"total_items": 412,
"destinations": [
{
"destination": "AE",
"destination_name": "United Arab Emirates",
"nationalities": ["NG", "US", "GB"],
"visa_types": ["tourist", "transit"]
}
]
},
"transfers": { "total_items": 0, "countries": [] },
"rentals": { "total_items": 0, "countries": [] },
"insurance": { "total_items": 12, "providers": ["SafetyWing"], "plans": [] }
},
"generated_at": "2026-04-28T10:00:00.000Z"
}const t = Travsify.init("tsk_sandbox_...");
// Populate a country dropdown for tours
const { tours } = (await t.catalog("tours")).data;
const countries = tours.countries.map(c => c.country);
// Or fetch every vertical at once
const all = await t.catalog();/api/v1/catalog, your users see the new inventory the moment we publish it — no redeploy, no DB migration, no code change on your side.Flights
Live NDC + GDS inventory via Duffel. Real seat maps, real-time confirmation, instant tickets.
/api/v1/flights/search{
"origin": "LOS",
"destination": "DXB",
"departure_date": "2026-06-01",
"return_date": "2026-06-12",
"adults": 1
}{
"data": {
"offers": [{
"id": "off_0001",
"owner": "Emirates",
"total_amount": "812.40",
"total_currency": "USD"
}]
}
}/api/v1/flights/orders{
"offer_id": "off_0001",
"passengers": [{
"title": "mr",
"given_name": "Ada",
"family_name": "Lovelace",
"born_on": "1992-04-12",
"gender": "f",
"email": "ada@example.com",
"phone_number": "+2348012345678"
}]
}{
"data": {
"booking_id": "bkg_01H...",
"reference": "TSF-FLT-9X2K",
"status": "confirmed",
"ticket_numbers": ["176-1234567890"]
}
}Hotels
2M+ properties via LiteAPI — instant confirmation, daily price refresh, cancellation policies included.
/api/v1/hotels/search{
"country_code": "AE",
"checkin": "2026-06-12",
"checkout": "2026-06-15",
"adults": 2,
"currency": "USD"
}{
"data": {
"hotels": [{
"id": "lp_5512",
"name": "Atlantis The Royal",
"stars": 5,
"price": 940,
"currency": "USD",
"offer_id": "ofr_..."
}]
}
}/api/v1/hotels/bookings{
"offer_id": "ofr_...",
"holder": { "firstName": "Ada", "lastName": "Lovelace", "email": "ada@example.com" },
"guests": [{ "firstName": "Ada", "lastName": "Lovelace" }]
}{ "data": { "booking_id": "bkg_...", "reference": "TSF-HTL-...", "status": "confirmed" } }Tours & activities
GetYourGuide affiliate inventory. Same unified API — your customers stay on your brand.
/api/v1/tours/search{ "destination": "Dubai", "date": "2026-06-13", "participants": 2 }{ "data": { "tours": [{ "id": "gyg_...", "title": "Burj Khalifa fast-track", "price": 89, "currency": "USD" }] } }/api/v1/tours/bookings{ "tour_id": "gyg_...", "participants": [{ "firstName": "Ada", "lastName": "Lovelace", "email": "ada@example.com" }] }{ "data": { "booking_id": "bkg_...", "status": "processing" } }Transfers
Mozio worldwide ground transport — sedans, vans, shuttles. Affiliate, fully wrapped.
/api/v1/transfers/search{ "pickup": "DXB Airport", "dropoff": "Atlantis The Royal", "datetime": "2026-06-12T18:30", "passengers": 2 }{ "data": { "transfers": [{ "id": "moz_...", "vehicle": "Sedan", "price": 65, "currency": "USD" }] } }e-Visas
Sherpa-powered visa eligibility + e-Visa application via affiliate. We handle fulfilment.
/api/v1/visas/search{ "nationality": "NG", "destination": "AE", "purpose": "tourism" }{ "data": { "visas": [{ "id": "shp_...", "name": "UAE 30-day eVisa", "price": 75, "currency": "USD" }] } }Insurance
SafetyWing travel medical & trip insurance — quote and bind in one call.
/api/v1/insurance/search{ "nationality": "NG", "destination": "AE", "start_date": "2026-06-12", "end_date": "2026-06-19", "travelers": 1 }{ "data": { "plans": [{ "id": "sw_...", "name": "Nomad Insurance", "price": 42, "currency": "USD" }] } }Webhooks
We push events to your endpoint in real time. Configure your URL from the dashboard, then verify the signature header on every request.
booking.confirmed— supplier confirmedbooking.cancelled— cancelled by you or supplierbooking.refunded— money returned to walletbooking.fulfilled— affiliate verticals onlywallet.credited— funds arrivedpayout.completed— withdrawal paid
// Verify the signature in your handler
import crypto from "crypto";
function verify(signatureHeader, rawBody, secret) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
}Errors & retries
Errors are JSON. Status codes follow standard HTTP semantics.
| Code | Meaning | What to do |
|---|---|---|
| 400 | validation_error | Fix the field highlighted in error.message and retry. |
| 401 | invalid_api_key | Check the Authorization header. Re-issue from dashboard if needed. |
| 402 | wallet_insufficient | Top up your wallet then retry. We never auto-charge cards. |
| 404 | offer_expired | Search again — flight/hotel offers expire after ~15 minutes. |
| 429 | rate_limited | Back off using the Retry-After header. Default limit: 120 req/min. |
| 5xx | provider_error | Idempotent retry safe. Use the same Idempotency-Key header. |
Idempotency-Key: <uuid> on every write call. We deduplicate retries for 24 hours so a network blip never double-books or double-charges.Going live
Four things to tick off before you flip the switch:
- 1Submit KYBOpen Dashboard → Profile. Reviews complete in 24–72 hours.
- 2Set your markupsConfigure per-vertical partner markup at Dashboard → Markups.
- 3Fund your walletTop up USD or NGN at Dashboard → Wallet. Even $10 unlocks live bookings.
- 4Swap your keyReplace
tsk_sandbox_withtsk_live_in your environment. Done.