Channel Manager
Connect your property to online travel agencies (OTAs) like Booking.com, Expedia, Agoda, and Airbnb. The channel manager syncs availability, rates, and reservations automatically through ChanneX middleware, with AI-powered room mapping, rate suggestions, and error diagnosis.
Where to find it
Overview
The channel manager is built on a provider-agnostic abstraction. The first supported provider is ChanneX, which connects to 200+ OTAs through a single integration. The architecture supports adding direct OTA APIs (Booking.com Direct, Expedia Direct) or other middleware (SiteMinder) as drop-in providers.
What Gets Synced
| Data | Direction | Frequency | Source of Truth |
|---|---|---|---|
| Availability | Push (PMS → OTA) | Every 15 min | Resource count minus active allocations |
| Rates | Push (PMS → OTA) | Every 30 min | Rate Calendar (overrides) + base price |
| Restrictions | Push (PMS → OTA) | On change | Stop sell, min/max stay, CTA/CTD |
| Reservations | Pull (OTA → PMS) | Webhook + poll every 5 min | OTA booking → MasterReservation |
Setting Up a Channel Connection
The setup wizard guides you through connecting an OTA in 4 steps. AI auto-maps your room types to reduce manual work.
Step 1: Choose Provider
Select your channel manager provider. Currently supported: ChanneX. Future providers (SiteMinder, Booking.com Direct, Expedia Direct) will appear here as they are added.
Step 2: Enter Credentials
- Enter a Connection Name (e.g. "ChanneX - Main Property")
- Enter your API Key from the provider dashboard
- Enter your External Property ID (the property ID in the provider system)
- Click Test Connection to verify credentials are valid
The system validates credentials against the provider API. If successful, you see the property name and can proceed. If it fails, check that the API key is active and the property ID is correct.
Step 3: Map Room Types
The system fetches room types from the channel and your local services (room types). AI auto-mapping matches them by name similarity and suggests mappings with confidence scores. You review the mapping table and adjust if needed.
- Each local room type maps to one external room type
- Unmapped room types are listed separately so you can add them manually
- You can skip mappings for room types you don't want to sell on that OTA
Step 4: Confirm & Connect
Review the configuration summary and click Create Connection. The system creates the connection, saves room type mappings, generates a webhook URL for receiving OTA bookings, and triggers an initial availability sync.
Dashboard
The channel manager dashboard (Settings → Integrations → Channel Manager) shows:
- Connection Status Cards — One per connection, color-coded (green = connected, yellow = pending, red = error), with last sync time and error count
- OTA Bookings Today / This Week — Count of incoming OTA reservations
- Sync Success Rate — Percentage of successful syncs over the last 7 days
- Pending Errors — Number of unresolved sync failures
- Quick Actions — "Add Channel" and "Refresh" buttons
Rate Calendar
The rate calendar shows a grid of room types (rows) vs dates (columns). Each cell shows the effective nightly rate.
How Rates Work
- Base Price — Set on the Rate Plan. Used when no calendar override exists for a date
- Calendar Override — Per-date price set manually or by AI. Overrides the base price
- Channel Markup — Optional per-channel markup (percentage or fixed amount) applied on top of the effective rate
- Effective Rate = (Calendar Override ?? Base Price) + Channel Markup
Editing Rates
- Click any cell in the rate calendar grid
- Enter the new price in the inline editor
- Press Enter to save or Escape to cancel
- The rate is saved as a "MANUAL" override and will be pushed to channels on the next rate sync
Rate Plan Types
| Type | Description |
|---|---|
| STANDARD | Default flexible rate with standard cancellation |
| NON_REFUNDABLE | Discounted rate (typically 10% off), no cancellation |
| EARLY_BIRD | Discount for booking far in advance |
| LAST_MINUTE | Discounted rate for bookings within a few days |
| LONG_STAY | Discount for extended stays (7+ nights) |
| PROMOTIONAL | Special offer or seasonal promotion |
Visual Legend
- Amber background — Custom rate override (manual or accepted AI suggestion)
- Blue background — AI-suggested rate (pending acceptance)
- Gray background — Weekend
- Regular text = base price (no override)
- Bold text = override price
AI Features
The channel manager includes three AI-powered capabilities.
AI Room Type Mapping
During setup, AI reads your local room types and the channel's room types and auto-matches them by name, description, and capacity. Each match includes a confidence score (0.5–1.0) and explanation. You review and confirm the mapping table instead of manually dragging and dropping.
AI Rate Intelligence
AI analyzes your occupancy history (last 90 days by day-of-week), upcoming occupancy levels, and current rate overrides to suggest optimal nightly rates. Suggestions follow these rules:
- High occupancy (>80%) = increase rate 10–30%
- Low occupancy (<40%) = decrease rate 5–15%
- Weekend premium of 10–20%
- Never below 60% of base price (floor)
- Never above 200% of base price (ceiling)
Suggestions appear in the rate calendar with a blue "AI" indicator. Accept or reject each suggestion individually.
AI Error Diagnosis
When a sync fails, AI analyzes the error details and provides a human-readable diagnosis with root cause, severity level, and specific action items. Common diagnoses include:
- 401/403 → API credentials invalid or expired
- 404 → Property or room type not found on channel
- 429 → Rate limiting, wait and retry
- 5xx / timeout → Channel provider temporarily down
Qvi (AI Assistant) Integration
You can interact with the channel manager through the Qvi AI assistant. Examples:
- "What's my channel sync status?" → Shows connection health table
- "Why did the last sync fail?" → AI error diagnosis
- "How many OTA bookings this week?" → Booking stats by channel
- "Set Ocean View to $150 for Christmas week" → Creates rate calendar entries
- "Stop selling Standard Rooms tomorrow" → Creates stop-sell restriction
- "Sync now" → Triggers immediate availability push
OTA Reservations
Incoming OTA reservations are received via webhook or polling, and automatically converted into standard reservations.
Ingestion Flow
- OTA sends booking via webhook (or it is polled every 5 minutes)
- System verifies webhook signature and checks for duplicate (idempotency)
- Creates a
ChannelReservationrecord with the raw OTA payload - Maps the external room type to a local service via room type mappings
- Finds or creates the guest as a
TradingPartner - Calls the standard
ReservationService.createReservation()to create aMasterReservation - All normal accounting, tax, resource allocation, and fulfillment flows apply
- Triggers an availability re-sync to update all channels
OTA reservations appear in the Reservations list and Front Desk like any other booking, with a channelSource field indicating the origin (e.g. "booking_com").
OTA Reservations Tab
The OTA Reservations tab (Channel Manager → Reservations) shows a dedicated list of OTA bookings with:
- Channel badge (color-coded: blue for Booking.com, yellow for Expedia, etc.)
- Guest name and email
- Check-in / check-out dates
- Total amount and commission
- Status (Pending, Confirmed, Modified, Cancelled)
- Link to the master reservation (once processed)
Filter by channel or status using the dropdown filters.
Sync Monitor
The sync monitor (Channel Manager → Sync Monitor) shows a log of all sync operations with:
- Time — When the sync ran
- Type — AVAILABILITY, RATES, RESTRICTIONS, or RESERVATIONS
- Direction — PUSH (to OTA) or PULL (from OTA)
- Status — SUCCESS, IN_PROGRESS, PENDING, PARTIAL_FAILURE, or FAILED
- Items — Success count / total count, with failure count highlighted
- Duration — How long the sync took
- Triggered By — CRON (automatic), MANUAL (user-triggered), or WEBHOOK
Filter by connection and sync type. Failed syncs show error details inline.
Auto-Suspension
If a connection accumulates 10+ consecutive errors, the system automatically suspends it to prevent further failed API calls. The hourly health check cron monitors all connections and flags stale syncs (no sync in 2+ hours).
Restrictions
Restrictions control selling rules per room type and date. They are pushed to channels alongside rates.
| Restriction | Effect |
|---|---|
| Stop Sell | Room type cannot be booked on this date |
| Closed to Arrival (CTA) | Guests cannot check in on this date |
| Closed to Departure (CTD) | Guests cannot check out on this date |
| Min Stay | Minimum number of nights required |
| Max Stay | Maximum number of nights allowed |
Managing Connections
Connection Detail Page
Click a connection to see its detail page, which shows:
- Connection status and last sync times
- Room type mappings (local service ↔ external room type)
- Rate plan mappings (local rate plan ↔ external rate plan with optional markup)
- Manual sync buttons (Sync Availability, Sync Rates, Sync Restrictions)
- Disconnect button (soft-deletes the connection)
Connection Statuses
| Status | Meaning |
|---|---|
| PENDING_SETUP | Connection created but not yet tested / synced |
| CONNECTED | Active and syncing normally |
| ERROR | Last sync failed, will retry |
| SUSPENDED | Auto-suspended after 10+ errors |
| DISCONNECTED | Manually disconnected, no longer syncing |
Webhook Integration
Each connection gets a unique webhook URL for receiving real-time reservation notifications from the channel provider.
POST /webhooks/channel-manager/:channelConnectionIdThe webhook endpoint:
- Loads the connection and determines the provider type
- Verifies the request signature using the connection's webhook secret
- Checks idempotency (prevents duplicate processing of the same event)
- Routes the event: new booking → ingestion, modification → update, cancellation → cancel
- Triggers an availability re-sync after any reservation change
Register this webhook URL in your channel provider's dashboard (e.g. ChanneX property settings).
GraphQL API Reference
The channel manager exposes these GraphQL queries and mutations. All require JWT authentication.
Queries
| Query | Description |
|---|---|
| channelManagerDashboard(businessUnitId) | Dashboard with connections, booking counts, sync rate |
| channelConnections(businessUnitId) | List all connections for a business unit |
| channelConnection(id) | Single connection with mappings |
| externalRoomTypes(channelConnectionId) | Fetch room types from the channel |
| ratePlans(businessUnitId) | List rate plans |
| rateCalendar(input) | Rate plans with calendar entries for a date range |
| channelReservations(input) | List OTA reservations with filters |
| channelSyncLogs(input) | Sync history log |
| aiRateSuggestions(businessUnitId, serviceId, startDate, endDate) | AI-generated rate suggestions for a date range |
| aiDiagnoseChannelError(businessUnitId, channelConnectionId?) | AI diagnosis of latest sync error |
| aiChannelSetupSuggestions(businessUnitId, channelConnectionId) | AI-suggested room type mappings and rate plans |
Mutations
| Mutation | Description |
|---|---|
| testChannelConnection(input) | Test credentials without creating a connection |
| createChannelConnection(input) | Create a new OTA connection |
| updateChannelConnection(id, input) | Update connection settings |
| deleteChannelConnection(id) | Soft-delete (disconnect) a connection |
| bulkCreateRoomTypeMappings(input) | Map multiple room types at once |
| createRatePlan(input) | Create a rate plan for a room type |
| setRateCalendar(input) | Set per-date rate overrides |
| syncChannelAvailability(channelConnectionId) | Trigger manual availability push |
| syncChannelRates(channelConnectionId) | Trigger manual rate push |
| syncChannelRestrictions(channelConnectionId) | Trigger manual restriction push |
Data Model
The channel manager adds 8 database tables and 5 enums.
Tables
| Table | Purpose |
|---|---|
| channel_connections | OTA connection per business unit (credentials, status, sync settings) |
| channel_room_type_mappings | Maps local Service to channel room type code |
| rate_plans | Rate plans per room type (Standard, Non-Refundable, etc.) |
| rate_calendar | Per-date rate overrides with source tracking |
| channel_rate_plan_mappings | Maps local rate plan to channel rate plan + markup |
| channel_restrictions | Per-date selling restrictions (stop sell, min/max stay) |
| channel_reservations | Incoming OTA reservations with raw payload |
| channel_sync_logs | Audit trail for all sync operations |
Cron Jobs
| Cron | Schedule | Purpose |
|---|---|---|
| Availability Sync | Every 15 min | Push availability to all connected channels |
| Rate Sync | :05 and :35 of every hour | Push rate changes to channels |
| Reservation Poll | Every 5 min | Poll channels for new reservations |
| Health Check | Every hour | Check for stale syncs, auto-suspend failing connections |
Troubleshooting
Connection test fails
- Verify the API key is correct and active in your ChanneX dashboard
- Verify the property ID matches exactly (case-sensitive)
- Check that your ChanneX subscription is active
Availability not updating on OTAs
- Check that the connection status is CONNECTED (not ERROR or SUSPENDED)
- Check the Sync Monitor for recent AVAILABILITY sync failures
- Verify room type mappings exist (unmapped room types are not synced)
- Try a manual sync from the connection detail page
OTA bookings not appearing
- Verify the webhook URL is registered in ChanneX
- Check the OTA Reservations tab for pending or errored bookings
- Check that the external room type in the booking maps to a local service
- The reservation poll cron (every 5 min) is a fallback if webhooks are not configured
Connection auto-suspended
If a connection reaches 10+ consecutive errors, the hourly health check suspends it. To fix:
- Go to the connection detail page
- Review the error message and sync logs
- Fix the underlying issue (usually credentials or property ID)
- Click Test Connection to verify it works
- The connection will be reactivated on successful test
Related
- Reservations — Where OTA bookings appear after ingestion
- Hotel Front Desk — Check-in/out OTA guests
- Room Allocations — See OTA bookings in the room grid
- Service Management — Define room types that get mapped to channels
- AI Assistant (Qvi) — Chat-based channel manager interaction