API & automation
Tulo's inventory can be initialized programmatically — built for operators and, ahead of time, for the software agents that will onboard properties automatically.
Seeding a property in one call
One request creates room types, physical rooms (and dorm beds), nightly rates and availability for a whole date window, and switches the property live. It runs on the Tulo operator API and requires an operator token — properties don't need to touch it; the Tulo team (or its tooling) runs it during onboarding.
POST /admin/v1/places/{place_id}/inventory/seed
Authorization: Bearer <tulo-operator-token>
Content-Type: application/json
{
"config": { "accepting_reservations": true },
"room_types": [
{
"name": "Standard Double",
"booking_mode": "private",
"units": 5,
"nightly_rate": 45000,
"days": 90
},
{
"name": "6-Bed Dorm",
"booking_mode": "shared",
"units": 2,
"beds_per_room": 6,
"nightly_rate": 15000
},
{
"name": "Lake House",
"booking_mode": "entire",
"units": 1,
"nightly_rate": 150000,
"cleaning_fee": 10000,
"days": 60
}
]
}Fields
nameRoom type name, unique per property. Matching is case-insensitive on re-runs.booking_modeprivate (default) | shared (dorm beds) | entire (whole place).unitsHow many physical rooms to create (entire is always 1). Rooms are labeled 'Name 1..N'.beds_per_roomShared only: beds created per room ('Bed 1..N').nightly_ratePrice per night in minor units (ngwee): 45000 = K450.00.currency3-letter code, defaults to ZMW.daysHow many days of rates + availability to open, starting today. Default 90, max 366.available_countUnits sellable per night. Defaults to units (or units × beds_per_room for shared).min_nightsMinimum stay, default 1.cleaning_feeOne-time fee in minor units, entire-place types.config.accepting_reservationsGo live immediately (default true).
Safe to re-run
Seeding is idempotent. Room types match by name and are never duplicated; rooms and beds are only created if missing; rates are updated in place; availability only fills dates that don't exist yet, so counts already reduced by real bookings are never resurrected.
Property API: bookings from your own website
Properties running on the Tulo console can take bookings from their own websites. A manager creates an API key in the console (Settings → API keys); the key is shown once and identifies your property — no place IDs in URLs. Send it as Authorization: Bearer tulo_pk_… on every call. Keys are rate limited to 60 requests per minute and can be revoked at any time from the console.
# What can be booked for those dates
GET /partner/v1/quote?check_in=2026-08-01&check_out=2026-08-03&adults=2
# Create a booking (confirms instantly; guest pays at the property)
POST /partner/v1/bookings
{
"room_type_id": "<from the quote>",
"check_in": "2026-08-01",
"check_out": "2026-08-03",
"adults": 2,
"guest": { "name": "Chanda Mwale", "phone": "+260971234567" }
}
# Read or cancel
GET /partner/v1/bookings/{id}
POST /partner/v1/bookings/{id}/cancelWebsite bookings appear in your console instantly, marked with source "website", alongside app bookings and walk-ins. They count against the same availability, so you can never be double-booked across channels.
Webhooks: Tulo bookings into your PMS
Properties that keep their own PMS can receive every Tulo booking event by webhook. Tulo POSTs JSON to {your-base-url}/tulo/webhooks with events like booking.created, booking.confirmed and booking.cancelled. Every request carries X-Tulo-Signature: the hex HMAC-SHA256 of the exact request body using your shared webhook secret — verify it before trusting the payload. Failed deliveries retry with exponential backoff for up to 8 attempts, and Tulo keeps the authoritative booking record plus a full delivery log for auditability (and painless migration onto the Tulo console later). Integration setup is done with the Tulo team: support@mail.tulo.homes.