Channel Manager / OTA Sync
Bookings rarely come from one place. ABc pulls reservations from major OTAs and pushes the property's inventory + rates back to them — two-way, near-real-time, with explicit conflict resolution and a parity safety net.
Supported channels (target list)
Booking.com
XML-based OTA protocol. Two-way: pull reservations, push rates + availability.
V1Airbnb
REST API + iCal fallback. Two-way for partner-connected hosts, iCal-only otherwise.
V1.1MakeMyTrip
Hotelier / MMT Connect API. India's largest domestic OTA.
V1.1TripAdvisor
TA Bookings (Instant Booking). Cookie-cutter integration via partner platform.
V2Expedia / Hotels.com
Expedia Quick Connect. Useful for international travellers.
V2Agoda
YCS API. Asia-Pacific heavy.
V2Goibibo
Same backend as MMT — done in one integration.
V1.1iCal (universal fallback)
Read & write .ics URLs. Lets us sync with any platform that supports calendar export — without partner approval.
MVPWhat two-way sync means
Outbound (ABc → OTA)
- Availability per day per room type
- Rate per day per room type (or per rate plan)
- Min/max stay restrictions
- Close-out flags
- Property & room photos (manual push on update)
Inbound (OTA → ABc)
- New reservation (creates booking, source = otaName)
- Modified reservation (updates dates/guest count)
- Cancellation (sets status, triggers refund per OTA policy)
- Inquiry-only message (Airbnb)
Sync console UI
| Channel | Status | Last sync | Bookings (30d) | Revenue (30d) | |
|---|---|---|---|---|---|
| Booking.com BDC-prop-9928 |
Connected | 1 min ago | 34 | ₹2,18,400 | |
| Airbnb iCal mode |
iCal · 1-way push only | 3 min ago | 12 | ₹78,200 | |
| MakeMyTrip MMT-44218 |
Connected | 4 min ago | 22 | ₹1,52,800 | |
| TripAdvisor | Not connected | — | — | — | |
| Expedia | Not connected | — | — | — |
How a Booking.com reservation flows in
Booking.com sends webhook
On every reservation event (new / modify / cancel), Booking.com hits
POST /api/webhooks/booking-comwith signed payload.Adapter normalises
The channel adapter parses the BDC-specific shape into ABc's internal Booking model. Maps their room IDs to our
room_type_id.Inventory check (defensive)
Although we already pushed availability to them, race conditions exist. If no inventory: log + alert + create the booking with status
oversold_review.Create booking
Status set per BDC's reservation state. Source =
booking_com. Payment model recorded (pay-at-hotel vs collected-by-OTA).Emit events
Internal event
booking.created.otafires. Notify-service emails the owner; analytics service updates the channel-mix dashboard.
How outbound sync works
// Two clocks High-frequency push — every 60s • Pushes any availability change touched in the last 60s • Pushes new rate plans / blackouts created in the last 60s • Lives in queue: "channel.push" Daily reconciliation — every night 03:00 IST • Full snapshot push of next 18 months • Compares our inventory to OTA's reported inventory • Files a "drift" report; alerts owner if > 2 % delta
The adapter pattern
Each OTA has its own quirks (XML vs JSON, rate-plan-per-room vs rate-plan-per-property, etc.). We isolate that in adapter modules with a common interface:
interface ChannelAdapter { connectListing(propertyId: string, credentials: OAuthOrApiKey): Promise<Connection>; pushAvailability(connection, days: AvailabilityDay[]): Promise<SyncResult>; pushRates(connection, days: RateDay[]): Promise<SyncResult>; pushRestrictions(connection, days: RestrictionDay[]): Promise<SyncResult>; parseInboundReservation(payload: unknown): CanonicalBooking; verifyWebhookSignature(req): boolean; }
Overbooking prevention across channels
The hard problem. We use three defences in order of cost:
| Strategy | How it works |
|---|---|
| Hold + version | 10-min inventory hold during public checkout. Confirm endpoint uses optimistic concurrency. |
| Safety buffer | Owner config: "Always keep 1 unit out of OTA inventory" — that one is direct-only. |
| Webhook race detect | If two reservations arrive within 5 s for the last unit, the later one auto-routes to oversold_review. |
| Daily parity check | Nightly job recomputes inventory from confirmed bookings and republishes to all OTAs. |
iCal fallback (MVP scope)
For owners without OTA partner agreements, we ship a basic iCal sync:
- Push: ABc exports an
.icsURL per property/room. Each blocked date is a VEVENT. OTAs import this URL on their side every 1–6 hours. - Pull: ABc accepts up to 5 .ics URLs per property. Polled every 15 minutes. New VEVENTs become blocks; vanished VEVENTs lift the block.
- Caveat: iCal carries dates only, not rate or guest details. Bookings imported from iCal show as "External block" — no guest name, no money.
An iCal sync can be 15–60 min behind real-time. For high-occupancy weekends, this is a non-trivial risk. We surface this in the UI and recommend partner-API for properties with > 70 % weekend occupancy.
Rate parity
Most OTAs require that the direct rate not be cheaper than the OTA-shown rate. We give owners three modes:
Same everywhere
Default. ABc pushes the same rate to all channels. No risk of parity violation.
Channel-aware
Owner sets per-channel multipliers (e.g. BDC +12 % to offset commission). System enforces parity floor on direct site.
Direct-cheaper
Direct site can be cheaper (e.g. via member discount), but the OTA rate is the public posted rate. Risk-aware mode.