API reference

Property Twin

The counts behind the Property tab: who is on property, what is open, what has been earned today.

The digital twin is the Property tab in Hotel Operator: counts and a live stream of events. No floor plans, no predictions. This route supplies the counts. The stream beside them comes from GET /v1/activity.

Every number is computed on read against the property's current calendar day in America/Nassau. Nothing here is cached or precomputed.

GET /v1/property/summary

One payload holding every count the Property tab renders.

Auth: unauthenticated in this build.

Request

GET /v1/property/summary

GET /v1/property/summary

No path params, no query params, no body.

Response

JSON

{
  "on_property": { "total": 1, "consented": 1 },
  "arrivals_today": 0,
  "departures_today": 0,
  "requests": {
    "open": 1,
    "overdue": 1,
    "queues": [
      { "queue_id": "guest_services", "label": "Guest Services", "open": 1, "overdue": 1 }
    ]
  },
  "offers": { "open": 0, "accepted_today": 0, "revenue_today_usd": 0 },
  "groups": { "groups": 0, "largest": 0 },
  "recovery": { "incidents_today": 0, "gestures_sent_today": 0 },
  "revenue_today_usd": 75
}
FieldTypeMeaning
on_property.totalnumberLive-origin stays whose arrival is on or before today and whose departure is on or after it.
on_property.consentednumberThe subset of those with analytics_consent = 1.
arrivals_todaynumberLive-origin stays arriving today.
departures_todaynumberLive-origin stays departing today.
requests.opennumberSum of the per-queue open counts.
requests.overduenumberSum of the per-queue overdue counts.
requests.queues[]arrayOne entry per row in the queues table, each with queue_id, label, open, overdue.
offers.opennumberOffers with status open whose expires_at is still in the future.
offers.accepted_todaynumberOffer instances accepted today.
offers.revenue_today_usdnumberSum of value_usd on those instances.
groups.groupsnumberLive groups, from the same computation as GET /v1/groups/summary.
groups.largestnumberBiggest live group's active member count.
recovery.incidents_todaynumberfriction_detected events from source make_it_right today.
recovery.gestures_sent_todaynumberrecovery_sent events from source make_it_right today.
revenue_today_usdnumberSum of value_usd across bookings created today, from every path (requests, offers, group activities).

A request is overdue when it is still open and was created strictly earlier than now minus its queue's sla_minutes. A request created exactly at the cutoff is not yet overdue. Each queue carries its own SLA from the config: 15 minutes for Dining, 20 for Guest Services and Bell Desk, 30 for Housekeeping.

With an empty database every block returns zeros and requests.queues is an empty array.

Errors

None. The route always returns 200.

Notes

  • offers.revenue_today_usd and revenue_today_usd are different numbers on purpose. The first counts only accepted offer instances, the second counts every booking written today.
  • The recovery block reads only events whose source is make_it_right. Core events with the same names never count toward it.
  • Dates are compared on their first ten characters, so vendor rows carrying 2026-09-10 00:00:00 line up with fixture rows carrying 2026-09-10.
  • The Property tab pairs this route with GET /v1/activity. Counts here, sentences there. See activity-and-events.md.