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.

V1

Airbnb

REST API + iCal fallback. Two-way for partner-connected hosts, iCal-only otherwise.

V1.1

MakeMyTrip

Hotelier / MMT Connect API. India's largest domestic OTA.

V1.1

TripAdvisor

TA Bookings (Instant Booking). Cookie-cutter integration via partner platform.

V2

Expedia / Hotels.com

Expedia Quick Connect. Useful for international travellers.

V2

Agoda

YCS API. Asia-Pacific heavy.

V2

Goibibo

Same backend as MMT — done in one integration.

V1.1

iCal (universal fallback)

Read & write .ics URLs. Lets us sync with any platform that supports calendar export — without partner approval.

MVP

What 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

app.abc.com/channels
Channels · Park View Hotel
3 connected · last full sync 2 minutes ago
ChannelStatusLast syncBookings (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

  1. Booking.com sends webhook

    On every reservation event (new / modify / cancel), Booking.com hits POST /api/webhooks/booking-com with signed payload.

  2. 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.

  3. 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.

  4. Create booking

    Status set per BDC's reservation state. Source = booking_com. Payment model recorded (pay-at-hotel vs collected-by-OTA).

  5. Emit events

    Internal event booking.created.ota fires. Notify-service emails the owner; analytics service updates the channel-mix dashboard.

How outbound sync works

SCHEDULE
// 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:

TypeScript — interface ChannelAdapter
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:

Last available unit?
Apply "safety buffer"
Soft close-out on OTAs
Direct site only
StrategyHow it works
Hold + version10-min inventory hold during public checkout. Confirm endpoint uses optimistic concurrency.
Safety bufferOwner config: "Always keep 1 unit out of OTA inventory" — that one is direct-only.
Webhook race detectIf two reservations arrive within 5 s for the last unit, the later one auto-routes to oversold_review.
Daily parity checkNightly 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 .ics URL 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.
iCal lag is real.

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.