Skip to content

Webhook events

Every event Omaya can POST to an endpoint of yours, what fires it, and how to verify it really came from us.

Read out of the platform

This page is generated from the code that runs your instance, so it cannot drift from what the platform actually does.

Subscribe on Connectors → Outbound webhooks (/admin/connector/outbound-webhooks). One endpoint can subscribe to several event types; the same event type can go to several endpoints.

The catalog on that page also shows which events your tenant has actually received in the last 30 days, which is usually the faster way to answer "why am I not getting anything?" — if an event has never fired for you, the subscription is probably not the problem.

What a delivery looks like

POST to your URL, Content-Type: application/json, with these headers:

HeaderWhat it carries
X-Omaya-EventThe event type, e.g. zone.occupancy.status. Route on this, not on the payload.
X-Omaya-DeliveryA UID that is the same across every retry of one logical delivery. Use it to de-duplicate.
X-Omaya-TimestampUnix seconds at the moment the attempt was signed.
X-Omaya-Signaturesha256= + HMAC-SHA256 of <timestamp>.<raw body>, keyed with your endpoint's secret.
User-AgentOmaya-Webhook/1.1

Verify the signature against the raw request body, before any JSON parsing or re-serialisation — a re-encoded body will not match. In PHP that is:

php
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
hash_equals($expected, $signatureHeader);   // never ===

Also check the timestamp is recent (a few minutes) so an old, valid, captured delivery cannot be replayed at you.

Timeout and retries. We wait 10 seconds for your response. Anything outside 2xx — or no response at all — is retried: 6 attempts in total, backing off 1 min, 5 min, 15 min, 1 h, 6 h after each failure. After the last one the delivery is parked in the dead-letter queue (/admin/connector/outbound-webhooks/dead-letter) for you to inspect and replay.

Answer 200 as soon as you have the body; do the work afterwards. A handler that does its processing before responding will eventually exceed the timeout and be sent the same event again.

Built-in events

These ship with Omaya and are available to every tenant.

Event typeFires when
device.anomalyA device stopped reporting, is draining its battery unusually fast, or is reporting far less than its baseline (critical or warning only).
device.battery_forecastA device's battery is forecast to reach the low threshold within two weeks, from its own drain rate over the last 14 days.
device.recoveredA device that had been flagged silent is reporting again; its silent anomaly was auto-closed.
emergency.activatedA panic button was pressed and matched at least one configured panic-button routing (Devices → Panic Buttons).
rule.firedAny rule action dispatches (alert, email, webhook, telegram, whatsapp, sms, mqtt, write_record, home_assistant, or a module channel).
tenant.health_score.criticalA tenant's health score fell into the critical band (< 40).
tenant.health_score.driftA tenant's health score dropped by >= 10 points (or crossed a band boundary: good -> fair -> poor -> critical) compared to yesterday's snapshot.
venue.coverage.degradedFewer of a venue's gateways are online than positioning needs (default 3), so devices there fall back to nearest-gateway presence.
venue.coverage.restoredEnough of the venue's gateways are online again for positioning.
zone.occupancy.statusA zone's occupancy status changed: empty, normal, busy (from 50 % of capacity) or over (at capacity) — the same status the Right Now page and /api/v1/occupancy show, on the same count (radar or fixed sensor where the zone has one, otherwise BLE tags).

The device events

device.anomaly

Device Anomaly · added 2026-09-11

A device stopped reporting, is draining its battery unusually fast, or is reporting far less than its baseline (critical or warning only). Sent once per episode — a silent device fires when it goes quiet and not again until it has been seen and goes quiet again. Payload: anomaly_uid, anomaly_type, severity, device_uid, device_name, mac_address, last_seen_at, detected_at.

device.battery_forecast

Battery Replacement Due Soon · added 2026-09-11

A device's battery is forecast to reach the low threshold within two weeks, from its own drain rate over the last 14 days. Sent once per forecast episode. Payload: device_uid, device_name, mac_address, battery_pct, drain_pct_per_day, days_left, threshold_pct.

device.recovered

Device Reporting Again · added 2026-09-11

A device that had been flagged silent is reporting again; its silent anomaly was auto-closed. Payload: anomaly_uid, device_uid, device_name, mac_address, last_seen_at, flagged_at.

