API reference
Read provider-neutral property and reservation records through a small, stable contract.
Base URL and schema
https://supahost.io/api/v1The machine-readable OpenAPI 3.1 schema is available at /api/v1/openapi.json.
Test keys and sandbox data
Create a test key in Settings to build an integration without touching real data. Test keys start with sh_test_; live keys start with sh_live_.
A test key serves a fixed synthetic dataset: three sandbox properties with room types, rate plans, and calendar days, plus eight sandbox reservations across every status and channel. Filters, cursor pagination, and error responses behave exactly as they do for live keys.
- Sandbox records are clearly fake: names like
Sandbox Seaside Resort,@example.comemails, and555phone numbers. - The dataset is stable, so a cursor chain reads the same records on every run. Unknown IDs return
not_found, the same as live keys. - Test keys share the scopes, rate limit, and request audit of live keys. The audit record marks the key environment.
Writes need a live key. Test keys answer every write endpoint (property, task, message, calendar, rate-plan, and webhook management) with sandbox_read_only.
Properties
Property endpoints require the properties:read scope. Required response fields are always present; nullable fields include null in their type.
GET /properties
Return one stable page of properties.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
updated_after | string (date-time) | Optional | Return records changed after this ISO 8601 date and time. |
status | 'active' | 'inactive' | 'all' | Optional | Filter by property status. The default is active. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Property[] | Required | A stable page of property records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable property ID. |
data[].code | string | Required | Property code. |
data[].name | string | Required | Display name. |
data[].timezone | string | Required | IANA time zone. |
data[].status | 'active' | 'inactive' | Required | Property status. |
data[].updatedAt | string (date-time) | Required | Last property change time. |
data[].inventory | object | Required | Property inventory summary. |
data[].inventory.maxGuests | integer | Required | Maximum occupancy across active room types. |
data[].inventory.physicalUnits | integer | Required | Number of active physical units. |
data[].inventory.strategies | string[] | Required | Inventory strategies used by active pools. |
data[].channels | string[] | Required | Active channel names. |
data[].startingRate | object | null | Required | Lowest active starting rate, or null when no rate exists. |
data[].startingRate.amountMinor | string | Conditional | Required when startingRate is an object. Amount in the currency minor unit. |
data[].startingRate.currency | string | Conditional | Required when startingRate is an object. Three-letter currency code. |
GET /properties/{propertyId}
Return one property from the API key workspace.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Positive property database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Property | Required | The requested property. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable property ID. |
data.code | string | Required | Property code. |
data.name | string | Required | Display name. |
data.timezone | string | Required | IANA time zone. |
data.status | 'active' | 'inactive' | Required | Property status. |
data.updatedAt | string (date-time) | Required | Last property change time. |
data.inventory | object | Required | Property inventory summary. |
data.inventory.maxGuests | integer | Required | Maximum occupancy across active room types. |
data.inventory.physicalUnits | integer | Required | Number of active physical units. |
data.inventory.strategies | string[] | Required | Inventory strategies used by active pools. |
data.channels | string[] | Required | Active channel names. |
data.startingRate | object | null | Required | Lowest active starting rate, or null when no rate exists. |
data.startingRate.amountMinor | string | Conditional | Required when startingRate is an object. Amount in the currency minor unit. |
data.startingRate.currency | string | Conditional | Required when startingRate is an object. Three-letter currency code. |
PUT /properties/{propertyId}
Replace the writable details of one property. This endpoint requires the properties:write scope. Only name and timezone are writable; the other read fields are ignored when sent back.
The response is the updated property record. On a channel-connected property the change also queues to the channel sync outbox and propagates to connected channels asynchronously. An archived property must be restored in the dashboard before editing.
Send an Idempotency-Key header to make retries safe: a repeated PUT with the same key and the same payload returns the original record and applies nothing twice; the same key with a different payload fails with 409 idempotency_key_reused. A write that lands while a channel sync is still in progress fails with 409 sync_in_progress; retry once the sync completes.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Positive property database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Required | Display name, 2 to 100 characters. |
timezone | string | Required | IANA time zone. Other read fields sent back on round-trip are ignored. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Property | Required | The requested property. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable property ID. |
data.code | string | Required | Property code. |
data.name | string | Required | Display name. |
data.timezone | string | Required | IANA time zone. |
data.status | 'active' | 'inactive' | Required | Property status. |
data.updatedAt | string (date-time) | Required | Last property change time. |
data.inventory | object | Required | Property inventory summary. |
data.inventory.maxGuests | integer | Required | Maximum occupancy across active room types. |
data.inventory.physicalUnits | integer | Required | Number of active physical units. |
data.inventory.strategies | string[] | Required | Inventory strategies used by active pools. |
data.channels | string[] | Required | Active channel names. |
data.startingRate | object | null | Required | Lowest active starting rate, or null when no rate exists. |
data.startingRate.amountMinor | string | Conditional | Required when startingRate is an object. Amount in the currency minor unit. |
data.startingRate.currency | string | Conditional | Required when startingRate is an object. Three-letter currency code. |
GET /properties/{propertyId}/rooms
Return one stable page of room types for one property, each with its physical units. Inactive records stay in the response with status inactive.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Positive property database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
updated_after | string (date-time) | Optional | Return records changed after this ISO 8601 date and time. |
| Field | Type | Required | Description |
|---|---|---|---|
data | RoomType[] | Required | A stable page of room type records, each with its physical units. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable room type ID. |
data[].code | string | Required | Room type code. |
data[].name | string | Required | Room type display name. |
data[].status | 'active' | 'inactive' | Required | Room type status. |
data[].maxOccupancy | integer | Required | Maximum occupancy. |
data[].bedrooms | integer | Required | Bedroom count. |
data[].bathrooms | integer | Required | Bathroom count. |
data[].updatedAt | string (date-time) | Required | Last room type or physical unit change time. |
data[].units | object[] | Required | Physical units of this room type. |
data[].units[].id | string | Required | Stable physical unit ID. |
data[].units[].code | string | Required | Physical unit code. |
data[].units[].name | string | Required | Physical unit display name. |
data[].units[].floor | string | null | Required | Floor label, or null. |
data[].units[].status | 'active' | 'inactive' | Required | Physical unit status. |
GET /properties/{propertyId}/rate-plans
Return one stable page of rate plans for one property. This endpoint requires the rate-plans:read scope.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Positive property database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
updated_after | string (date-time) | Optional | Return records changed after this ISO 8601 date and time. |
| Field | Type | Required | Description |
|---|---|---|---|
data | RatePlan[] | Required | A stable page of rate plan records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable rate plan ID. |
data[].code | string | Required | Rate plan code. |
data[].name | string | Required | Rate plan display name. |
data[].status | 'active' | 'inactive' | Required | Rate plan status. |
data[].updatedAt | string (date-time) | Required | Last rate plan or inventory pool change time. |
data[].inventoryPool | object | Required | Inventory pool this rate plan prices. |
data[].inventoryPool.id | string | Required | Stable inventory pool ID. |
data[].inventoryPool.code | string | Required | Inventory pool code. |
data[].inventoryPool.name | string | Required | Inventory pool display name. |
data[].inventoryPool.strategy | 'pooled' | 'fixed_unit' | 'entitlement' | Required | Inventory strategy of the pool. |
data[].inventoryPool.roomTypeId | string | Required | Room type the pool sells. |
data[].baseRate | object | Required | Default nightly rate. |
data[].baseRate.amountMinor | string | Required | Amount in the currency minor unit. |
data[].baseRate.currency | string | Required | Three-letter currency code. |
data[].includedOccupancy | integer | Required | Guests included in the base rate. |
data[].extraGuestRate | object | Required | Nightly rate for each extra guest. |
data[].extraGuestRate.amountMinor | string | Required | Amount in the currency minor unit. |
data[].extraGuestRate.currency | string | Required | Three-letter currency code. |
PUT /properties/{propertyId}/rate-plans
Create and update rate plans for one property. This endpoint requires the rate-plans:write scope. The body is an array of rate plan entries shaped like the read rows.
Each entry is an upsert keyed by id: an entry with an id replaces that plan’s fields — nights that inherit the base rate follow the new rate — and an entry without an id creates a plan under inventoryPool.id. Plans not mentioned stay untouched. Changes queue to the channel sync outbox and propagate to connected channels asynchronously.
Send an Idempotency-Key header to make retries safe: a repeated PUT with the same key and the same payload returns the original summary and applies nothing twice; the same key with a different payload fails with 409 idempotency_key_reused. A write that lands while a channel sync is still in progress fails with 409 sync_in_progress; retry once the sync completes.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Positive property database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
ratePlans[].id | string | Optional | Rate plan ID to update. Omit to create a rate plan. |
ratePlans[].code | string | Required | Rate plan code, unique within its inventory pool. 2–40 letters, numbers, or hyphens. |
ratePlans[].name | string | Required | Rate plan display name, 2 to 100 characters. |
ratePlans[].status | string | Required | Only active is writable. inactive is accepted on plans already inactive; archiving is not supported. |
ratePlans[].inventoryPool.id | string | Conditional | Inventory pool ID the plan prices. Required when creating; on update it must match the plan’s pool. Other read fields on inventoryPool are ignored. |
ratePlans[].baseRate | object | Required | amountMinor/currency pair for the default nightly rate. All rate plans on one property share one currency. |
ratePlans[].includedOccupancy | integer | Required | Guests included in the base rate, 1 to 500. |
ratePlans[].extraGuestRate | object | null | Required | amountMinor/currency pair for each extra guest, or null for no extra-guest rate. |
| Field | Type | Required | Description |
|---|---|---|---|
data | RatePlansWriteResult | Required | The applied rate-plans write summary. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.propertyId | string | Required | Property the rate-plans write applied to. |
data.plansWritten | integer | Required | Rate plan entries applied by the write. |
GET /properties/{propertyId}/calendar
Return per-day availability, lowest rate, and minimum stay for every active inventory pool of one property. This endpoint requires the calendar:read scope. The range spans at most 92 days and defaults to the next 31 days in the property time zone. Dates accept years 1 through 9999. The response is limited to 2000 rows (dates × active pools); larger requests fail with calendar_result_too_large, so narrow the range or pass pool_id.
availableUnits subtracts reservations and availability blocks from the sellable count and is 0 on closed dates. rate and minStay come from the lowest-priced sellable rate plan; both are null when no active plan sells the date, and stopSell is true when every active plan is stop-sold.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Positive property database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
from | string (date) | Optional | First stay date, inclusive. The default is today in the property time zone. |
to | string (date) | Optional | Last stay date, inclusive. The default is 30 days after from; the range can span at most 92 days. |
pool_id | string | Optional | Return rows for one inventory pool ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | CalendarDay[] | Required | One row per active inventory pool per stay date in the range. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data[].date | string (date) | Required | Stay date in YYYY-MM-DD format. |
data[].inventoryPool | object | Required | Inventory pool this row describes. |
data[].inventoryPool.id | string | Required | Stable inventory pool ID. |
data[].inventoryPool.code | string | Required | Inventory pool code. |
data[].inventoryPool.name | string | Required | Inventory pool display name. |
data[].inventoryPool.strategy | 'pooled' | 'fixed_unit' | 'entitlement' | Required | Inventory strategy of the pool. |
data[].inventoryPool.roomTypeId | string | Required | Room type the pool sells. |
data[].availableUnits | integer | Required | Units left after reservations and blocks; 0 when the pool is closed. |
data[].closed | boolean | Required | Whether the pool is closed on this date. |
data[].stopSell | boolean | Required | Whether every active rate plan is stop-sold on this date. |
data[].rate | object | null | Required | Lowest nightly rate across sellable active rate plans, or null when none sells. |
data[].rate.amountMinor | string | Conditional | Required when rate is an object. Amount in the currency minor unit. |
data[].rate.currency | string | Conditional | Required when rate is an object. Three-letter currency code. |
data[].minStay | integer | null | Required | Minimum stay of the lowest sellable rate plan, or null when no rate exists. |
PUT /properties/{propertyId}/calendar
Bulk-update per-day availability, rates, and restrictions for one property. This endpoint requires the calendar:write scope. The body is an array of day entries shaped like the read rows.
Each entry is an upsert: days not mentioned stay untouched, and a null rate or minStay leaves the stored value unchanged. Without ratePlanId an entry writes every active rate plan on the pool; with it, only that plan’s nightly state changes. Entries for the same pool and date may target different rate plans, but their pool-level fields (availableUnits, closed) must agree, and a pool-level entry cannot share a date with targeted entries. availableUnits is the target availability — reservations and blocks are added back when the sellable count is stored. A request can form at most 90 disjoint date ranges in total; batch genuinely sparse updates into multiple requests. Changes queue to the channel sync outbox and propagate to connected channels asynchronously.
Send an Idempotency-Key header to make retries safe: a repeated PUT with the same key and the same payload returns the original summary and applies nothing twice; the same key with a different payload fails with 409 idempotency_key_reused.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Positive property database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
days[].date | string (date) | Required | Stay date in YYYY-MM-DD format. |
days[].inventoryPool.id | string | Required | Inventory pool ID this entry writes. Other read fields on inventoryPool are ignored. |
days[].ratePlanId | string | Optional | Active rate plan ID on the pool to write. Omit to write every active rate plan on the pool. Entries sharing a pool and date must target different plans with matching pool-level fields. |
days[].availableUnits | integer | Required | Target available units after reservations and blocks. |
days[].closed | boolean | Required | Whether the pool is closed on this date. |
days[].stopSell | boolean | Required | Whether active rate plans stop selling this date. |
days[].rate | object | null | Required | amountMinor/currency pair — the amount must be positive — or null to leave the stored rate unchanged. |
days[].minStay | integer | null | Required | Minimum stay, or null to leave the stored value unchanged. |
| Field | Type | Required | Description |
|---|---|---|---|
data | CalendarWriteResult | Required | The applied calendar write summary. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.propertyId | string | Required | Property the calendar write applied to. |
data.daysApplied | integer | Required | Per-day entries applied by the write. |
Reservations
Reservation endpoints require the reservations:read scope. Required response fields are always present; nullable fields include null in their type.
items lists the booked room lines of the reservation. Line totals are the booked amounts in the currency the nights were priced under; an item cancelled before booked totals were recorded returns total null.
Money uses amountMinor strings and 3-letter currency codes. This format prevents floating-point errors.
GET /reservations
Return one stable page of reservations.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
updated_after | string (date-time) | Optional | Return records changed after this ISO 8601 date and time. |
property_id | string | Optional | Return reservations for one property ID. |
arrival_from | string (date) | Optional | Return arrivals on or after this YYYY-MM-DD date. |
arrival_to | string (date) | Optional | Return arrivals on or before this YYYY-MM-DD date. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Reservation[] | Required | A stable page of reservation records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable reservation ID. |
data[].confirmationCode | string | Required | Guest-facing confirmation code. |
data[].status | 'pending' | 'confirmed' | 'in_house' | 'completed' | 'cancelled' | Required | Reservation lifecycle status. |
data[].updatedAt | string (date-time) | Required | Last reservation change time. |
data[].guest | object | Required | Guest contact summary. |
data[].guest.name | string | Required | Guest name. |
data[].guest.email | string | null | Required | Guest email address, or null. |
data[].guest.phone | string | null | Required | Guest phone number, or null. |
data[].property | object | Required | Reserved property summary. |
data[].property.id | string | Required | Property ID. |
data[].property.name | string | Required | Property name. |
data[].stay | object | Required | Stay dates and length. |
data[].stay.arrivalDate | string (date) | Required | Arrival date in YYYY-MM-DD format. |
data[].stay.departureDate | string (date) | Required | Departure date in YYYY-MM-DD format. |
data[].stay.nights | integer | Required | Number of nights. |
data[].occupancy | object | Required | Guest and room counts. |
data[].occupancy.adults | integer | Required | Adult count. |
data[].occupancy.children | integer | Required | Child count. |
data[].occupancy.rooms | integer | Required | Booked room quantity. |
data[].total | object | Required | Reservation total. |
data[].total.amountMinor | string | Required | Amount in the currency minor unit. |
data[].total.currency | string | Required | Three-letter currency code. |
data[].source | object | Required | Reservation origin. |
data[].source.type | 'direct' | 'channel' | Required | Whether the reservation was direct or arrived from a channel. |
data[].source.channel | string | Conditional | Required when source.type is channel. |
data[].items | object[] | Required | Booked room lines with per-line totals from their nightly rates. |
data[].items[].id | string | Required | Stable reservation item ID. |
data[].items[].status | 'pending' | 'confirmed' | 'cancelled' | Required | Item lifecycle status. |
data[].items[].checkInDate | string (date) | Required | Check-in date in YYYY-MM-DD format. |
data[].items[].checkOutDate | string (date) | Required | Check-out date in YYYY-MM-DD format. |
data[].items[].nights | integer | Required | Number of nights. |
data[].items[].quantity | integer | Required | Booked room quantity. |
data[].items[].adults | integer | Required | Adult count. |
data[].items[].children | integer | Required | Child count. |
data[].items[].inventoryPoolId | string | Required | Inventory pool the item books. |
data[].items[].ratePlanId | string | Required | Rate plan the item is priced with. |
data[].items[].total | object | null | Required | Booked item total in the currency the nights were priced under; null only for items cancelled before booked totals were recorded. |
data[].items[].total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data[].items[].total.currency | string | Conditional | Required when total is an object. Three-letter currency code. |
GET /reservations/{reservationId}
Return one reservation from the API key workspace.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
reservationId | string | Required | Positive reservation database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Reservation | Required | The requested reservation. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable reservation ID. |
data.confirmationCode | string | Required | Guest-facing confirmation code. |
data.status | 'pending' | 'confirmed' | 'in_house' | 'completed' | 'cancelled' | Required | Reservation lifecycle status. |
data.updatedAt | string (date-time) | Required | Last reservation change time. |
data.guest | object | Required | Guest contact summary. |
data.guest.name | string | Required | Guest name. |
data.guest.email | string | null | Required | Guest email address, or null. |
data.guest.phone | string | null | Required | Guest phone number, or null. |
data.property | object | Required | Reserved property summary. |
data.property.id | string | Required | Property ID. |
data.property.name | string | Required | Property name. |
data.stay | object | Required | Stay dates and length. |
data.stay.arrivalDate | string (date) | Required | Arrival date in YYYY-MM-DD format. |
data.stay.departureDate | string (date) | Required | Departure date in YYYY-MM-DD format. |
data.stay.nights | integer | Required | Number of nights. |
data.occupancy | object | Required | Guest and room counts. |
data.occupancy.adults | integer | Required | Adult count. |
data.occupancy.children | integer | Required | Child count. |
data.occupancy.rooms | integer | Required | Booked room quantity. |
data.total | object | Required | Reservation total. |
data.total.amountMinor | string | Required | Amount in the currency minor unit. |
data.total.currency | string | Required | Three-letter currency code. |
data.source | object | Required | Reservation origin. |
data.source.type | 'direct' | 'channel' | Required | Whether the reservation was direct or arrived from a channel. |
data.source.channel | string | Conditional | Required when source.type is channel. |
data.items | object[] | Required | Booked room lines with per-line totals from their nightly rates. |
data.items[].id | string | Required | Stable reservation item ID. |
data.items[].status | 'pending' | 'confirmed' | 'cancelled' | Required | Item lifecycle status. |
data.items[].checkInDate | string (date) | Required | Check-in date in YYYY-MM-DD format. |
data.items[].checkOutDate | string (date) | Required | Check-out date in YYYY-MM-DD format. |
data.items[].nights | integer | Required | Number of nights. |
data.items[].quantity | integer | Required | Booked room quantity. |
data.items[].adults | integer | Required | Adult count. |
data.items[].children | integer | Required | Child count. |
data.items[].inventoryPoolId | string | Required | Inventory pool the item books. |
data.items[].ratePlanId | string | Required | Rate plan the item is priced with. |
data.items[].total | object | null | Required | Booked item total in the currency the nights were priced under; null only for items cancelled before booked totals were recorded. |
data.items[].total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.items[].total.currency | string | Conditional | Required when total is an object. Three-letter currency code. |
POST /reservations
Create one direct reservation. This endpoint requires the reservations:write scope. The body mirrors the read row: guest, stay, occupancy, and one items line with the ratePlanId to book.
The rate plan, its inventory pool, and the property must be active, and a channel-mapped (OTA) rate plan cannot take a direct booking. The total prices from the plan’s base rate for every night. Inventory allocates inside the same transaction and the availability change queues to the channel sync outbox asynchronously. Owner (entitlement) inventory cannot be booked through this endpoint.
Capacity failures return 400 insufficient_inventory. Send an Idempotency-Key header to make retries safe: a repeated POST with the same key and the same payload returns the original reservation instead of booking twice; the same key with a different payload fails with 409 idempotency_key_reused.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
guest.name | string | Required | Guest name, 2 to 120 characters. |
guest.email | string | null | Required | Guest email address, or null. |
stay.arrivalDate | string (date) | Required | Arrival date in YYYY-MM-DD format. |
stay.departureDate | string (date) | Required | Departure date in YYYY-MM-DD format, 1 to 365 nights after arrival. |
occupancy.adults | integer | Required | Adult count, 1 to 500. Adults plus children must fit the room capacity. |
occupancy.children | integer | Required | Child count, 0 to 500. |
occupancy.rooms | integer | Required | Booked room quantity, 1 to 100. |
items[].ratePlanId | string | Required | Rate plan the line books. Exactly one line; other read fields on items are ignored. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Reservation | Required | The stored reservation after the write. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable reservation ID. |
data.confirmationCode | string | Required | Guest-facing confirmation code. |
data.status | 'pending' | 'confirmed' | 'in_house' | 'completed' | 'cancelled' | Required | Reservation lifecycle status. |
data.updatedAt | string (date-time) | Required | Last reservation change time. |
data.guest | object | Required | Guest contact summary. |
data.guest.name | string | Required | Guest name. |
data.guest.email | string | null | Required | Guest email address, or null. |
data.guest.phone | string | null | Required | Guest phone number, or null. |
data.property | object | Required | Reserved property summary. |
data.property.id | string | Required | Property ID. |
data.property.name | string | Required | Property name. |
data.stay | object | Required | Stay dates and length. |
data.stay.arrivalDate | string (date) | Required | Arrival date in YYYY-MM-DD format. |
data.stay.departureDate | string (date) | Required | Departure date in YYYY-MM-DD format. |
data.stay.nights | integer | Required | Number of nights. |
data.occupancy | object | Required | Guest and room counts. |
data.occupancy.adults | integer | Required | Adult count. |
data.occupancy.children | integer | Required | Child count. |
data.occupancy.rooms | integer | Required | Booked room quantity. |
data.total | object | Required | Reservation total. |
data.total.amountMinor | string | Required | Amount in the currency minor unit. |
data.total.currency | string | Required | Three-letter currency code. |
data.source | object | Required | Reservation origin. |
data.source.type | 'direct' | 'channel' | Required | Whether the reservation was direct or arrived from a channel. |
data.source.channel | string | Conditional | Required when source.type is channel. |
data.items | object[] | Required | Booked room lines with per-line totals from their nightly rates. |
data.items[].id | string | Required | Stable reservation item ID. |
data.items[].status | 'pending' | 'confirmed' | 'cancelled' | Required | Item lifecycle status. |
data.items[].checkInDate | string (date) | Required | Check-in date in YYYY-MM-DD format. |
data.items[].checkOutDate | string (date) | Required | Check-out date in YYYY-MM-DD format. |
data.items[].nights | integer | Required | Number of nights. |
data.items[].quantity | integer | Required | Booked room quantity. |
data.items[].adults | integer | Required | Adult count. |
data.items[].children | integer | Required | Child count. |
data.items[].inventoryPoolId | string | Required | Inventory pool the item books. |
data.items[].ratePlanId | string | Required | Rate plan the item is priced with. |
data.items[].total | object | null | Required | Booked item total in the currency the nights were priced under; null only for items cancelled before booked totals were recorded. |
data.items[].total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.items[].total.currency | string | Conditional | Required when total is an object. Three-letter currency code. |
PUT /reservations/{reservationId}
Replace the writable fields of one direct reservation. This endpoint requires the reservations:write scope. The body is the same shape as the create body; the stored allocation moves to the new dates, rate plan, and room quantity, and the total reprices.
Channel reservations must be changed in the connected channel (400 channel_managed). Cancelled, started, or completed reservations cannot be changed, and reservations with assigned units or multiple item records need the dashboard.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
reservationId | string | Required | Positive reservation database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
guest.name | string | Required | Guest name, 2 to 120 characters. |
guest.email | string | null | Required | Guest email address, or null. |
stay.arrivalDate | string (date) | Required | Arrival date in YYYY-MM-DD format. |
stay.departureDate | string (date) | Required | Departure date in YYYY-MM-DD format, 1 to 365 nights after arrival. |
occupancy.adults | integer | Required | Adult count, 1 to 500. Adults plus children must fit the room capacity. |
occupancy.children | integer | Required | Child count, 0 to 500. |
occupancy.rooms | integer | Required | Booked room quantity, 1 to 100. |
items[].ratePlanId | string | Required | Rate plan the line books. Exactly one line; other read fields on items are ignored. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Reservation | Required | The stored reservation after the write. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable reservation ID. |
data.confirmationCode | string | Required | Guest-facing confirmation code. |
data.status | 'pending' | 'confirmed' | 'in_house' | 'completed' | 'cancelled' | Required | Reservation lifecycle status. |
data.updatedAt | string (date-time) | Required | Last reservation change time. |
data.guest | object | Required | Guest contact summary. |
data.guest.name | string | Required | Guest name. |
data.guest.email | string | null | Required | Guest email address, or null. |
data.guest.phone | string | null | Required | Guest phone number, or null. |
data.property | object | Required | Reserved property summary. |
data.property.id | string | Required | Property ID. |
data.property.name | string | Required | Property name. |
data.stay | object | Required | Stay dates and length. |
data.stay.arrivalDate | string (date) | Required | Arrival date in YYYY-MM-DD format. |
data.stay.departureDate | string (date) | Required | Departure date in YYYY-MM-DD format. |
data.stay.nights | integer | Required | Number of nights. |
data.occupancy | object | Required | Guest and room counts. |
data.occupancy.adults | integer | Required | Adult count. |
data.occupancy.children | integer | Required | Child count. |
data.occupancy.rooms | integer | Required | Booked room quantity. |
data.total | object | Required | Reservation total. |
data.total.amountMinor | string | Required | Amount in the currency minor unit. |
data.total.currency | string | Required | Three-letter currency code. |
data.source | object | Required | Reservation origin. |
data.source.type | 'direct' | 'channel' | Required | Whether the reservation was direct or arrived from a channel. |
data.source.channel | string | Conditional | Required when source.type is channel. |
data.items | object[] | Required | Booked room lines with per-line totals from their nightly rates. |
data.items[].id | string | Required | Stable reservation item ID. |
data.items[].status | 'pending' | 'confirmed' | 'cancelled' | Required | Item lifecycle status. |
data.items[].checkInDate | string (date) | Required | Check-in date in YYYY-MM-DD format. |
data.items[].checkOutDate | string (date) | Required | Check-out date in YYYY-MM-DD format. |
data.items[].nights | integer | Required | Number of nights. |
data.items[].quantity | integer | Required | Booked room quantity. |
data.items[].adults | integer | Required | Adult count. |
data.items[].children | integer | Required | Child count. |
data.items[].inventoryPoolId | string | Required | Inventory pool the item books. |
data.items[].ratePlanId | string | Required | Rate plan the item is priced with. |
data.items[].total | object | null | Required | Booked item total in the currency the nights were priced under; null only for items cancelled before booked totals were recorded. |
data.items[].total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.items[].total.currency | string | Conditional | Required when total is an object. Three-letter currency code. |
POST /reservations/{reservationId}/cancel
Cancel one direct reservation and release its inventory. This endpoint requires the reservations:write scope. Cancelling an already cancelled reservation succeeds without changing anything.
Channel reservations must be cancelled in the connected channel (400 channel_managed), and completed reservations cannot be cancelled (400 reservation_completed). The release queues to the channel sync outbox asynchronously.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
reservationId | string | Required | Positive reservation database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Reservation | Required | The stored reservation after the write. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable reservation ID. |
data.confirmationCode | string | Required | Guest-facing confirmation code. |
data.status | 'pending' | 'confirmed' | 'in_house' | 'completed' | 'cancelled' | Required | Reservation lifecycle status. |
data.updatedAt | string (date-time) | Required | Last reservation change time. |
data.guest | object | Required | Guest contact summary. |
data.guest.name | string | Required | Guest name. |
data.guest.email | string | null | Required | Guest email address, or null. |
data.guest.phone | string | null | Required | Guest phone number, or null. |
data.property | object | Required | Reserved property summary. |
data.property.id | string | Required | Property ID. |
data.property.name | string | Required | Property name. |
data.stay | object | Required | Stay dates and length. |
data.stay.arrivalDate | string (date) | Required | Arrival date in YYYY-MM-DD format. |
data.stay.departureDate | string (date) | Required | Departure date in YYYY-MM-DD format. |
data.stay.nights | integer | Required | Number of nights. |
data.occupancy | object | Required | Guest and room counts. |
data.occupancy.adults | integer | Required | Adult count. |
data.occupancy.children | integer | Required | Child count. |
data.occupancy.rooms | integer | Required | Booked room quantity. |
data.total | object | Required | Reservation total. |
data.total.amountMinor | string | Required | Amount in the currency minor unit. |
data.total.currency | string | Required | Three-letter currency code. |
data.source | object | Required | Reservation origin. |
data.source.type | 'direct' | 'channel' | Required | Whether the reservation was direct or arrived from a channel. |
data.source.channel | string | Conditional | Required when source.type is channel. |
data.items | object[] | Required | Booked room lines with per-line totals from their nightly rates. |
data.items[].id | string | Required | Stable reservation item ID. |
data.items[].status | 'pending' | 'confirmed' | 'cancelled' | Required | Item lifecycle status. |
data.items[].checkInDate | string (date) | Required | Check-in date in YYYY-MM-DD format. |
data.items[].checkOutDate | string (date) | Required | Check-out date in YYYY-MM-DD format. |
data.items[].nights | integer | Required | Number of nights. |
data.items[].quantity | integer | Required | Booked room quantity. |
data.items[].adults | integer | Required | Adult count. |
data.items[].children | integer | Required | Child count. |
data.items[].inventoryPoolId | string | Required | Inventory pool the item books. |
data.items[].ratePlanId | string | Required | Rate plan the item is priced with. |
data.items[].total | object | null | Required | Booked item total in the currency the nights were priced under; null only for items cancelled before booked totals were recorded. |
data.items[].total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.items[].total.currency | string | Conditional | Required when total is an object. Three-letter currency code. |
Tasks
Read endpoints require the tasks:read scope; write endpoints require tasks:write. Required response fields are always present; nullable fields include null in their type.
Tasks embed stable IDs only, so list pages never go stale when a name changes: resolve property names through GET /properties. Tasks without a property link return property and reservationId as null. Tasks without an assignee return assignee as null.
Test keys cannot create or update tasks. Writes with a test key return sandbox_read_only.
GET /tasks
Return one stable page of tasks.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
updated_after | string (date-time) | Optional | Return records changed after this ISO 8601 date and time. |
status | 'open' | 'in_progress' | 'completed' | 'cancelled' | 'all' | Optional | Filter by task status. The default is all. |
property_id | string | Optional | Return tasks for one property ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Task[] | Required | A stable page of task records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable task ID. |
data[].title | string | Required | Task title. |
data[].description | string | null | Required | Task description, or null. |
data[].category | 'cleaning' | 'maintenance' | 'guest' | 'inspection' | 'listing' | 'operations' | Required | Task category. |
data[].priority | 'low' | 'normal' | 'high' | 'urgent' | Required | Task priority. |
data[].status | 'open' | 'in_progress' | 'completed' | 'cancelled' | Required | Task status. |
data[].source | 'manual' | 'automation' | Required | Whether the task was created manually or by an automation rule. |
data[].dueAt | string (date-time) | null | Required | When the task is due, or null. |
data[].property | object | null | Required | Linked property, or null. Resolve names via the properties endpoint. |
data[].property.id | string | Conditional | Required when property is an object. Property ID. |
data[].reservationId | string | null | Required | Linked reservation ID, or null. |
data[].assignee | object | null | Required | Assigned workspace member, or null. |
data[].assignee.id | string | Conditional | Required when assignee is an object. Workspace member user ID. |
data[].createdAt | string (date-time) | Required | Task creation time. |
data[].updatedAt | string (date-time) | Required | Last task change time. |
POST /tasks
Create a task. Send an Idempotency-Key header to make retries safe: a repeated POST with the same key and the same payload returns 200 with the original task and creates nothing new; the same key with a different payload fails with 409 idempotency_key_reused.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes create retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Required | Task title, 2 to 200 characters. |
category | 'cleaning' | 'maintenance' | 'guest' | 'inspection' | 'listing' | 'operations' | Required | Task category. |
priority | 'low' | 'normal' | 'high' | 'urgent' | Required | Task priority. |
description | string | null | Optional | Task description, up to 2,000 characters. |
dueAt | string (date-time) | null | Optional | When the task is due; a time-zone offset is allowed. |
propertyId | string | null | Optional | Positive property database ID. |
reservationId | string | null | Optional | Positive reservation database ID. Requires propertyId. |
assigneeUserId | string | null | Optional | Assigned workspace member user ID, 1 to 255 characters. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Task | Required | The created task. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable task ID. |
data.title | string | Required | Task title. |
data.description | string | null | Required | Task description, or null. |
data.category | 'cleaning' | 'maintenance' | 'guest' | 'inspection' | 'listing' | 'operations' | Required | Task category. |
data.priority | 'low' | 'normal' | 'high' | 'urgent' | Required | Task priority. |
data.status | 'open' | 'in_progress' | 'completed' | 'cancelled' | Required | Task status. |
data.source | 'manual' | 'automation' | Required | Whether the task was created manually or by an automation rule. |
data.dueAt | string (date-time) | null | Required | When the task is due, or null. |
data.property | object | null | Required | Linked property, or null. Resolve names via the properties endpoint. |
data.property.id | string | Conditional | Required when property is an object. Property ID. |
data.reservationId | string | null | Required | Linked reservation ID, or null. |
data.assignee | object | null | Required | Assigned workspace member, or null. |
data.assignee.id | string | Conditional | Required when assignee is an object. Workspace member user ID. |
data.createdAt | string (date-time) | Required | Task creation time. |
data.updatedAt | string (date-time) | Required | Last task change time. |
GET /tasks/{taskId}
Return one task from the API key workspace.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
taskId | string | Required | Positive task database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Task | Required | The requested task. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable task ID. |
data.title | string | Required | Task title. |
data.description | string | null | Required | Task description, or null. |
data.category | 'cleaning' | 'maintenance' | 'guest' | 'inspection' | 'listing' | 'operations' | Required | Task category. |
data.priority | 'low' | 'normal' | 'high' | 'urgent' | Required | Task priority. |
data.status | 'open' | 'in_progress' | 'completed' | 'cancelled' | Required | Task status. |
data.source | 'manual' | 'automation' | Required | Whether the task was created manually or by an automation rule. |
data.dueAt | string (date-time) | null | Required | When the task is due, or null. |
data.property | object | null | Required | Linked property, or null. Resolve names via the properties endpoint. |
data.property.id | string | Conditional | Required when property is an object. Property ID. |
data.reservationId | string | null | Required | Linked reservation ID, or null. |
data.assignee | object | null | Required | Assigned workspace member, or null. |
data.assignee.id | string | Conditional | Required when assignee is an object. Workspace member user ID. |
data.createdAt | string (date-time) | Required | Task creation time. |
data.updatedAt | string (date-time) | Required | Last task change time. |
PUT /tasks/{taskId}
Replace one task. PUT is a full replacement: an omitted status resets the task to open.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
taskId | string | Required | Positive task database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Required | Task title, 2 to 200 characters. |
category | 'cleaning' | 'maintenance' | 'guest' | 'inspection' | 'listing' | 'operations' | Required | Task category. |
priority | 'low' | 'normal' | 'high' | 'urgent' | Required | Task priority. |
description | string | null | Optional | Task description, up to 2,000 characters. |
dueAt | string (date-time) | null | Optional | When the task is due; a time-zone offset is allowed. |
propertyId | string | null | Optional | Positive property database ID. |
reservationId | string | null | Optional | Positive reservation database ID. Requires propertyId. |
assigneeUserId | string | null | Optional | Assigned workspace member user ID, 1 to 255 characters. |
status | 'open' | 'in_progress' | 'completed' | 'cancelled' | Optional | Full replacement: the default is open. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Task | Required | The requested task. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable task ID. |
data.title | string | Required | Task title. |
data.description | string | null | Required | Task description, or null. |
data.category | 'cleaning' | 'maintenance' | 'guest' | 'inspection' | 'listing' | 'operations' | Required | Task category. |
data.priority | 'low' | 'normal' | 'high' | 'urgent' | Required | Task priority. |
data.status | 'open' | 'in_progress' | 'completed' | 'cancelled' | Required | Task status. |
data.source | 'manual' | 'automation' | Required | Whether the task was created manually or by an automation rule. |
data.dueAt | string (date-time) | null | Required | When the task is due, or null. |
data.property | object | null | Required | Linked property, or null. Resolve names via the properties endpoint. |
data.property.id | string | Conditional | Required when property is an object. Property ID. |
data.reservationId | string | null | Required | Linked reservation ID, or null. |
data.assignee | object | null | Required | Assigned workspace member, or null. |
data.assignee.id | string | Conditional | Required when assignee is an object. Workspace member user ID. |
data.createdAt | string (date-time) | Required | Task creation time. |
data.updatedAt | string (date-time) | Required | Last task change time. |
Conversations
Read endpoints require the conversations:read scope; replies require conversations:write. channel names the sales channel (airbnb, vrbo, direct, or other); internal channel manager identifiers are never exposed.
Test keys cannot send replies. Writes with a test key return sandbox_read_only.
GET /conversations
Return one stable page of conversations, newest activity first.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
updated_after | string (date-time) | Optional | Return records changed after this ISO 8601 date and time. |
status | 'open' | 'closed' | 'all' | Optional | Filter by conversation status. The default is all. |
property_id | string | Optional | Return conversations for one property ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Conversation[] | Required | A stable page of conversation records, newest activity first. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable conversation ID. |
data[].guestName | string | Required | Guest name on the thread. |
data[].subject | string | null | Required | Thread subject, or null. |
data[].status | 'open' | 'closed' | Required | Thread status. |
data[].channel | 'airbnb' | 'vrbo' | 'direct' | 'other' | Required | Sales channel the thread runs on. |
data[].property | object | Required | Property the thread belongs to. |
data[].property.id | string | Required | Property ID. |
data[].property.name | string | Required | Property name. |
data[].reservationId | string | null | Required | Linked reservation ID, or null. |
data[].lastMessageAt | string (date-time) | Required | Last message time. |
data[].lastMessage | object | Required | Last message summary. |
data[].lastMessage.direction | 'inbound' | 'outbound' | Required | Direction of the last message. |
data[].lastMessage.snippet | string | Required | Body of the last message. |
data[].updatedAt | string (date-time) | Required | Last conversation change time. |
GET /conversations/{conversationId}/messages
Return one stable page of messages in chronological order.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
conversationId | string | Required | Positive conversation database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Message[] | Required | A stable page of messages in chronological order. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable message ID. |
data[].direction | 'inbound' | 'outbound' | Required | Message direction. |
data[].senderType | 'guest' | 'staff' | 'system' | Required | Who sent the message. |
data[].senderName | string | null | Required | Staff sender name, or null. |
data[].body | string | Required | Message body. |
data[].occurredAt | string (date-time) | Required | When the message was sent. |
POST /conversations/{conversationId}/messages
Queue a reply for delivery through the channel connection. The 201 response returns the stored message. Replying fails with replies_not_supported when the connection cannot send messages, and with conversation_closed when the thread is closed.
Send an Idempotency-Key header to make retries safe: a repeated POST with the same key and the same payload returns 200 with the original message and queues nothing new; the same key with a different payload fails with 409 idempotency_key_reused.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes create retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
conversationId | string | Required | Positive conversation database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
body | string | Required | Reply body, 1 to 10,000 characters. |
| Field | Type | Required | Description |
|---|---|---|---|
data | Message | Required | The queued reply. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable message ID. |
data.direction | 'inbound' | 'outbound' | Required | Message direction. |
data.senderType | 'guest' | 'staff' | 'system' | Required | Who sent the message. |
data.senderName | string | null | Required | Staff sender name, or null. |
data.body | string | Required | Message body. |
data.occurredAt | string (date-time) | Required | When the message was sent. |
Channels
Channel endpoints require the channels:read scope. Each connection carries its rate plan mappings; a mapping with null external codes is not linked on the sales channel yet.
Connection credentials are never returned. channelActive reports whether the connection is live on the sales channel, and syncState shows a queued or failed channel manager sync.
GET /channels
Return one stable page of channel connections.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
updated_after | string (date-time) | Optional | Return records changed after this ISO 8601 date and time. |
property_id | string | Optional | Return channel connections for one property ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | ChannelConnection[] | Required | A stable page of channel connection records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable channel connection ID. |
data[].title | string | Required | Connection display name. |
data[].channel | string | Required | Sales channel this connection distributes through, or other. |
data[].status | 'draft' | 'pending' | 'active' | 'error' | Required | Connection status. |
data[].channelActive | boolean | Required | Whether the connection is live on the sales channel. |
data[].syncState | 'pending' | 'failed' | Required | Pending channel manager sync state, or null when nothing is queued. |
data[].currency | string | null | Required | Rate currency override, or null. |
data[].property | object | Required | Property this connection distributes. |
data[].property.id | string | Required | Property ID. |
data[].property.name | string | Required | Property name. |
data[].mappings | object[] | Required | Rate plan mappings for this connection. |
data[].mappings[].id | string | Required | Stable channel mapping ID. |
data[].mappings[].ratePlanId | string | Required | Mapped rate plan ID. |
data[].mappings[].ratePlanName | string | Required | Mapped rate plan name. |
data[].mappings[].roomTypeName | string | Required | Room type of the mapped rate plan. |
data[].mappings[].externalRoomCode | string | null | Required | Room code on the sales channel, or null when unmapped. |
data[].mappings[].externalRateCode | string | null | Required | Rate code on the sales channel, or null when unmapped. |
data[].mappings[].primaryOccupancy | boolean | Required | Whether the mapping drives the primary occupancy rate. |
data[].createdAt | string (date-time) | Required | Connection creation time. |
data[].updatedAt | string (date-time) | Required | Last connection change time. |
Webhooks
Webhook endpoints require the webhooks:manage scope. The signing secret appears exactly once, in the create response; list and get responses never return it.
Test keys cannot create, update, or delete webhook endpoints. Writes with a test key return sandbox_read_only.
GET /webhooks
Return one stable page of webhook endpoints, newest first.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
| Field | Type | Required | Description |
|---|---|---|---|
data | WebhookEndpoint[] | Required | A stable page of webhook endpoint records, newest first. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable webhook endpoint ID. |
data[].url | string | Required | Endpoint URL. |
data[].description | string | Required | Endpoint description, or an empty string. |
data[].events | string[] | Required | Subscribed event types. |
data[].status | 'active' | 'disabled' | Required | Endpoint status. |
data[].createdAt | string (date-time) | Required | Endpoint creation time. |
POST /webhooks
Create a webhook endpoint. The URL must be a public https:// address without embedded credentials: loopback, private, link-local, and reserved hosts are rejected at save time, and delivery re-checks DNS answers and every redirect hop before connecting.
Send an Idempotency-Key header to make retries safe. A repeated POST with the same key and the same payload returns 200 with the original endpoint and creates nothing new; the same key with a different payload fails with 409 idempotency_key_reused.
The 201 response is the only one that includes signingSecret. A replayed request returns 200 without the secret.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
Idempotency-Key | string | Optional | 1 to 200 characters. Makes create retries safe. |
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Required | Public https:// endpoint URL. |
events | string[] | Required | Subscribed event types from the event catalog. |
description | string | Optional | Endpoint description. |
enabled | boolean | Optional | Set false to disable the endpoint. The default is true. |
| Field | Type | Required | Description |
|---|---|---|---|
data | WebhookEndpoint | Required | The created webhook endpoint, including its signing secret. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable webhook endpoint ID. |
data.url | string | Required | Endpoint URL. |
data.description | string | Required | Endpoint description, or an empty string. |
data.events | string[] | Required | Subscribed event types. |
data.status | 'active' | 'disabled' | Required | Endpoint status. |
data.createdAt | string (date-time) | Required | Endpoint creation time. |
data.signingSecret | string | Required | Payload signing secret. Returned only in the create response. |
GET /webhooks/{webhookId}
Return one webhook endpoint from the API key workspace.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
webhookId | string | Required | Positive webhook endpoint database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
data | WebhookEndpoint | Required | The requested webhook endpoint. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable webhook endpoint ID. |
data.url | string | Required | Endpoint URL. |
data.description | string | Required | Endpoint description, or an empty string. |
data.events | string[] | Required | Subscribed event types. |
data.status | 'active' | 'disabled' | Required | Endpoint status. |
data.createdAt | string (date-time) | Required | Endpoint creation time. |
PUT /webhooks/{webhookId}
Replace the URL, description, and subscribed events of one webhook endpoint. Set enabled to change the status.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
webhookId | string | Required | Positive webhook endpoint database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Required | Public https:// endpoint URL. |
events | string[] | Required | Subscribed event types from the event catalog. |
description | string | Optional | Endpoint description. |
enabled | boolean | Optional | Set false to disable the endpoint. The default is true. |
| Field | Type | Required | Description |
|---|---|---|---|
data | WebhookEndpoint | Required | The requested webhook endpoint. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data.id | string | Required | Stable webhook endpoint ID. |
data.url | string | Required | Endpoint URL. |
data.description | string | Required | Endpoint description, or an empty string. |
data.events | string[] | Required | Subscribed event types. |
data.status | 'active' | 'disabled' | Required | Endpoint status. |
data.createdAt | string (date-time) | Required | Endpoint creation time. |
DELETE /webhooks/{webhookId}
Delete one webhook endpoint. A successful delete returns 204 with no body.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
webhookId | string | Required | Positive webhook endpoint database ID. |
GET /webhooks/{webhookId}/deliveries
Return one stable page of delivery attempts for the endpoint, newest first.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
webhookId | string | Required | Positive webhook endpoint database ID. |
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Records per page, from 1 through 200. The default is 100. |
cursor | string | Optional | Send meta.page.nextCursor without changing any other filter. |
| Field | Type | Required | Description |
|---|---|---|---|
data | WebhookDelivery[] | Required | A stable page of delivery records, newest first. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
meta.page | object | Required | Cursor pagination state. |
meta.page.hasMore | boolean | Required | Whether another page is available. |
meta.page.limit | integer | Required | The page size applied to this response. |
meta.page.nextCursor | string | null | Required | The cursor for the next page, or null when the page is final. |
meta.page.snapshotAt | string (date-time) | Required | The stable read boundary shared by every page in the cursor chain. |
data[].id | string | Required | Stable delivery ID. |
data[].eventType | 'reservation.created' | 'reservation.updated' | 'reservation.cancelled' | 'message.received' | 'message.sent' | 'property.created' | 'property.updated' | 'task.created' | 'task.updated' | 'calendar.updated' | Required | Delivered event type. |
data[].eventKey | string | Required | Logical event identity; repeated deliveries of one event share it. |
data[].status | 'pending' | 'delivered' | 'failed' | 'exhausted' | Required | Delivery status. |
data[].attemptCount | integer | Required | Delivery attempts so far. |
data[].responseStatus | integer | null | Required | HTTP status the endpoint returned, or null. |
data[].durationMs | integer | null | Required | Last attempt duration in milliseconds, or null. |
data[].nextAttemptAt | string (date-time) | null | Required | Next scheduled retry, or null. |
data[].createdAt | string (date-time) | Required | Delivery creation time. |
Stable cursor pagination
List endpoints return 100 records by default. Set limit from 1 through 200.
If hasMore is true, send nextCursor as the next cursor. Keep all other filters unchanged.
The cursor holds a snapshot boundary. Records that change during a multi-page read do not move between its pages.
One rate limit
Each API key can make 120 requests per minute. Supahost does not combine second, minute, and hour quotas.
RateLimit-Limitshows the key limit.RateLimit-Remainingshows the requests left in the current window.RateLimit-Resetshows the seconds until the window resets.Retry-Afterappears with a429response.
Request audit
Supahost records each authenticated request. The record has the key, route, status, duration, and request ID.
Supahost does not store request bodies, response bodies, credentials, or URL query values in this audit record.