Read provider-neutral property and reservation records through a small, stable contract.
https://supahost.io/api/v1The machine-readable OpenAPI 3.1 schema is available at /api/v1/openapi.json.
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.
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 public property UUID. |
data[].code | string | Required | Property code. |
data[].name | string | Required | Display name. |
data[].timezone | string | Required | IANA time zone. |
data[].lodgingType | string | null | Optional | Accommodation type, or null for an unclassified legacy property. Omitted only in older idempotent replay snapshots. |
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.baseCapacity | integer | Optional | Total base capacity of active inventory pools. Excludes dated entitlement allocations and does not subtract reservations or blocks; use the calendar for date-specific availability. |
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.
Property IDs are UUID strings, including property references in reservations, tasks, conversations, channels, calendar and rate-plan write results, and new webhook events. Keep IDs as opaque strings. Legacy numeric property input is temporarily accepted, but responses always use UUIDs.
Pre-GA identifier transition: refresh your property list and stored references after this release. Start a new property pagination chain; old numeric property cursors return invalid_cursor. Retry writes with the same URL, body and Idempotency-Key to preserve replay behavior. Previously queued webhook events retain their original payload.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Public property UUID. Legacy numeric input is temporarily accepted. |
| 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 public property UUID. |
data.code | string | Required | Property code. |
data.name | string | Required | Display name. |
data.timezone | string | Required | IANA time zone. |
data.lodgingType | string | null | Optional | Accommodation type, or null for an unclassified legacy property. Omitted only in older idempotent replay snapshots. |
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.baseCapacity | integer | Optional | Total base capacity of active inventory pools. Excludes dated entitlement allocations and does not subtract reservations or blocks; use the calendar for date-specific availability. |
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. |
POST /properties
Create a draft property with properties:write. Send name, code, the postal address fields (addressLine, city, state, postalCode, countryCode), timezone, lodgingType, strategy, bedrooms, bathrooms, maxGuests, baseCapacity, and baseRateMinor. The OpenAPI request schema lists supported types and limits.
lodgingType describes the accommodation, such as hotel, apart_hotel, apartment, or villa. strategy independently selects pooled, fixed_unit, or entitlement inventory. baseCapacity is the number of sellable units in the first room type: at least 1, or 0 for entitlement inventory whose capacity comes from dated owner-night allocations. Bedrooms, bathrooms, guest capacity and the USD nightly rate apply per unit.
Returns 201 with the property, first room type, inventory pool and standard rate plan saved atomically. The property stays inactive until activated in the dashboard. Send Idempotency-Key to retry safely. Test keys cannot create properties. inventory.baseCapacity in read responses is the base unit count, not remaining availability; use the calendar for specific dates.
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 | Public property UUID. Legacy numeric input is temporarily accepted. |
| 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 public property UUID. |
data.code | string | Required | Property code. |
data.name | string | Required | Display name. |
data.timezone | string | Required | IANA time zone. |
data.lodgingType | string | null | Optional | Accommodation type, or null for an unclassified legacy property. Omitted only in older idempotent replay snapshots. |
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.baseCapacity | integer | Optional | Total base capacity of active inventory pools. Excludes dated entitlement allocations and does not subtract reservations or blocks; use the calendar for date-specific availability. |
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 | Public property UUID. Legacy numeric input is temporarily accepted. |
| 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 | Public property UUID. Legacy numeric input is temporarily accepted. |
| 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. |
data[].weeklyDiscountPercent | number | null | Required | Percent off the accommodation for direct stays of 7 or more nights, or null for none. |
data[].monthlyDiscountPercent | number | null | Required | Percent off the accommodation for direct stays of 28 or more nights, or null for none. The larger tier applies. |
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, so 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 | Public property UUID. Legacy numeric input is temporarily accepted. |
| 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 to 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. |
ratePlans[].weeklyDiscountPercent | number | null | Optional | Percent off the accommodation for direct stays of 7 or more nights, 0 to 100 with at most two decimals. Omit to leave unchanged; null or 0 clears it. Not sent to channels. |
ratePlans[].monthlyDiscountPercent | number | null | Optional | Percent off the accommodation for direct stays of 28 or more nights. When both tiers qualify the larger one applies. |
| 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 | Public UUID of the property the rate-plans write applied to. |
data.plansWritten | integer | Required | Rate plan entries applied by the write. |
Protected closures
A normal closed date or availability block is editable. A protected closure adds a durable guard for one inventory pool and stay date. It closes the pool, sets stop sell on every active rate plan, and prevents ordinary API, import, agent and dashboard calendar edits from reopening it. It also prevents removal of existing closed-to-arrival and closed-to-departure flags. It does not turn those flags on automatically.
Protection preserves bookings, reserved and sellable quantities, prices and other restrictions. Its channel update contains only stop sell and existing true arrival/departure flags. It does not publish prices or stay-length rules, or clear channel flags that are false locally. Derived channel plans keep their inherited prices. Booking modifications and cancellations can still update reserved quantities without reopening the date. This is closure protection, not a price freeze or reservation lock.
Protection is enforced in the database and checked again before queued Supahost channel writes. A stale queued reopening is superseded by current closed state. A provider request already in flight finishes before protection commits; the closure is then queued. HTTP 200 proves the Supahost change committed, not that the connected channel has acknowledged delivery. Verify channel delivery separately.
Protection stays active until explicitly removed; there is no automatic expiry. It cannot control direct edits made in the channel manager or an OTA, another application that bypasses Supahost, or privileged database administration. Keep one authorized channel writer for the protected scope.
Writes require the opt-in calendar-protections:write scope, separately from calendar:write. Existing keys do not gain this scope. The key creator must remain an active workspace member with availability.manage permission, including on idempotent retries. Missing scope or permission returns 403. Test keys cannot write; their GET response is an empty sandbox collection.
GET /properties/{propertyId}/calendar/protections
Requires calendar:read. Supply one inventory pool and an inclusive range of 1 to 366 dates. Returns every active protection in that range, ordered by stay date, with no truncation. An unprotected range returns data: []. Unknown properties or pools return 404.
Send Authorization: Bearer $SUPAHOST_API_KEY. For POST and DELETE, use a unique Idempotency-Key (1 to 200 characters) for each intended operation. A retry with the same key and payload replays its original response without changing current state. Reusing a key with different content returns 409 idempotency_key_reused. After removing and re-creating protection, use a new key.
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Public property UUID. Legacy numeric input is temporarily accepted. |
| Field | Type | Required | Description |
|---|---|---|---|
inventoryPoolId | string | Required | One inventory pool on the property. |
startsOn | string (date) | Required | First date, inclusive. Range must span 1 to 366 dates. |
endsOn | string (date) | Required | Last date, inclusive. |
| Field | Type | Required | Description |
|---|---|---|---|
data | CalendarProtection[] | Required | Protection records with id, inventoryPoolId, stayDate, original reason, createdAt and releasedAt. No pagination; at most 366 records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data[].id | string | Required | |
data[].inventoryPoolId | string | Required | |
data[].stayDate | string | Required | |
data[].reason | string | Required | |
data[].createdAt | string (date-time) | Required | |
data[].releasedAt | string (date-time) | null | Required |
POST /properties/{propertyId}/calendar/protections
Writes require the opt-in calendar-protections:write scope, separately from calendar:write. Existing keys do not gain this scope. The key creator must remain an active workspace member with availability.manage permission, including on idempotent retries. Missing scope or permission returns 403. Test keys cannot write; their GET response is an empty sandbox collection.
Send Authorization: Bearer $SUPAHOST_API_KEY. For POST and DELETE, use a unique Idempotency-Key (1 to 200 characters) for each intended operation. A retry with the same key and payload replays its original response without changing current state. Reusing a key with different content returns 409 idempotency_key_reused. After removing and re-creating protection, use a new key.
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Public property UUID. Legacy numeric input is temporarily accepted. |
The strict JSON body requires inventoryPoolId, startsOn, endsOn and a trimmed reason of 2 to 240 characters. Dates must be today or later in the property time zone, span 1 to 366 dates inclusive, and target an active property and non-entitlement pool. Unknown fields and invalid dates return 400 before any mutation. A date already protected keeps its original ID, reason and creator.
curl -X POST "https://supahost.io/api/v1/properties/$PROPERTY_ID/calendar/protections" \
-H "Authorization: Bearer $SUPAHOST_API_KEY" \
-H "Content-Type: application/json" -H "Idempotency-Key: protect-maintenance-1" \
-d '{"inventoryPoolId":"123","startsOn":"2030-10-10","endsOn":"2030-10-12","reason":"Owner maintenance closure"}'| Field | Type | Required | Description |
|---|---|---|---|
data | CalendarProtection[] | Required | Protection records with id, inventoryPoolId, stayDate, original reason, createdAt and releasedAt. No pagination; at most 366 records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data[].id | string | Required | |
data[].inventoryPoolId | string | Required | |
data[].stayDate | string | Required | |
data[].reason | string | Required | |
data[].createdAt | string (date-time) | Required | |
data[].releasedAt | string (date-time) | null | Required |
DELETE /properties/{propertyId}/calendar/protections/{closureId}
Writes require the opt-in calendar-protections:write scope, separately from calendar:write. Existing keys do not gain this scope. The key creator must remain an active workspace member with availability.manage permission, including on idempotent retries. Missing scope or permission returns 403. Test keys cannot write; their GET response is an empty sandbox collection.
Send Authorization: Bearer $SUPAHOST_API_KEY. For POST and DELETE, use a unique Idempotency-Key (1 to 200 characters) for each intended operation. A retry with the same key and payload replays its original response without changing current state. Reusing a key with different content returns 409 idempotency_key_reused. After removing and re-creating protection, use a new key.
Read the current protection, review it, then pass its exact closureId and a strict JSON body containing reason (2 to 240 characters). One call removes one date’s protection. Repeat for each approved date. An already released ID returns 409 closure_changed and cannot remove a replacement protection. An ID outside the property returns 400 invalid_reference.
Removal retains the protection record and its release reason, actor and timestamp for audit. The date remains closed, with stop sell and other restrictions unchanged. To reopen it, make a separate ordinary calendar write after removal. The agent has no unlock tool.
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Public property UUID. Legacy numeric input is temporarily accepted. |
closureId | string (uuid) | Required | Exact UUID of the active protection to remove. |
curl -X DELETE "https://supahost.io/api/v1/properties/$PROPERTY_ID/calendar/protections/$CLOSURE_ID" \
-H "Authorization: Bearer $SUPAHOST_API_KEY" \
-H "Content-Type: application/json" -H "Idempotency-Key: release-maintenance-1" \
-d '{"reason":"Owner approved reopening"}'| Field | Type | Required | Description |
|---|---|---|---|
data | CalendarProtection[] | Required | Protection records with id, inventoryPoolId, stayDate, original reason, createdAt and releasedAt. No pagination; at most 366 records. |
meta | object | Required | Response metadata. |
meta.requestId | string | Required | Support identifier for this request. |
data[].id | string | Required | |
data[].inventoryPoolId | string | Required | |
data[].stayDate | string | Required | |
data[].reason | string | Required | |
data[].createdAt | string (date-time) | Required | |
data[].releasedAt | string (date-time) | null | Required |
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 | Public property UUID. Legacy numeric input is temporarily accepted. |
| 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.
Protected closures cannot be overridden by this endpoint. Reopening inventory or removing protected restrictions returns 409 protected_calendar_closure and rolls back the entire batch. Explicitly remove protection in the calendar or through the protection API first. Removing protection alone leaves the date closed.
Nights locked in the Supahost calendar cannot be written by this endpoint. A request that includes a locked night returns 409 calendar_night_locked and changes nothing. A night is locked when a person locks it, edits it in the calendar on a property the live RentShare feed writes, or when the feed finds it was changed outside the feed. On such a property, a night this endpoint writes is changed outside the feed too: the next feed update locks it, so it keeps your value and later writes to it return 409 until it is unlocked in the calendar. Unlock it in the calendar first.
Unknown fields return HTTP 400 before any change. This also applies inside inventoryPool and rate. Use camelCase names such as maxStay. Null rejects for maxStay, closedToArrival and closedToDeparture. Use zero or false to clear them.
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, and 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 | Public property UUID. Legacy numeric input is temporarily accepted. |
| 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. Optional code, name, strategy and roomTypeId fields are read metadata. Their values do not change the pool. |
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, where 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. |
days[].maxStay | integer | Optional | 0 to 365 nights. Zero removes the limit. Omission preserves the stored value; new nights default to 14. A positive maximum cannot be less than the effective minimum. |
days[].closedToArrival | boolean | Optional | Whether arrivals are closed. Omission preserves the stored value; new nights default to false. |
days[].closedToDeparture | boolean | Optional | Whether departures are closed. Omission preserves the stored value; new nights default to false. |
| 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 | Public UUID of the property the calendar write applied to. |
data.daysApplied | integer | Required | Per-day entries applied by the write. |
GET /properties/{propertyId}/rate-plans/{ratePlanId}/calendar
Verify nightly prices and all restrictions for one active plan with the calendar:read scope. The response includes stop-sold and zero-price nights.
stopSell reports the stored flag. A zero price also prevents sales. rate falls back to the plan base price when no night exists. Other defaults are minimum 1, maximum 14, and false flags. Maximum 0 means unlimited.
Pool availability subtracts reservations and property-local blocks. Closed pools return zero availability while their plan prices and restrictions remain visible.
Both dates are inclusive. The default range spans 31 days from today in the property time zone. The maximum is 92 days. The endpoint returns 404 for an unknown property, mismatched plan, inactive plan or inactive pool. It reads Supahost data and does not verify channel delivery.
| Field | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Send Bearer $SUPAHOST_API_KEY. |
| Field | Type | Required | Description |
|---|---|---|---|
propertyId | string | Required | Public property UUID. Legacy numeric input is temporarily accepted. |
ratePlanId | string | Required | Positive rate plan database ID on this property. |
| 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. |
| Field | Type | Required | Description |
|---|---|---|---|
data | RatePlanCalendarDay[] | Required | One row per stay date for the selected rate plan. |
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 | Stored stop-sell restriction for this plan; false when no night exists. A zero rate also prevents sales. |
data[].rate | object | Required | Stored nightly price with base-price fallback, including zero and stop-sold nights. |
data[].rate.amountMinor | string | Required | |
data[].rate.currency | string | Required | |
data[].minStay | integer | Required | Minimum stay; defaults to 1 when no night exists. |
data[].ratePlanId | string | Required | Rate plan ID this row describes. |
data[].maxStay | integer | Required | Maximum stay; 0 means unlimited. Defaults to 14 when no night exists. |
data[].closedToArrival | boolean | Required | Arrival restriction; defaults to false when no night exists. |
data[].closedToDeparture | boolean | Required | Departure restriction; defaults to false when no night exists. |
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 use the currency recorded for the booked nights. An item without a recorded price returns total null, including older cancelled items.
An imported reservation without a known guest price also returns total null. A free stay returns an amount of "0". Owner payouts do not replace guest prices.
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 public property UUID. Legacy numeric input is temporarily accepted. |
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 | Public property UUID. |
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 | null | Required | Reservation total. Null when the imported guest price is unknown. |
data[].total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data[].total.currency | string | Conditional | Required when total is an object. 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 recorded currency; null when the price is unknown, including older cancelled items. |
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 | Public property UUID. |
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 | null | Required | Reservation total. Null when the imported guest price is unknown. |
data.total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.total.currency | string | Conditional | Required when total is an object. 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 recorded currency; null when the price is unknown, including older cancelled items. |
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 | Public property UUID. |
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 | null | Required | Reservation total. Null when the imported guest price is unknown. |
data.total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.total.currency | string | Conditional | Required when total is an object. 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 recorded currency; null when the price is unknown, including older cancelled items. |
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 | Public property UUID. |
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 | null | Required | Reservation total. Null when the imported guest price is unknown. |
data.total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.total.currency | string | Conditional | Required when total is an object. 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 recorded currency; null when the price is unknown, including older cancelled items. |
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 | Public property UUID. |
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 | null | Required | Reservation total. Null when the imported guest price is unknown. |
data.total.amountMinor | string | Conditional | Required when total is an object. Amount in the currency minor unit. |
data.total.currency | string | Conditional | Required when total is an object. 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 recorded currency; null when the price is unknown, including older cancelled items. |
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. |
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 public property UUID. Legacy numeric input is temporarily accepted. |
| 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 UUID. |
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. Public property UUID. |
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 | Public property UUID. Legacy numeric input is temporarily accepted. |
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 UUID. |
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. Public property UUID. |
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 (uuid) | Required | Task UUID. |
| 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 UUID. |
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. Public property UUID. |
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 (uuid) | Required | Task UUID. |
| 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 | Public property UUID. Legacy numeric input is temporarily accepted. |
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 UUID. |
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. Public property UUID. |
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. |
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 public property UUID. Legacy numeric input is temporarily accepted. |
| 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 UUID. |
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' | 'website' | 'other' | Required | Sales channel the thread runs on. |
data[].property | object | Required | Property the thread belongs to. |
data[].property.id | string | Required | Public property UUID. |
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 UUID. |
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 UUID. |
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. |
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 public property UUID. Legacy numeric input is temporarily accepted. |
| 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 UUID. |
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 | Stable primary associated property. Deprecated: use properties. |
data[].property.id | string | Required | Public property UUID. |
data[].property.name | string | Required | Property name. |
data[].properties | object[] | Required | Properties this account-level connection distributes. |
data[].properties[].id | string | Required | Public property UUID. |
data[].properties[].name | string | Required | Property name. |
data[].mappings | object[] | Required | Rate plan mappings for this connection. |
data[].mappings[].id | string | Required | Stable channel mapping UUID. |
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. |
data[].removedAt | string (date-time) | null | Required | When the account was removed, or null. Only updated_after reads return removed accounts. |
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 UUID. |
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 UUID. |
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 (uuid) | Required | Webhook endpoint UUID. |
| 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 UUID. |
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 (uuid) | Required | Webhook endpoint UUID. |
| 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 UUID. |
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 (uuid) | Required | Webhook endpoint UUID. |
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 (uuid) | Required | Webhook endpoint UUID. |
| 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 UUID. |
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. |
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.
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.
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.