RapidEye API

Reference

Reservations

Read connected customers' homes and stays, with measured freshness per source.

Reservations: properties and stays

Read the homes and stays of the RapidEye customers who connected your integration.

  • Read-only. You do not create a workspace, send a roster or issue a recording link.
  • One customer is one workspace. Its workspace_id is ours, rwd_ and 16 characters, and never changes, even when the customer disconnects and connects again.
  • Unlisted until the date we agree. Your key, these routes and your webhook receiver work from day one, but no customer can connect you until we list you. Until then GET /v1/workspaces returns an empty list and any workspace_id answers 404 workspace_not_provisioned.

Scopes for these routes

Scope Grants On the customer's connection
read:workspaces GET /v1/workspaces, GET /v1/workspaces/{workspace_id} Not needed
read:properties GET /v1/properties: homes and full addresses Always
read:reservations GET /v1/reservations and the two routes under it Always
  • A read needs the scope on your key and on the customer's connection. Otherwise it answers 403 insufficient_scope, and detail.required_scope names the scope.
  • Every other route in this guide answers a key with only these scopes with 403 insufficient_scope.

Keeping in sync

Step Call Rule
1. Customers GET /v1/workspaces Daily. Keep each workspace_id.
2. Backfill GET /v1/reservations?workspace_id=...&updated_since=2000-01-01T00:00:00Z&limit=500 Once per customer, and again after a reconnect. Walk every page, until a page has no next_cursor. Backfill customers one after another, not all at once, and back off on a 429.
3. Poll GET /v1/reservations?workspace_id=...&updated_since=... Every 5 minutes, or every 15 if you take events. updated_since = when you started your previous poll, less 5 minutes. Walk every page. Reading a stay twice is harmless.
4. Apply Upsert each stay by reservation_id when its revision is higher than the one you hold; ignore it otherwise. A cancellation is the same stay with a higher revision and status: "cancelled", never a deletion.
5. Homes GET /v1/properties?workspace_id=...&updated_since=... About hourly, with the same 5-minute overlap. Dedupe on rapideye_property_id.
6. Events Optional. Each one is a nudge to re-read what it names (Events).

Stubs

  • When: a stay whose home is switched off, removed or deleted reads as a stub, whatever its status. A live stay there turns out_of_scope within about 15 minutes, and GET /v1/properties shows the home inactive or removed.
  • Fields: only reservation_id, rapideye_property_id, source, source_reservation_id, source_property_id, status, status_basis, first_seen_at, last_confirmed_at, last_changed_at and revision. Match a stub to your copy by reservation_id.
  • Not a cancellation. If the home is switched back on, its stays come back in full.

Coverage and freshness

A new booking or change reaches the API within the target below. A cancellation the source does not state takes the time in its row of the source table.

Stays Target
In house, or arriving or departing from yesterday through 2 days ahead 20 minutes at p95, 60 at most
Arriving within 30 days About an hour
Departing from 30 days ago to arriving within a year A day
Source Guest name Status
Breezeway Yes checked_in and checked_out stated; otherwise confirmed, and cancelled once the stay leaves Breezeway (status_basis: inferred): about 30 minutes within 2 days, about 2 hours within 30 days, up to 2 nights further out
OwnerRez Yes A new booking or change reaches the API within about 3 minutes, at any date. Stated by OwnerRez: active is confirmed, a pending booking or quote hold is hold, canceled is cancelled. A booking deleted in OwnerRez becomes unknown: about 2 hours within 30 days, up to 2 nights further out
Track Yes Stated by Track, within 15 minutes. A stay deleted in Track becomes unknown: about 3 hours within 30 days, up to 3 nights further out
Trellis No (source_does_not_provide) confirmed, and unknown once the stay leaves Trellis (status_basis: inferred): about 45 minutes within 2 days, about 3 hours within 30 days, up to 3 nights further out. Only stays with a Trellis task are visible.

