2026-04-045 min

How to Build a Vacation Rental Channel Manager in 50 Lines of Code

Building a channel manager typically takes months. With the Repull API, you can sync reservations across all your PMS platforms and OTA channels in about 50 lines of TypeScript.

What we are building

A script that: 1. Connects to any PMS (Hostaway, Guesty, OwnerRez, etc.) 2. Fetches all reservations from all channels (Airbnb, Booking.com, VRBO) 3. Syncs availability across properties 4. Sets up real-time webhooks for new bookings

The code

import { Repull } from '@repull/sdk'

const dom = new Repull({
  apiKey: 'sk_live_YOUR_KEY',
  workspaceId: 'YOUR_WORKSPACE_ID',
})

// 1. List all properties
const { data: properties } = await dom.properties.list()
console.log(`Found ${properties.length} properties`)

// 2. Get reservations from ALL channels
const { data: airbnb } = await dom.reservations.list({ source: 'AIRBNB' })
const { data: booking } = await dom.reservations.list({ source: 'BOOKING_COM' })
const { data: vrbo } = await dom.reservations.list({ source: 'VRBO' })
const { data: direct } = await dom.reservations.list({ source: 'DIRECT' })

console.log(`Airbnb: ${airbnb.length}, Booking: ${booking.length}, VRBO: ${vrbo.length}, Direct: ${direct.length}`)

// 3. Sync availability — block dates that are booked
for (const property of properties) {
  const allReservations = [...airbnb, ...booking, ...vrbo, ...direct]
    .filter(r => r.propertyId === property.id && r.status === 'CONFIRMED')

  const blockedDates = allReservations.flatMap(r => {
    const dates = []
    let d = new Date(r.checkIn)
    const end = new Date(r.checkOut)
    while (d < end) {
      dates.push({ date: d.toISOString().split('T')[0], available: false })
      d.setDate(d.getDate() + 1)
    }
    return dates
  })

  if (blockedDates.length > 0) {
    await dom.availability.update({
      propertyId: property.id,
      updates: blockedDates,
    })
    console.log(`Blocked ${blockedDates.length} dates for ${property.name}`)
  }
}

// 4. Set up webhook for real-time sync
await dom.webhooks.create({
  url: 'https://your-app.com/webhooks/new-booking',
  events: ['reservation.created', 'reservation.updated', 'reservation.cancelled'],
  description: 'Channel sync webhook',
})

console.log('Channel manager is live!')

How it works

The Repull API normalizes data from 9+ PMS platforms and 3 OTA channels into one unified schema. When a reservation comes in from Airbnb, it appears with source: "AIRBNB". When it comes from Booking.com, source: "BOOKING_COM". Same endpoint, same schema, same code.

What is next

  • - Add the [Connect Widget](/docs/connect-widget) so your users can authenticate with their PMS
  • - Use [schema adapters](/docs/schema-adapters) to match Calry format if migrating
  • - Set up the [MCP Server](/docs/mcp-server) for AI-powered channel management