Skip to main content

Quickstart

This page takes you from nothing to a webhook delivering events to your endpoint.

Before you start

  • Your endpoint must be reachable over HTTPS and respond within 10 seconds. See Delivery and batching.
  • Each webhook type requires the matching API feature (Occupancy API, Sightings API, or Space Sensor Readings API) to be enabled on at least one of your floors, and events are only delivered for floors where it is enabled. If you cannot register a webhook, your XY Sense representative can enable the feature. See Feature enablement.
  • Registering via GraphQL needs WritePublicApi on the API key. See the GraphQL quickstart.

1. Register the webhook

Register via the Admin Console at https://app.xysense.io/settings/webhooks, or programmatically with addWebhook.

Open in API Explorer

Example query

mutation AddWebhook($headers: [InputPair!]) {
addWebhook(
name: "Occupancy stream"
webhookType: OccupancyChanges
endpoint: "https://example.com/hooks/xy"
email: "integrations@example.com"
additionalHeaders: $headers
signatureSecret: "<64-256 char secret>"
enabled: true
) {
id
name
endpoint
enabled
webhookType
}
}

Example variables

{
"headers": [
{
"key": "X-Partner-Token",
"value": "mytoken"
}
]
}

Example response

{
"data": {
"addWebhook": {
"id": "1c9c1e7a-38f6-4a9a-8f4c-6a1f0f2d3e4b",
"name": "Occupancy stream",
"endpoint": "https://example.com/hooks/xy",
"enabled": true,
"webhookType": "OccupancyChanges"
}
}
}

The signature secret cannot be read back after it is set, so store it when you create the webhook.

2. Handle the first delivery

Deliveries are POST requests with Content-Type: application/json; charset=utf-8. The body is a batch envelope, not a bare array of events:

{
"Id": "3f1b8f0e-2c44-4a1d-9f52-6b3f0a2d1c77",
"Type": "Occupancy",
"CustomerId": "2b7f9e10-4c3a-4b8e-9a11-7d2e5f6c8b90",
"Created": "2026-06-02T04:17:40Z",
"Sent": "2026-06-02T04:17:41Z",
"Data": [
{
"FloorSpaceId": "ac52e43d-7c21-4464-ab21-d0ace07a94b1",
"OccupancyStatus": "CurrentlyOccupied",
"Headcount": 2,
"CollectedDate": "2026-06-02T04:17:39.1066221Z",
"OccupancyStatusChangeDate": "2026-06-02T04:17:39.1066221Z",
"PreviousOccupancyStatus": "RecentlyOccupied"
}
]
}

Iterate Data and return 2xx to acknowledge the whole batch. Field names are PascalCase. See Delivery and batching for the full envelope reference.

3. Verify it is working

  • Inspect delivery metrics with the webhook(id:) query.
  • If your floor is in dev mode, generate traffic on demand with Webhook test events.

4. Harden it

Troubleshooting

SymptomWhere to look
Registration rejected for a webhook typeThe matching API feature is not enabled on any floor. See Feature enablement.
You are not authorized to access the '...' fieldThe API key needs WritePublicApi, in addition to your user account's permissions.
No deliveries arrivingCheck enabled on the webhook, and its delivery metrics via webhook(id:). A webhook that fails continuously is disabled automatically.
Deliveries stopped after an outageThe queue holds up to 1,000,000 events and retries for 24 hours. If your receiver is far behind, use resetWebhookConsumer and backfill the gap through GraphQL.
Receiver only sees the first eventThe body is an envelope object, not an array. Iterate Data.
Timeouts under loadDeliveries time out after 10 seconds per attempt. Acknowledge the batch and process asynchronously.