Measured freshness per customer is on GET /v1/workspaces/{workspace_id}.

Events

Optional signed deliveries that tell you about a change sooner than your next poll.

  • Register: send us one HTTPS receiver URL, and the event types you want if not all. We send back its signing secret.
  • Order by revision. Deliveries arrive out of order and more than once; never order by arrival or occurred_at.
  • Dedupe on webhook-id, the payload's event_id, the same on every retry.
Event When Payload
workspace.enabled A customer connects you workspace: the workspace object
workspace.disabled A customer disconnects you, or RapidEye revokes the connection workspace, with disabled_at set
reservation.created We first see a stay reservation: the reservation object, and changes
reservation.updated Anything about the stay changed: dates, times, status, stay type, guest count, channel, home or guest. A cancellation is this event with status: "cancelled"; there is no separate one. reservation and changes, as in the history

Handling an event

  1. Verify the signature over the raw body (Verifying our signature).
  2. Dedupe on webhook-id.
  3. Answer 2xx within 10 seconds and do the rest asynchronously. A non-2xx, a redirect or a timeout is retried after 1m, 5m, 30m, 2h and 12h, six attempts in all.
  4. Re-read what it names. reservation.*: GET /v1/reservations/{reservation_id}?workspace_id=..., applied by revision (skip it when the payload's revision is not higher than yours; changes is only a hint). workspace.*: GET /v1/workspaces/{workspace_id}; on a workspace.enabled for a workspace you hold as disabled, re-run its backfill. When many events arrive at once, run your poll early instead.

Errors on these routes

Every error uses the envelope in The error envelope. Besides each route's own codes, any route here can return:

Error When
401 invalid_key The key is missing or not one we recognize.
403 partner_disabled We paused your whole integration. Your key is not the problem; email support.
403 insufficient_scope Your key, or the customer's connection, does not carry the scope this read needs. detail.required_scope names it.
403 workspace_disabled This customer's connection to you is off: its data is not readable and its events stop. The workspace_id stays the same if it connects again.
404 workspace_not_provisioned That workspace_id is not one of your customers. GET /v1/workspaces lists the ones you can read.
429 too_many_requests More than 600 requests from your key in one 5-minute window of the clock. Retry once the next window starts, at most 5 minutes later; nothing is lost.

GET/v1/workspaces#

Lists every customer connected to you (enabled) and every customer that was and no longer is (disabled). Scope: read:workspaces.

Name In Type Required Description
Authorization header string yes Bearer rapideye_pk_...
status query string no enabled or disabled, comma-separated for both. Default: both.
limit query integer no 1 to 500, default 100.
cursor query string no The previous page's next_cursor.
Field Meaning
scopes What this customer's connection grants (Scopes for these routes).
enabled_at When the current connection began.
active_properties The number of homes the customer shares. Absent on a disabled workspace.
next_cursor Absent on the last page.
Error When
400 invalid_request status, limit or cursor is malformed. detail.parameter names it.
HTTP
GET /v1/workspaces?status=enabled HTTP/1.1
Host: api.rapideyeinspections.com
Authorization: Bearer rapideye_pk_...
HTTP
HTTP/1.1 200 OK
Content-Type: application/json

{
  "workspaces": [
    {
      "workspace_id": "rwd_7Hq2c9Lm4TzPx8Ab",
      "customer_name": "Coastal Stays",
      "status": "enabled",
      "scopes": ["read:properties", "read:reservations"],
      "enabled_at": "2026-10-14T15:02:11+00:00",
      "disabled_at": null,
      "active_properties": 142
    }
  ]
}

GET/v1/workspaces/{workspace_id}#

Returns one customer's workspace with its measured freshness. Scope: read:workspaces.

Name In Type Required Description
Authorization header string yes Bearer rapideye_pk_...
workspace_id path string yes Ours, rwd_....
Field Meaning
freshness Absent on a disabled workspace, as is active_properties. A disabled workspace still answers here with its status, scopes and times.
reads[].kind window (stays within 2 days), upcoming (the next 30 days), full (the whole window) or, for Track and OwnerRez, recent (everything the source changed since our last read, standing in for window).
reads[].last_complete_at When that kind of read last finished in full. For recent, which is never complete, when it last succeeded.
last_read_at, last_read_status Our most recent read of the customer's PMS, of any kind: ok or failed. reads_last_24h and failed_reads_last_24h count them.
new_booking_lag_minutes From when the source recorded a stay to when we first had it, over the last 7 days, split by whether the stay arrives within 2 days of being booked.
change_lag_minutes From the source's last-modified time to when we saw the change. null for a source that sends no last-modified time.
stays_in_window The customer's stays in the default window.
stays_without_property Stays whose RapidEye home has since been deleted: we hold them but can no longer place them. A stay at a home the customer never added is not held, so not counted.
exceptions In words, where this source falls short of the target.
Measured fields null, not zero, if we cannot read our own measurements at that moment. The declared reads, cancellation and exceptions are still there.
sources, note [] and a note for a customer whose PMS we do not read stays from.

Errors: only the shared ones. This route never answers workspace_disabled.

HTTP
GET /v1/workspaces/rwd_7Hq2c9Lm4TzPx8Ab HTTP/1.1
Host: api.rapideyeinspections.com
Authorization: Bearer rapideye_pk_...
HTTP
HTTP/1.1 200 OK
Content-Type: application/json

{
  "workspace_id": "rwd_7Hq2c9Lm4TzPx8Ab",
  "customer_name": "Coastal Stays",
  "status": "enabled",
  "scopes": ["read:properties", "read:reservations"],
  "enabled_at": "2026-10-14T15:02:11+00:00",
  "disabled_at": null,
  "active_properties": 142,
  "freshness": {
    "targets": { "p95_minutes": 20, "ceiling_minutes": 60, "applies_to": "stays in house, or arriving or departing from yesterday through 2 days ahead" },
    "sources": [
      {
        "source": "breezeway",
        "reads": [
          { "kind": "window", "covers": "stays in house, or arriving or departing from yesterday through 2 days ahead", "every_minutes": 15, "last_complete_at": "2026-10-20T13:35:02+00:00" },
          { "kind": "upcoming", "covers": "stays in house, or arriving or departing from yesterday through 30 days ahead", "every_minutes": 60, "last_complete_at": "2026-10-20T13:00:41+00:00" },
          { "kind": "full", "covers": "stays departing from 30 days ago to arriving within 365 days, nightly from 06:00 UTC; also run at once whenever a near or upcoming read lacks a stay we hold", "every_minutes": 1440, "last_complete_at": "2026-10-20T06:21:44+00:00" }
        ],
        "last_read_at": "2026-10-20T13:35:02+00:00",
        "last_read_status": "ok",
        "reads_last_24h": 97,
        "failed_reads_last_24h": 0,
        "new_booking_lag_minutes": {
          "window_days": 7,
          "arriving_within_2_days": { "sample": 23, "p50": 7.9, "p95": 15.6 },
          "arriving_later": { "sample": 230, "p50": 38.5, "p95": 702.0 }
        },
        "change_lag_minutes": null,
        "stays_in_window": 1204,
        "stays_without_property": 0,
        "cancellation": "...",
        "exceptions": ["..."]
      }
    ]
  }
}

GET/v1/properties#

Lists the customer's homes as RapidEye holds them. Scope: read:properties.

Name In Type Required Description
Authorization header string yes Bearer rapideye_pk_...
workspace_id query string yes Ours, rwd_....
status query string no active, inactive, removed, comma-separated. Default: all three.
updated_since query date-time no Homes changed at or after this time. ISO 8601 with an offset.
limit query integer no 1 to 500, default 100.
cursor query string no The previous page's next_cursor.
Field Meaning
rapideye_property_id Ours and stable. Every stay names its home by it.
source_property_id The home's id in the customer's PMS.
source The PMS the home came from: breezeway, ownerrez, track, trellis, or manual for a home added by hand in RapidEye.
status active, inactive (switched off in RapidEye) or removed. An inactive or removed home carries only rapideye_property_id, status, source, source_property_id and updated_at. A home the customer deletes from RapidEye no longer appears; its stays turn out_of_scope at our next read and still name it by source_property_id.
address Refreshed from the PMS every night. A field we do not hold is null.
address_complete false when line 1, city, region or postal code is missing.
timezone The home's IANA zone. Every stay time is in it.
coordinates null when the PMS sends none.
Error When
400 missing_parameter workspace_id is absent or blank. detail.parameter names it.
400 invalid_request A filter is malformed, such as updated_since without an offset. detail.parameter names it; for a bad status, detail.allowed lists the accepted values; for a limit out of range, detail.limit is the maximum.
HTTP
GET /v1/properties?workspace_id=rwd_7Hq2c9Lm4TzPx8Ab&status=active HTTP/1.1
Host: api.rapideyeinspections.com
Authorization: Bearer rapideye_pk_...
HTTP
HTTP/1.1 200 OK
Content-Type: application/json

{
  "workspace_id": "rwd_7Hq2c9Lm4TzPx8Ab",
  "properties": [
    {
      "rapideye_property_id": "1f0a9c22-6b1e-4a77-9b0f-2d2b0c5f7a10",
      "name": "Beach House Unit 1",
      "status": "active",
      "source": "breezeway",
      "source_property_id": "512345",
      "address": {
        "line1": "18 Ocean Drive",
        "city": "Panama City Beach",
        "region": "FL",
        "postal_code": "32413",
        "country_code": "US"
      },
      "address_complete": true,
      "timezone": "America/Chicago",
      "coordinates": { "latitude": 30.1766, "longitude": -85.8055 },
      "updated_at": "2026-10-15T07:04:12+00:00"
    }
  ]
}

GET/v1/reservations#

Lists one page of a customer's stays, oldest change first. Scope: read:reservations.

Name In Type Required Description
Authorization header string yes Bearer rapideye_pk_...
workspace_id query string yes Ours, rwd_....
updated_since query date-time no Stays that changed at or after this time. ISO 8601 with an offset; a bare date answers 400 invalid_request. Removes the default window, so a change to an old stay is still returned.
arrival_from, arrival_to query date no Arrival date range, YYYY-MM-DD, inclusive. Removes the default window. Never returns a stub.
rapideye_property_id query string no One home.
status query string no One or more statuses (The reservation object), comma-separated.
stay_type query string no One or more of guest, owner, owner_guest, block, unknown, comma-separated. Never returns a stub.
limit query integer no 1 to 500, default 100.
cursor query string no The previous page's next_cursor.
  • Default window: with none of updated_since, arrival_from or arrival_to, stays departing from 30 days ago to arriving within 365 days.
  • Order: last_changed_at, then reservation_id. A stay that changes while you walk the pages moves to the end, and you read it again in its newer state. A write that lands just as your walk passes its time can fall behind the cursor; the 5-minute overlap in your next poll catches it.

Each stay is a reservation object (The reservation object). next_cursor is absent on the last page.

Error When
400 missing_parameter workspace_id is absent or blank. detail.parameter names it.
400 invalid_request A filter is malformed, such as updated_since without an offset. detail.parameter names it; for a bad status or stay_type, detail.allowed lists the accepted values; for a limit out of range, detail.limit is the maximum.
HTTP
GET /v1/reservations?workspace_id=rwd_7Hq2c9Lm4TzPx8Ab&updated_since=2026-10-19T09:00:00Z&limit=500 HTTP/1.1
Host: api.rapideyeinspections.com
Authorization: Bearer rapideye_pk_...
HTTP
HTTP/1.1 200 OK
Content-Type: application/json

{
  "workspace_id": "rwd_7Hq2c9Lm4TzPx8Ab",
  "reservations": [
    {
      "reservation_id": "8c1e4b7a-90d2-4f55-a3f1-1d2e9b0c6a44",
      "rapideye_property_id": "1f0a9c22-6b1e-4a77-9b0f-2d2b0c5f7a10",
      "source": "breezeway",
      "source_reservation_id": "107053350",
      "source_property_id": "512345",
      "pms_reservation_id": "HMX4QZ8KT2",
      "status": "confirmed",
      "status_basis": "inferred",
      "stay_type": "guest",
      "arrival_date": "2026-10-23",
      "departure_date": "2026-10-27",
      "check_in_at": "2026-10-23T16:00:00-05:00",
      "check_out_at": "2026-10-27T10:00:00-05:00",
      "timezone": "America/Chicago",
      "booked_at": null,
      "source_recorded_at": "2026-10-08T14:21:09+00:00",
      "channel": "unknown",
      "channel_raw": null,
      "guest_count": 4,
      "primary_guest": { "name": "Dana Whitfield" },
      "first_seen_at": "2026-10-08T14:25:41+00:00",
      "last_confirmed_at": "2026-10-20T13:35:02+00:00",
      "last_changed_at": "2026-10-19T09:12:55+00:00",
      "revision": 3,
      "missing": {
        "booked_at": "source_does_not_provide",
        "channel": "source_does_not_provide"
      }
    }
  ],
  "next_cursor": "MjAyNi0xMC0xOVQwOToxMjo1NS4wMDAwMDBafDhjMWU0YjdhLTkwZDItNGY1NS1hM2YxLTFkMmU5YjBjNmE0NA=="
}

GET/v1/reservations/{reservation_id}#

Returns one stay, in any window. Scope: read:reservations.

Name In Type Required Description
Authorization header string yes Bearer rapideye_pk_...
reservation_id path string yes Ours.
workspace_id query string yes Ours, rwd_....

The body is a reservation object. This example is a stub (Stubs); a stay at an active home has every field shown under GET /v1/reservations.

Error When
400 missing_parameter workspace_id is absent or blank.
404 reservation_not_found No stay with that reservation_id in that workspace.
HTTP
GET /v1/reservations/8c1e4b7a-90d2-4f55-a3f1-1d2e9b0c6a44?workspace_id=rwd_7Hq2c9Lm4TzPx8Ab HTTP/1.1
Host: api.rapideyeinspections.com
Authorization: Bearer rapideye_pk_...
HTTP
HTTP/1.1 200 OK
Content-Type: application/json

{
  "reservation_id": "8c1e4b7a-90d2-4f55-a3f1-1d2e9b0c6a44",
  "rapideye_property_id": "1f0a9c22-6b1e-4a77-9b0f-2d2b0c5f7a10",
  "source": "breezeway",
  "source_reservation_id": "107053350",
  "source_property_id": "512345",
  "status": "out_of_scope",
  "status_basis": "inferred",
  "first_seen_at": "2026-10-08T14:25:41+00:00",
  "last_confirmed_at": "2026-10-20T13:35:02+00:00",
  "last_changed_at": "2026-10-22T08:10:31+00:00",
  "revision": 5
}

GET/v1/reservations/{reservation_id}/history#

Lists every change we observed to one stay, oldest first. Scope: read:reservations.

Name In Type Required Description
Authorization header string yes Bearer rapideye_pk_...
reservation_id path string yes Ours.
workspace_id query string yes Ours, rwd_....
Field Meaning
changes Oldest first, so the first entry is the stay as we first saw it.
event created, updated, cancelled, reinstated (a stay we had marked cancelled or missing came back) or missing.
fields Each changed field with its old and new value. Names are the reservation object's, except that a time changes as check_in_time or check_out_time, the home's wall-clock time ("16:00:00") that check_in_at and check_out_at are built from. Guest fields appear as "changed", never with their values. For a stub, cut to the status change.
Error When
400 missing_parameter workspace_id is absent or blank.
404 reservation_not_found No stay with that reservation_id in that workspace.
HTTP
GET /v1/reservations/8c1e4b7a-90d2-4f55-a3f1-1d2e9b0c6a44/history?workspace_id=rwd_7Hq2c9Lm4TzPx8Ab HTTP/1.1
Host: api.rapideyeinspections.com
Authorization: Bearer rapideye_pk_...
HTTP
HTTP/1.1 200 OK
Content-Type: application/json

{
  "reservation_id": "8c1e4b7a-90d2-4f55-a3f1-1d2e9b0c6a44",
  "changes": [
    { "revision": 1, "event": "created", "observed_at": "2026-10-08T14:25:41+00:00", "source_updated_at": null,
      "fields": { "arrival_date": [null, "2026-10-23"], "departure_date": [null, "2026-10-26"] } },
    { "revision": 2, "event": "updated", "observed_at": "2026-10-19T09:12:55+00:00", "source_updated_at": null,
      "fields": { "departure_date": ["2026-10-26", "2026-10-27"] } }
  ]
}

The reservation object

Date-times are ISO 8601 in UTC, except check_in_at and check_out_at, which carry the home's own offset.

Field Meaning
reservation_id Ours, stable. Key your copy of a stay on it.
rapideye_property_id The home, as GET /v1/properties names it.
source, source_reservation_id The system we read the stay from (breezeway, ownerrez, track, trellis) and its id there.
source_property_id The home's id in that system, the same id GET /v1/properties gives. Still set when the home has since been deleted from RapidEye.
pms_reservation_id The booking's id in the customer's PMS or channel, usually what you match to your own records. null when the source sends none; absent from a stub.
status inquiry, hold, confirmed, checked_in, checked_out, cancelled, no_show, unknown or out_of_scope (the stay moved to a home the customer does not run with RapidEye, its home was switched off or removed, or the customer connected a different account of their PMS that does not hold that home; not a cancellation, and always a stub). Refreshed on every read of the PMS. A cancellation is a status, never a deletion.
status_basis source when the PMS stated the status; inferred when we derived it (Coverage and freshness).
stay_type guest, owner, owner_guest (an owner's guest), block (an owner or maintenance hold, no guest) or unknown.
arrival_date, departure_date The home's calendar dates. Do not convert them.
check_in_at, check_out_at The home's check-in and check-out times with that date's offset, daylight time included. null when the source gives no time or we hold no zone for the home.
timezone The home's IANA zone. null when we hold none, and then both times are null.
booked_at When the guest booked, when the source says.
source_recorded_at When the source first recorded the stay. For Breezeway, the closest thing to a booking time.
channel, channel_raw airbnb, vrbo, booking_com, direct, owner, other or unknown, and the source's own value. Breezeway and Trellis do not send a channel.
guest_count As the source states it.
primary_guest { "name": "..." }, the primary guest's name. Absent when the source provides no name; missing.primary_guest says why.
first_seen_at, last_confirmed_at, last_changed_at When we first saw the stay, when a read last returned it, and when it last changed. last_confirmed_at is refreshed at most hourly while a stay is unchanged, so it is accurate to the hour.
revision Rises by one on every change; never decreases.
missing Each empty field, mapped to one of the reasons below. Absent from a stub.
missing.*: source_does_not_provide The PMS never sends this field.
missing.*: withheld_by_channel The booking channel withholds it.
missing.*: timezone_unknown We hold no zone for the home, so the times are null.
missing.*: missing The source should have sent it and did not; tell us if it is on a field you rely on. Right after a customer connects you, a stay we read before then reads this for primary_guest until our next read of it, unless its source sends no name (Trellis); the name then arrives as a higher revision.