Travel & Tourism · API Integration
Booking engines and API integration for travel brands.
From WhatsApp package flows for tour operators to full OTA platforms with real-time flight and hotel inventory. Modern REST/GraphQL integration, dynamic packaging, resilient caching — no SOAP-era ceremony.

What we build
One booking layer, six moving parts — built to hold together.
Flight & Hotel Inventory APIs
Direct REST/GraphQL connections to consolidator inventory and select supplier APIs. Real-time pricing, availability and hold-book flows without the SOAP-era ceremony.
Dynamic Packaging Engine
Combine flight + hotel + transfer inventory into single-cart packages priced on the fly. Rules engine for margins, promo codes and seasonal overrides you control from the admin.
Itinerary Automation
Auto-generate day-wise itineraries from a package template, personalise per traveller, and push to WhatsApp/PDF. Same content, one source of truth.
Inventory Cache & Fallbacks
Layered caching (edge + Redis) keeps pricing pages sub-200ms even when upstream suppliers slow down. Circuit breakers keep one bad supplier from breaking the funnel.
PCI-Aware Payment Handoff
Tokenised payment flows via Razorpay, Cashfree and Stripe. Booking confirmations, refunds and disputes wire back into your CRM automatically.
Ops Sync — Back-office to Frontline
Bookings sync into your ops sheet, CRM or in-house tools via webhooks. No more copy-paste from portal to Excel to WhatsApp group.
The shift
Why we don't ship SOAP anymore.
Amadeus, Sabre and Travelport still power a large share of global travel inventory — and their public interfaces are still largely SOAP with WSDL-based contracts. For most tour operators and DMCs in India, going direct to a GDS is heavy: minimum monthly commitments, certification cycles, WS-Security wrappers, pagination that doesn't match anything else in your stack.
For 90% of the operators we work with, the right first step is a consolidator or NDC-forward supplier over REST — TBO, TripJack, RezLive, hotelbeds, and the direct APIs from suppliers you already book manually. Same inventory in most lanes, cleaner JSON, per-transaction pricing, and an abstraction layer we own so a second supplier can be added later without touching the UI.
The engineering job then becomes what it should be: keep supplier calls resilient, keep prices honest, keep the funnel fast. That's caching, timeouts, circuit breakers and background refresh — not SOAP envelopes and certification queues.

The build
"Every supplier call wrapped in a timeout, a retry, and a fallback. Nothing hits your customers without going through our resilience layer first."
The pattern
Retryable inventory fetch with cache and circuit breaker
Node.js 20+. No external dependencies beyond your HTTP client. This is roughly the shape of the code that sits between our operators' landing pages and their consolidator.
// Retryable hotel-inventory fetch with in-memory cache + circuit breaker
// Runs on Node.js 20+ — no external deps beyond your HTTP client of choice.
type InventoryRequest = { hotelCode: string; checkIn: string; nights: number };
type InventoryResult = { rate: number; currency: string; roomType: string }[];
const CACHE_TTL_MS = 45_000; // stale-fast — supplier prices change every ~60s
const cache = new Map<string, { at: number; data: InventoryResult }>();
const breaker = { failures: 0, openedAt: 0 };
const OPEN_AFTER = 5;
const OPEN_FOR_MS = 30_000;
function key(r: InventoryRequest) {
return `${r.hotelCode}|${r.checkIn}|${r.nights}`;
}
async function fetchWithTimeout(url: string, opts: RequestInit, ms = 2500) {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), ms);
try {
return await fetch(url, { ...opts, signal: ctrl.signal });
} finally {
clearTimeout(t);
}
}
export async function getInventory(
req: InventoryRequest,
): Promise<InventoryResult> {
// 1. Serve from cache when fresh — supplier calls cost money and quota.
const hit = cache.get(key(req));
if (hit && Date.now() - hit.at < CACHE_TTL_MS) return hit.data;
// 2. Short-circuit when the supplier is unhealthy.
if (
breaker.failures >= OPEN_AFTER &&
Date.now() - breaker.openedAt < OPEN_FOR_MS
) {
if (hit) return hit.data; // serve stale rather than block the page
throw new Error("supplier_unavailable");
}
try {
const res = await fetchWithTimeout(
`https://api.supplier.example/hotels/${req.hotelCode}/rates`,
{
headers: { Authorization: `Bearer ${process.env.SUPPLIER_TOKEN!}` },
},
);
if (!res.ok) throw new Error(`supplier_${res.status}`);
const data: InventoryResult = await res.json();
cache.set(key(req), { at: Date.now(), data });
breaker.failures = 0;
return data;
} catch (err) {
breaker.failures += 1;
if (breaker.failures === OPEN_AFTER) breaker.openedAt = Date.now();
if (hit) return hit.data; // graceful stale fallback
throw err;
}
}What it changes
What operators tell us a month after go-live.
Search-to-quote reduced from 6–9s (legacy SOAP polling) to under 1.2s with our REST+cache layer.
New supplier plugged in inside two sprints once the abstraction layer exists — versus rebuilding UI per source.
Meaningful drop in Google Ads CPA once landing pages started returning quotes in real time instead of a form.
Booking confirmations, itineraries and vouchers auto-generate — one tour operator we built for cut a full ops seat's worth of manual work.
Ranges based on projects we've delivered for tour operators and DMCs across India. Individual results depend on supplier mix, traffic patterns and the pre-launch baseline.
FAQ
Questions operators actually ask.
Do we need to buy Amadeus or Sabre access to launch a booking site?
Not necessarily. For most Indian tour operators and DMCs we start with a consolidator (TBO, TripJack, RezLive or similar) via their REST APIs — same inventory, cleaner integration, lower minimum commitments. Direct GDS access makes sense once volume and margin justify the fixed cost.
How do you keep the site fast when supplier APIs are slow?
Two layers. First, cache popular search combinations (Mumbai → Goa this weekend, common hotel codes) at the edge with short TTLs, refreshed by background jobs. Second, wrap every upstream call in a timeout + circuit breaker so a slow supplier degrades instead of blocking the page. Users see results in under 1.2s in most sessions.
Can you integrate with our existing CRM and ops sheets?
Yes. Bookings are pushed via webhooks into whatever you use — Zoho, HubSpot, custom Google Sheets, or your in-house ops tool. We do the reverse too: itineraries and vouchers can be regenerated from the CRM record so ops and frontline see the same truth.
Who owns the code once it's built?
You do. Full source, deployed to your own hosting (AWS, DigitalOcean, or ours if you prefer). We hand over the repo, the deployment scripts and a written runbook. No vendor lock-in on the platform itself — the only third-party dependency is the supplier APIs you'd have anyway.
How long from kick-off to a live booking page?
For a standard consolidator + WhatsApp confirmation flow, 6–8 weeks to a live production booking page. Dynamic packaging, multi-supplier fallbacks and custom margin engines add time — we scope those as separate phases so the first phase can start earning.
A booking engine worth owning.
Tell us what you sell and where you buy inventory. We'll come back with a scoped first phase, a fixed timeline and no vendor lock-in.