Calendar and iCal feeds
Two related surfaces: a JSON calendar for building your own day-by-day view, and an iCal feed for exporting availability into an OTA. Both are live. If you don’t want to build your own calendar UI, a pre-built, copy-paste version of the JSON calendar is also available — see Embed the calendar.
JSON calendar
Section titled “JSON calendar”GET /v1/resources/{id}/calendar returns one entry per night in the
window: availability status, a price hint, and any active restrictions —
built on the same data as Availability.
curl "https://api.<domain>/v1/resources/<RESOURCE_ID>/calendar?from=2026-08-01T00:00:00Z&to=2026-08-04T00:00:00Z" \ -H "Authorization: Bearer sk_test_..."const { data: calendar, error } = await client.GET("/v1/resources/{id}/calendar", { params: { path: { id: "<RESOURCE_ID>" }, query: { from: "2026-08-01T00:00:00Z", to: "2026-08-04T00:00:00Z" }, },});if (error) throw error;{ "resourceId": "<RESOURCE_ID>", "from": "2026-08-01T00:00:00.000Z", "to": "2026-08-04T00:00:00.000Z", "currency": "IDR", "days": [ { "date": "2026-08-01", "status": "available", "reasons": [], "priceHintMinorUnits": "1500000", "restrictions": { "minStayNights": 2, "maxStayNights": null, "closedToArrival": false, "closedToDeparture": false, "stopSell": false } } ]}Both sk_ and pk_ keys can call this endpoint. priceHintMinorUnits is a
hint only — always price the actual stay with POST /v1/quotes
(see Quotes) before you hold it.
The window is limited to 366 nights per call (400 range_too_large beyond
that). The response carries a strong ETag and Cache-Control: max-age=60
— send If-None-Match on your next request for the same window and expect
a 304 with an empty body when nothing changed:
curl -i "https://api.<domain>/v1/resources/<RESOURCE_ID>/calendar?from=2026-08-01T00:00:00Z&to=2026-08-04T00:00:00Z" \ -H "Authorization: Bearer sk_test_..." \ -H 'If-None-Match: "<etag-from-previous-response>"'iCal feed (export)
Section titled “iCal feed (export)”GET /v1/feeds/{token}.ics exports confirmed direct bookings and any
already-synced external OTA blocks as an iCal feed — busy/free VEVENTs
only, no guest names or contact details.
curl https://api.<domain>/v1/feeds/<TOKEN>.icsBEGIN:VCALENDARVERSION:2.0BEGIN:VEVENTUID:...DTSTART:20260801DTEND:20260804SUMMARY:BookedEND:VEVENTEND:VCALENDARThe token itself is issued per resource with an sk_ key
(channel:manage scope):
curl -X POST https://api.<domain>/v1/resources/<RESOURCE_ID>/feed-tokens \ -H "Authorization: Bearer sk_test_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Airbnb export" }'const { data: feedToken, error } = await client.POST("/v1/resources/{id}/feed-tokens", { params: { path: { id: "<RESOURCE_ID>" } }, body: { name: "Airbnb export" },});if (error) throw error;POST /v1/resources/{id}/feed-tokens returns the full URL exactly once —
copy it immediately, it is never shown again. If you don’t hold an sk_
key yourself, ask your operator contact to issue one for you. Losing a feed
URL means revoking it (DELETE /v1/resources/{id}/feed-tokens/{tokenId})
and issuing a new one — the old URL stops working immediately, and nothing
else about your API keys is affected.
iCal import (bringing an OTA’s calendar in)
Section titled “iCal import (bringing an OTA’s calendar in)”The reverse direction — pulling an OTA’s own calendar in, so a booking made on that OTA blocks the date here too — is set up per channel connection by your operator contact, not through a public endpoint. Once a connection is active, we poll the OTA’s iCal URL on a short cycle and keep both calendars in sync automatically; you don’t need to call anything for this to happen.
What’s still future
Section titled “What’s still future”Direct, self-serve OTA connectivity (for example, a Booking.com Connectivity integration instead of iCal) isn’t available yet. iCal import and export, described above, both work today.
Next steps
Section titled “Next steps”- Embed the calendar — a pre-built, copy-paste version of the JSON calendar above.
- Availability — the underlying reason vocabulary shared with this endpoint.