Skip to main content

Entry crossings polling

Use entry crossings when you need each individual pass through an entry, for example to count how busy a doorway is or to see which way people are moving. Each crossing is one person passing through one entry, with the direction resolved for every space the entry leads into. If you only need how many people are in a space right now, use occupancy instead: entry sensors already drive its headcount.

Requires the Entry Crossings API feature

The Entry Crossings API feature is enabled by XY Sense per organisation and can vary per building and floor. A query that covers any floor without it fails rather than leaving that floor out, so if only some floors have it, filter to them with floorIds or buildingIds. If your queries return an access-disabled error, your XY Sense representative can enable it. See Feature enablement.

1. Find the entries on a floor and the spaces they lead into​

An entry is a line drawn across a doorway or opening, watched by an entry sensor. shape is the line, in centimetres from the top-left of the floor plan. entryFloorSpaces lists the spaces the entry leads into, so you can label crossings by space name and decide which entries to poll.

Open in API Explorer

Example query​

query EntryCrossingEntries($floorId: ID!) {
floor(id: $floorId) {
id
name
entrySensorInstallations(isActive: true) {
id
name
entries {
id
name
shape
entryFloorSpaces {
floorSpaceId
floorSpace {
name
}
}
}
}
}
}

Example variables​

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

Example response​

{
"data": {
"floor": {
"id": "a2961d46-971f-4ce1-a66e-7ee7bdb2a204",
"name": "Level 12",
"entrySensorInstallations": [
{
"id": "0c9d4b7e-2f61-4a8e-b3d5-6e1f9a2c7b40",
"name": "Lobby sensor",
"entries": [
{
"id": "5f3c8e21-7a4d-4c1b-9e62-0d8b7a1f4c35",
"name": "Meeting room 12.04 door",
"shape": [
{ "x": 1820, "y": 940 },
{ "x": 1910, "y": 940 }
],
"entryFloorSpaces": [
{ "floorSpaceId": "ac52e43d-7c21-4464-ab21-d0ace07a94b1", "floorSpace": { "name": "Meeting room 12.04" } },
{ "floorSpaceId": "7f10b2c9-5e83-4d26-a1f4-3b9c8e6d2a17", "floorSpace": { "name": "Level 12 open plan" } }
]
}
]
}
]
}
}
}

2. Fetch recent crossings​

If you omit from, the API returns the last minute of crossings for the matching floors.

Open in API Explorer

Example query​

query RecentEntryCrossings($floorIds: [ID!]) {
entryCrossings(floorIds: $floorIds) {
nextFrom
data {
id
entryId
floorId
collectedDate
lineDirection
spaces {
floorSpaceId
direction
}
}
}
}

Example variables​

{
"floorIds": [
"a2961d46-971f-4ce1-a66e-7ee7bdb2a204"
]
}

Example response​

{
"data": {
"entryCrossings": {
"nextFrom": "2026-06-02T07:36:12.001Z",
"data": [
{
"id": "8e4b1c02-9d37-4f5a-b6e1-2c7a9f0d3b58",
"entryId": "5f3c8e21-7a4d-4c1b-9e62-0d8b7a1f4c35",
"floorId": "a2961d46-971f-4ce1-a66e-7ee7bdb2a204",
"collectedDate": "2026-06-02T07:36:09.412Z",
"lineDirection": "Forward",
"spaces": [
{ "floorSpaceId": "ac52e43d-7c21-4464-ab21-d0ace07a94b1", "direction": "In" },
{ "floorSpaceId": "7f10b2c9-5e83-4d26-a1f4-3b9c8e6d2a17", "direction": "Out" }
]
}
]
}
}
}

3. Read the direction of a crossing​

Use spaces[].direction to tell whether a crossing went into or out of a space:

  • In or Out is resolved for you, per space. A door between two spaces, like the meeting room door above, is In for one space and Out for the other in the same crossing, so counting by space never counts a crossing twice.
  • It uses the mapping at the time of the crossing. If an entry is later mapped to different spaces, older crossings keep the direction they had when they happened.
  • spaces is empty when the entry is not mapped to any space. lineDirection is then the only direction available.

lineDirection is Forward or Backward relative to the entry line itself. Crossings without a known direction are never recorded.

4. Poll for new crossings with a moving cursor​

Persist nextFrom and send it as the next request's from. Filter with floorIds, buildingIds or entryIds to narrow the results. A floorIds filter matches crossings from sensors on that floor and crossings into spaces on that floor. Crossings are only recorded when the feature is enabled on the entry sensor's floor, so a crossing into a space on this floor from a sensor on a floor without the feature is never returned, and one from a sensor on a floor with it includes all its spaces, wherever they are.

Open in API Explorer

Example query​

query EntryCrossingUpdates($floorIds: [ID!], $entryIds: [ID!], $from: Date!, $to: Date) {
entryCrossings(floorIds: $floorIds, entryIds: $entryIds, from: $from, to: $to) {
from
to
nextFrom
data {
id
entryId
floorId
collectedDate
lineDirection
spaces {
floorSpaceId
direction
}
}
}
}

Example variables​

{
"floorIds": [
"a2961d46-971f-4ce1-a66e-7ee7bdb2a204"
],
"entryIds": [
"5f3c8e21-7a4d-4c1b-9e62-0d8b7a1f4c35"
],
"from": "2026-06-02T07:30:00Z",
"to": "2026-06-02T07:40:00Z"
}

Example response​

{
"data": {
"entryCrossings": {
"from": "2026-06-02T07:30:00Z",
"to": "2026-06-02T07:40:00Z",
"nextFrom": "2026-06-02T07:40:00.001Z",
"data": [
{
"id": "8e4b1c02-9d37-4f5a-b6e1-2c7a9f0d3b58",
"entryId": "5f3c8e21-7a4d-4c1b-9e62-0d8b7a1f4c35",
"floorId": "a2961d46-971f-4ce1-a66e-7ee7bdb2a204",
"collectedDate": "2026-06-02T07:36:09.412Z",
"lineDirection": "Forward",
"spaces": [
{ "floorSpaceId": "ac52e43d-7c21-4464-ab21-d0ace07a94b1", "direction": "In" },
{ "floorSpaceId": "7f10b2c9-5e83-4d26-a1f4-3b9c8e6d2a17", "direction": "Out" }
]
}
]
}
}
}

Things to handle when polling:

  • from and to are when a crossing reached XY Sense, not collectedDate. Crossings a sensor sends late, for example after a network outage, appear in a later page than their collectedDate suggests. Always page with nextFrom rather than computing the next window from collectedDate.
  • The same crossing can be returned more than once. Drop duplicates using id, which stays the same for a given crossing.
  • Delivery is best effort. A crossing can occasionally be missing, so treat counts as close estimates rather than an exact audit.
  • Polling again within a second of nextFrom returns an empty page with the same nextFrom. Wait and try again.

Request windows, retention and rate limits are in Limits and retention and Limits, versioning, and support.