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). |
emergency.cleared | An alarm a device raised and ended itself is over: a cellular badge's SOS, Alert or man-down (MOKO PS101-M) ended on the badge, by an exit-alarm command, or a later report said no alarm is active. |
geofence.entered | A tag with GPS (a tracker, or one an Omaya Scout phone places) went into a geofence (Space > Location > Map). |
geofence.exited | A tag with GPS left a geofence. |
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, location (where the button is: kind indoor | outdoor | last_gps, text, place, latitude, longitude, map_url, position_at; null when unknown), recipients_paged, test (true for a test press from the Panic Buttons page), source (ingestion | rule | test).
emergency.cleared
Emergency Cleared · added 2026-10-10
An alarm a device raised and ended itself is over: a cellular badge's SOS, Alert or man-down (MOKO PS101-M) ended on the badge, by an exit-alarm command, or a later report said no alarm is active. Sent once per alarm, after the emergency.activated that started it. Payload: device_mac, device_uid, alarm (sos | alert | man_down), started_at, ended_at, ended_how (device | command | no_alarm), buttons_matched.
The geofence events
geofence.entered
Geofence Entered · added 2026-10-05
A tag with GPS (a tracker, or one an Omaya Scout phone places) went into a geofence (Space > Location > Map). Sent once per crossing, from the fix that crossed; coming back out of a building inside the same geofence is not a new crossing. Payload: geofence_uid, geofence_name, device_uid, device_mac, entity_uid, entity_type, latitude, longitude, at.
geofence.exited
Geofence Exited · added 2026-10-05
A tag with GPS left a geofence. Sent before geofence.entered when it moved straight into another one. Same payload as geofence.entered.
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: rollcall.event_started (a roll call, drill or real muster, was started from the app, the mobile app or a rule) and rollcall.event_ended (it was ended and its counts frozen). Payloads carry event_uid, name, type, is_drill, priority, the gathering point and timestamps.
| Event type | Fires when |
|---|---|
rollcall.event_started | A roll call (drill or real muster) was started. Payload: event_uid, name, type, is_drill, priority, gathering_point, gathering_zone_uid/venue_uid, expected (people on the roster), started_at. |
rollcall.event_ended | A roll call was ended. Payload adds: present, excused, off_site (outside on GPS, accounted for), unaccounted (missing + late + badge not heard + never classified), accountability_pct ((present + excused + off_site) / expected), duration_seconds, ended_at. |
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. |
Warehouse — warehouse.*
Owned by the Warehouse module.
Warehouse app events for the ERP: goods received, shipped, adjusted, counted, issued to and reported from production, returned, rejected by QC, and storage breaches. Payloads carry the ERP codes (SKU, order type and number, partner code), never Omaya ids. GET /api/v1/warehouse/movements carries every ledger line in order.
| Event type | Fires when |
|---|---|
warehouse.receipt | Goods received against a PO (receiving closed): lines with SKU, batch, quantity, serials. |
warehouse.return_received | A customer return was received; it is held for QC. |
warehouse.qc_rejected | Inspection failed units on a receipt or pick list; they are quarantined. Payload adds units_failed. |
warehouse.shipment | A pick list was shipped: lines with SKU, batch, quantity, plus vehicle and carrier. |
warehouse.adjustment | Stock adjusted in or out by hand (stock in, stock out, scrap), with the reason and who did it. |
warehouse.count_approved | A stock count was approved; payload carries each variance line posted and its quantity change. |
warehouse.materials_issued | Materials issued to a work order. |
warehouse.materials_returned | Unused material returned from a work order to stock; payload lines carry the quantity back and the new unit label. |
warehouse.supplier_return | Goods returned to a supplier left at the gate (return to supplier): the RTV number, the supplier's RMA / debit note, and lines with SKU, batch, serial, quantity and the PO they came in on. |
warehouse.production_reported | Finished goods reported on a work order, with the new unit labels. |
warehouse.condition_breach | A storage area left its temperature or humidity range; payload lists the units inside. |
warehouse.movement | Every ledger line, when the ERP connector asks for it (the movement feed is the better way to read these). |