The emergency events

emergency.activated

Emergency Activated · added 2026-09-14

A panic button was pressed and matched at least one configured panic-button routing (Devices → Panic Buttons). Sent once per press however many routings matched, after the recipients were paged. Payload: button_uid, button_labels, buttons_matched, device_mac, press_type, gateway_mac (the gateway that heard the press), pressed_at, recipients_paged, test (true for a test press from the Panic Buttons page), source (ingestion | rule | test).

The rule events

rule.fired

Rule Fired · added in H38 (2026-07-23)

Any rule action dispatches (alert, email, webhook, telegram, whatsapp, sms, mqtt, write_record, home_assistant, or a module channel). Fires once per matched action — a single rule with 3 actions produces 3 events.

The tenant events

tenant.health_score.critical

Tenant Health Score Critical · added in H27 (B4.3) 2026-07-23

A tenant's health score fell into the critical band (< 40). Sent once per day per tenant while they remain critical, so the notification can drive a ticket/escalation workflow. Use this to kick off customer-success outreach, not to spam them on every snapshot.

tenant.health_score.drift

Tenant Health Score Drifted · added in H27 (B4.3) 2026-07-23

A tenant's health score dropped by >= 10 points (or crossed a band boundary: good -> fair -> poor -> critical) compared to yesterday's snapshot. Payload includes tenant_id, previous_score, current_score, previous_band, current_band, and the per-component breakdown. Use this to alert account managers before a customer notices.

The venue events

venue.coverage.degraded

Positioning Coverage Degraded · added 2026-09-11

Fewer of a venue's gateways are online than positioning needs (default 3), so devices there fall back to nearest-gateway presence. Only for venues with at least that many gateways registered. Sent on the transition, once. Payload: venue_uid, venue_name, online_gateways, active_gateways, min_anchors.

venue.coverage.restored

Positioning Coverage Restored · added 2026-09-11

Enough of the venue's gateways are online again for positioning. Same payload as venue.coverage.degraded.

The zone events

zone.occupancy.status

Zone Occupancy Status Changed · added 2026-09-12

A zone's occupancy status changed: empty, normal, busy (from 50 % of capacity) or over (at capacity) — the same status the Right Now page and /api/v1/occupancy show, on the same count (radar or fixed sensor where the zone has one, otherwise BLE tags). Sent once per transition after the new status has held for a minute, so a tag flickering at a zone edge does not fire every minute. Payload: zone_uid, zone_name, venue_uid, venue_name, status, previous_status, previous_since, count, tags, source, capacity, occupancy_pct, as_of.

Module events

These exist only when the module that owns them is enabled for your tenant. If a module is not installed, its events simply never appear in the catalog.

Roll Call — rollcall.*

Owned by the RollCall module.

Roll-call module events. Currently fires: rollcall.event_started (a roll-call drill was launched), rollcall.event_ended (drill completed).

Event typeFires when
rollcall.event_startedA roll-call drill was launched. The event payload includes the roll-call name, venue, and zone.
rollcall.event_endedA roll-call drill completed. The event payload includes the roll-call name, total participants accounted for, and the elapsed time.

Visitor Management — visitor.*

Owned by the Visitor module.

Visitor Management events: a visit registered, approved or denied by its host companies, checked in, checked out, or cancelled. Payloads carry the visit uid, status, the visitor's name, and each company's approval.

Event typeFires when
visitor.registeredA visit was registered — at reception, by pre-registration, or by the visitor. Payload: visit uid, visitor, companies asked for and their initial approval.
visitor.approvedEvery host company approved the visit.
visitor.deniedA host company denied the visit; payload carries the reason.
visitor.checked_inThe visitor was checked in; payload carries the badge MAC when one was assigned.
visitor.checked_outThe visitor was checked out; payload carries the method (reception, auto_presence, expired, gate, self).
visitor.cancelledAn open visit was cancelled by reception, the visitor, a company withdrawing its approval while the visitor was on site, or the meeting the guest was invited to being cancelled.
visitor.badge_changedThe badge on an open stay was swapped and the access card with it; payload carries the old and new card numbers.

Last updated:

Omaya platform documentation