Skip to main content

Occupancy polling

Use occupancy polling when you need pull-based updates, replay windows, or downstream reconciliation.

Requires the Occupancy API feature

The Occupancy API feature is enabled by XY Sense per organisation and can vary per building and floor. If your queries return an access-disabled error, your XY Sense representative can enable it. See Feature enablement.

1. List the spaces you care about

Open in API Explorer

Example query

query OccupancyFloorSpaces($floorId: ID!) {
floorSpaces(floorId: $floorId) {
id
name
capacity
floor {
id
name
}
spaceType {
id
name
}
}
}

Example variables

{
"floorId": "a2961d46-971f-4ce1-a66e-7ee7bdb2a204"
}

Example response

{
"data": {
"floorSpaces": [
{
"id": "5c8a1d92-4b6e-4f03-9a71-2d4e6f8a0b13",
"name": "Desk NE-101",
"capacity": 1,
"floor": {
"id": "a2961d46-971f-4ce1-a66e-7ee7bdb2a204",
"name": "Level 12"
},
"spaceType": {
"id": "7d2e4f60-8a91-4c23-b5d6-0e1f2a3b4c56",
"name": "Desk"
}
}
]
}
}

2. Read the current state of those spaces

Open in API Explorer

Example query

query LatestOccupancy($floorId: ID!) {
floorSpaces(floorId: $floorId) {
id
name
latestOccupancy {
floorSpaceId
headcount
occupancyStatus
previousOccupancyStatus
collectedDate
occupancyStatusChangeDate
}
}
}

Example variables

{
"floorId": "a2961d46-971f-4ce1-a66e-7ee7bdb2a204"
}

Example response

{
"data": {
"floorSpaces": [
{
"id": "5c8a1d92-4b6e-4f03-9a71-2d4e6f8a0b13",
"name": "Desk NE-101",
"latestOccupancy": {
"floorSpaceId": "5c8a1d92-4b6e-4f03-9a71-2d4e6f8a0b13",
"headcount": 1,
"occupancyStatus": "CurrentlyOccupied",
"previousOccupancyStatus": "RecentlyOccupied",
"collectedDate": "2026-06-02T04:17:39.1066221Z",
"occupancyStatusChangeDate": "2026-06-02T04:17:39.1066221Z"
}
}
]
}
}

3. Poll for changes with a moving cursor

Each response carries a nextFrom. Persist it and send it as the next request's from: that is the cursor, and it is what stops you re-reading or skipping changes. Request windows and retention are in Limits and retention.

Open in API Explorer

Example query

query OccupancyChanges($floorIds: [ID!], $from: Date!, $to: Date!) {
occupancyChanges(floorIds: $floorIds, from: $from, to: $to, includeLatest: false, includeHeadcountChanges: true) {
from
to
nextFrom
data {
floorSpaceId
headcount
occupancyStatus
previousOccupancyStatus
collectedDate
occupancyStatusChangeDate
}
}
}

Example variables

{
"floorIds": [
"a2961d46-971f-4ce1-a66e-7ee7bdb2a204"
],
"from": "2026-06-02T04:00:00Z",
"to": "2026-06-02T05:00:00Z"
}

Example response

{
"data": {
"occupancyChanges": {
"from": "2026-06-02T04:00:00Z",
"to": "2026-06-02T05:00:00Z",
"nextFrom": "2026-06-02T04:17:39.1066221Z",
"data": [
{
"floorSpaceId": "5c8a1d92-4b6e-4f03-9a71-2d4e6f8a0b13",
"headcount": 0,
"occupancyStatus": "NotOccupied",
"previousOccupancyStatus": "RecentlyOccupied",
"collectedDate": "2026-06-02T04:17:39.1066221Z",
"occupancyStatusChangeDate": "2026-06-02T04:17:39.1066221Z"
}
]
}
}
}

Narrowing the poll to specific spaces

Use explicit floor-space filters when you only care about a subset of desks, rooms, or zones.

Open in API Explorer

Example query

query FilteredOccupancyChanges($floorSpaceIds: [ID!], $from: Date!, $to: Date!) {
occupancyChanges(floorSpaceIds: $floorSpaceIds, from: $from, to: $to, includeLatest: false, includeHeadcountChanges: true) {
nextFrom
data {
floorSpaceId
headcount
occupancyStatus
collectedDate
}
}
}

Example variables

{
"floorSpaceIds": [
"5c8a1d92-4b6e-4f03-9a71-2d4e6f8a0b13",
"6e0b4c85-1f27-4d93-a8b5-3c7d9e0f1a24"
],
"from": "2026-06-02T04:00:00Z",
"to": "2026-06-02T05:00:00Z"
}

Example response

{
"data": {
"occupancyChanges": {
"nextFrom": "2026-06-02T04:52:10.5411902Z",
"data": [
{
"floorSpaceId": "5c8a1d92-4b6e-4f03-9a71-2d4e6f8a0b13",
"headcount": 1,
"occupancyStatus": "CurrentlyOccupied",
"collectedDate": "2026-06-02T04:52:10.5411902Z"
},
{
"floorSpaceId": "6e0b4c85-1f27-4d93-a8b5-3c7d9e0f1a24",
"headcount": 4,
"occupancyStatus": "CurrentlyOccupied",
"collectedDate": "2026-06-02T04:49:58.1178410Z"
}
]
}
}
}