Read the event feed
const url = 'https://api.elwids.xyz/api/integration/v1/organizations/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/events';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.elwids.xyz/api/integration/v1/organizations/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/events \ --header 'Authorization: Bearer <token>'Requires: events:read, plus one of alerts:read or geofences:read
Rate limits: 240 a minute per address, 60 a minute per application
integration-event.v1 envelopes after cursor (from the start of the journal without one), in commit order, limit 1 to 100 (default 100). Pages skip events for devices not granted to the application, so save next_cursor even from an empty page. The feed is at least once: deduplicate by event id. Cursors are encrypted and bound to the organization, the application and its grant revision; a token rotation keeps them. Needs events:read and either alerts:read or geofences:read, each on both the application and the token. 409 after a grant change (rebuild from a fresh checkpoint); 422 for invalid input, an unreadable cursor or another application’s cursor.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The organization UUID. A value that does not match returns 404.
Query Parameters
Section titled “Query Parameters”Responses
Section titled “Responses”A page of events in commit order.
A page of the event feed. Continue from next_cursor while has_more is true; when it is false, poll again later from next_cursor.
object
An alert was activated, cleared or acknowledged; data is the alert snapshot.
object
Stable across feed reads, webhook retries and redelivery.
When the source transition happened.
When the event was written to the journal (not its commit time).
A snapshot of one alert episode. The same object is the data of the alert.*.v1 events.
object
Why the alert’s workflow stopped evaluating, for example binding_changed.
A device entered or left a geofence (entered, exited), or its geofence rule activated or cleared (wandering_started, wandering_resolved).
object
Stable across feed reads, webhook retries and redelivery.
When the source transition happened.
When the event was written to the journal (not its commit time).
object
The geofence event’s own UUID.
The telemetry event that caused the transition, when there was one.
A workflow’s action.event.v1 node fired.
object
Stable across feed reads, webhook retries and redelivery.
When the source transition happened.
When the event was written to the journal (not its commit time).
object
The action’s identity, stable across retries.
The event name configured on the node.
Save it even when data is empty; it moves past skipped events.
Example
{ "data": [ { "id": "e4f5a6b7-c8d9-4e0f-9a1b-2c3d4e5f6a7b", "schema_version": "integration-event.v1", "type": "alert.activated.v1", "occurred_at": "2026-10-12T07:58:10+00:00", "recorded_at": "2026-10-12T07:58:11+00:00", "data": { "uuid": "7c9e2a41-1d3b-4f5e-8a6c-2b4d6f8a0c1e", "episode": 3, "condition": "active", "activated_at": "2026-10-12T07:58:10.000000Z", "cleared_at": null, "acknowledged_at": null, "workflow_uuid": "5a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", "workflow_name": "North paddock — Herd tracker 17", "device_uuid": "3f8a1c2e-5b6d-4e7f-8a9b-0c1d2e3f4a5b", "execution_stopped_reason": null } }, { "id": "f5a6b7c8-d9e0-4f1a-8b2c-3d4e5f6a7b8c", "schema_version": "integration-event.v1", "type": "automation.triggered.v1", "occurred_at": "2026-10-12T08:01:00+00:00", "recorded_at": "2026-10-12T08:01:01+00:00", "data": { "workflow_uuid": "6b7c8d9e-0f1a-4b2c-9d3e-4f5a6b7c8d9e", "action_id": "8f14e45fceea167a5a36dedd4bea2543", "name": "Notify the yard", "node_id": "notify" } } ], "next_cursor": "eyJpdiI6IlZ3dE1oUnRkWjBTeUtmZz09IiwidmFsdWUiOiJuZXh0In0=", "has_more": false}Headers
Section titled “Headers”Responses to authenticated integration requests are never cached. The header also carries private.
Example
no-store, privateNo valid credentials: no session (first-party API), or a missing, invalid, expired or revoked application token (integration API).
The body of most error responses.
object
Example generated
{ "message": "example"}The caller is not allowed: not a member of the organization, missing a tenant or platform permission, or (integration API) an ability not granted on both the application and the token.
The body of most error responses.
object
Example generated
{ "message": "example"}Not found: an unknown organization or resource, a resource in another organization or not granted to the application, or a malformed identifier (the route does not match).
The body of most error responses.
object
Example generated
{ "message": "example"}The cursor can no longer be used: the application’s grants changed, or the event history changed. Rebuild the projection from a fresh checkpoint.
The body of most error responses.
object
Example generated
{ "message": "example"}The input failed validation (errors names the fields), or the request cannot be applied in the resource’s current state (a message only, for example an archived device or a limit reached).
422 for input that failed validation.
object
The first error, followed by a count of the others.
Messages per field, keyed by the field’s dotted path. A rejection by the device runtime appears under runtime.
object
The body of most error responses.
object
Example generated
{ "message": "example", "errors": { "runtime": [ "example" ] }}A rate limit was reached; see x-rate-limits on the operation.
The body of most error responses.
object
Example generated
{ "message": "example"}Headers
Section titled “Headers”Seconds to wait before retrying.