> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gridbeds.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Synchronisation

> Keep a copy of what is published to you: lists and cursors, updated_since, versions, tombstones, the lifecycle every resource shares, and availability.

<Warning>
  **Preview: nothing is served yet.** This describes the Distribution API contract (version `1.0.0`). Try it against a mock of the contract ([Testing](/en/distribution-api/testing)).
</Warning>

Your channel keeps its own copy of what hosts publish to it, and brings it up to date by asking what changed. Webhooks tell you sooner, but the lists and the event log are the source: anything you missed is still there for 35 days.

## Lists

`GET /locations`, `/owners`, `/properties`, `/amenities` and `/webhooks` answer a page:

```json theme={null}
{
  "data": [ … ],
  "next_cursor": "…"
}
```

* `limit` is 1 to 500, 100 by default; above 500 is refused.
* To read the next page, send `next_cursor` back as `cursor`. It is opaque and bound to the query that produced it. It is `null` on the last page.
* `/locations`, `/owners` and `/properties` filter by `status`, for example `status=active,inactive`, and `/properties` also by `location_id` and `owner_id`.
* A single resource is `GET /locations/{location_id}`, `/owners/{owner_id}`, `/properties/{property_id}`.
* A read carries an `ETag` (every one except `GET /availability`); send it back as `If-None-Match` and an unchanged answer is `304 Not Modified`, everywhere but the webhook delivery logs (`/webhooks/{webhook_id}/deliveries`).

Properties name their `location_id` and `owner_id`, so read locations and owners before the properties that point to them.

## The first copy, then only the changes

<Steps>
  <Step title="Read everything once">
    List each resource without `updated_since`, following `next_cursor` to the end. Keep every resource with its `version`, and remember the largest `updated_at` you received.
  </Step>

  <Step title="Ask for what changed since then">
    List again with `updated_since` set to that largest `updated_at`. The bound is **inclusive**, so you need no overlap: what changed at that very second comes back again, and its version tells you whether you already have it.
  </Step>

  <Step title="Apply by version">
    Apply a resource only when its `version` is higher than the one you hold, and ignore a lower one. A version grows with every change visible to your channel, but it is not a counter: do not expect consecutive values.
  </Step>

  <Step title="Start over when the window has passed">
    An `updated_since` older than the retention window, 35 days, is answered `410` with `sync-window-expired`. Resync from scratch: read everything once, as in the first step.
  </Step>
</Steps>

## One lifecycle for every resource

Locations, owners, properties, amenities and webhook endpoints share one `status`, with the same meaning everywhere:

| `status` | Meaning |
| - | - |
| `active` | Published to you and in effect. |
| `inactive` | Published, not in effect now: a property that cannot be sold at the moment, a location or owner whose every published property is inactive, a suspended webhook endpoint. It may become active again. |
| `withdrawn` | Not published to you now. It may come back under the same id with a higher version. |
| `deleted` | Final. The id is never used again. |

A `withdrawn` or `deleted` resource is a **tombstone**, on every resource, and nothing else is sent:

```json theme={null}
{ "id": "prp_1qnykkykp69yv8d59hxk5410m9", "status": "withdrawn", "version": 42, "updated_at": "2026-10-16T09:30:00Z" }
```

Tombstones appear in a list only when you send `updated_since`; without it, only `active` and `inactive` resources exist. A single resource read by its id answers with its tombstone. Handle all four values on every resource, including one that resource does not reach today.

## Availability and prices

Availability is read per property and per night, in the property's own dates.

* `GET /properties/{property_id}/availability?from=2026-12-20&to=2026-12-27` answers a property's nights in a window: `to` is exclusive, the window is at most 365 nights and within the published horizon. A `from` before the property's today is served from today, and the response says which window it served. A window beyond the horizon is answered `400` with `window-beyond-horizon` and the property's `horizon_end`. A withdrawn or deleted property answers `404`.
* `GET /availability?updated_since=…&from=…&to=…` answers the nights that changed, grouped by active or inactive property. A page ends at `limit` properties or 5,000 nights, whichever comes first, so a property's nights may continue on the next page under the same `property_id`: apply them by date. A page costs `max(1, ceil(nights / 1000))` units of your rate limit.

Each night carries `units_available` (0 is sold out), `min_stay` and `max_stay` for an arrival that night, `closed_to_arrival`, `closed_to_departure`, and a rate per rate plan. A rate's `price` is for `base_occupancy` guests, as the guest pays it (VAT included, markup applied), and is `null` when the rate is `closed`; `extra_guest_price` is the price of one more adult, `0` when free, `null` when the price covers everyone.

## The event log

`GET /events` is your log, in commit order, of what changed, retained for 35 days. Store the `last_event_id` of each page and send it back as `since`; `next_cursor` is `null` once you are caught up. Without `since` the log starts at its oldest retained event. Only the event types your key's scopes cover appear: `availability.updated` needs `read:ari`.

A `since` behind the retained log is answered `410` with `event-cursor-expired` and the `latest_event_id`: resync with `updated_since`, then continue the log from `latest_event_id`.

An event names a resource and its version, or, for `availability.updated`, a property and a range of nights (`from`, `to` exclusive) with no version: re-read that range. The event types are `location.created`, `location.updated`, `location.deleted`, `owner.created`, `owner.updated`, `owner.deleted`, `property.created`, `property.updated`, `property.deleted`, `property.distributed`, `property.withdrawn` and `availability.updated`, and more may be added.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.