Appearance
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:
| Header | What it carries |
|---|---|
X-Omaya-Event | The event type, e.g. zone.occupancy.status. Route on this, not on the payload. |
X-Omaya-Delivery | A UID that is the same across every retry of one logical delivery. Use it to de-duplicate. |
X-Omaya-Timestamp | Unix seconds at the moment the attempt was signed. |
X-Omaya-Signature | sha256= + HMAC-SHA256 of <timestamp>.<raw body>, keyed with your endpoint's secret. |
User-Agent | Omaya-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 type | Fires when |
|---|---|
device.anomaly | A device stopped reporting, is draining its battery unusually fast, or is reporting far less than its baseline (critical or warning only). |
device.battery_forecast | A device's battery is forecast to reach the low threshold within two weeks, from its own drain rate over the last 14 days. |
device.recovered | A device that had been flagged silent is reporting again; its silent anomaly was auto-closed. |
emergency.activated | A panic button was pressed and matched at least one configured panic-button routing (Devices → Panic Buttons). |
rule.fired | Any rule action dispatches (alert, email, webhook, telegram, whatsapp, sms, mqtt, write_record, home_assistant, or a module channel). |
tenant.health_score.critical | A tenant's health score fell into the critical band (< 40). |
tenant.health_score.drift | A tenant's health score dropped by >= 10 points (or crossed a band boundary: good -> fair -> poor -> critical) compared to yesterday's snapshot. |
venue.coverage.degraded | Fewer of a venue's gateways are online than positioning needs (default 3), so devices there fall back to nearest-gateway presence. |
venue.coverage.restored | Enough of the venue's gateways are online again for positioning. |
zone.occupancy.status | 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). |
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 type | Fires when |
|---|---|
rollcall.event_started | A roll-call drill was launched. The event payload includes the roll-call name, venue, and zone. |
rollcall.event_ended | A 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 type | Fires when |
|---|---|
visitor.registered | A visit was registered — at reception, by pre-registration, or by the visitor. Payload: visit uid, visitor, companies asked for and their initial approval. |
visitor.approved | Every host company approved the visit. |
visitor.denied | A host company denied the visit; payload carries the reason. |
visitor.checked_in | The visitor was checked in; payload carries the badge MAC when one was assigned. |
visitor.checked_out | The visitor was checked out; payload carries the method (reception, auto_presence, expired, gate, self). |
visitor.cancelled | An 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_changed | The badge on an open stay was swapped and the access card with it; payload carries the old and new card numbers. |