Skip to main content

Limits, versioning, and support

Rate limits and fair use

The API does not currently enforce hard per-key request quotas. It relies on fair use, and the patterns below will keep your integration fast and reliable:

  • Match your polling rate to how often the data changes. Occupancy and sightings update at most every ~2 seconds, and polling occupancyChanges every 30 seconds with a from/nextFrom cursor is a good default. Analytics updates once a day, so a daily poll is enough.
  • Prefer webhooks for frequent changes. If you find yourself polling often to keep up, a webhook will deliver the same data with lower latency and less work on both sides.
  • Prefer fewer, larger queries. One building- or floor-scoped query is cheaper than many per-space queries, even if it fetches more than you need. Aliased queries in a single request execute sequentially, so batching by scope (floor, building) is faster and avoids timeouts.
  • Request windows and retention limits per dataset are listed in Available data.

If you have a workload in mind that sits outside these patterns (large portfolio backfills, or polling faster than every 30 seconds), reach out before you build and we will help you find the most efficient approach.

Planned rate limiting

Enforced limits are planned. We are first measuring real integration traffic, including query complexity and depth, so that the limits we set have headroom above how existing integrations already use the API. We would rather publish a limit late than break a working integration.

When limits are introduced they will be announced to registered API contacts before enforcement begins. The exact limits, and the response you get when one is exceeded, will be published on this page as part of that announcement. We expect them to cover both how often a key can call the API and how much a single query asks for (depth, breadth, and the number of aliased queries in one request).

An integration that follows the fair-use patterns above is very unlikely to hit them. To be ready regardless:

  • retry rejected requests with exponential backoff rather than immediately, and follow any wait period given in the response. See Errors,
  • avoid tight polling loops and fixed-interval retries that do not back off,
  • batch by floor or building scope rather than issuing one query per space.

API versioning

There is no version in the API URL, and no version header to send. A single current version of the GraphQL schema is served, and integrations do not pin to a version.

That works because the schema only grows: see Schema stability and breaking changes for what is additive, what counts as breaking, and how breaking changes are communicated. If we ever need to introduce versioning, it will be announced well ahead of time along with a migration path for existing integrations.

Deprecated fields

Where a field, argument, or type is superseded, we keep the original working and mark it deprecated rather than removing it, so existing integrations keep running. This is how we avoid needing an API version.

A deprecation is marked in the schema itself and carries a reason naming what to use instead. The API currently has a few, for example:

  • location and locations are deprecated in favour of building and buildings,
  • on SpaceGroup, spaces and totalSpaces are deprecated in favour of floorSpaces and totalFloorSpaces.

If you are building a new integration, do not use deprecated fields. They are the likely candidates for removal in future, and removal is a breaking change, so it would come with advance notice and a migration window. Choosing the current field now saves you that migration. If you maintain an existing integration, there is no urgency to move, but moving off a deprecated field when you next touch the code is worthwhile.

Schema stability and breaking changes

The external GraphQL schema evolves additively: new fields, arguments, types, and enum values are added over time, and existing ones are not removed or repurposed without warning. Extending rather than changing the API is a deliberate choice, and it is why there is no API version for you to pin.

Changes we make without notice, and that your client should tolerate:

  • new fields and types in the schema,
  • new optional arguments on existing fields,
  • new values in an existing enum,
  • new event types and new fields in webhook payloads,
  • marking an existing field as deprecated, which does not change its behaviour (see Deprecated fields).

Changes we treat as breaking, and do not make without notice:

  • removing or renaming a field, argument, type, or enum value,
  • changing the type or nullability of an existing field,
  • changing the meaning of an existing field, or the units it is expressed in,
  • making a previously optional argument required.

To stay compatible, request only the fields you use, ignore fields you do not recognise, and handle an unfamiliar enum value as a default case rather than an error.

When a breaking change is unavoidable, XY Sense notifies registered API contacts ahead of time with a migration window, so you have time to adjust before the change takes effect. Planned maintenance that affects API availability is communicated the same way, ahead of the window.

Make sure we hold the right technical contact for your integration, so these notices reach the person who maintains it rather than a commercial contact.

The generated API reference always reflects the current production schema.

Getting help

  • Integration questions or unexpected results: contact your XY Sense representative or reach us via support@xysense.com.
  • Include your query (with variables), the full response including any errors array, and a timestamp. That is usually enough for us to reproduce.
  • Feature enablement (Occupancy API, Analytics API, Webhooks) and dev-mode floors are provisioned by XY Sense, ask your representative or contact us via support@xysense.com.