Skip to content

Read the event feed

GET
/integration/v1/organizations/{organization}/events
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.

organization
required
string format: uuid

The organization UUID. A value that does not match returns 404.

cursor
string | null
<= 4096 characters
limit
integer
>= 1 <= 100

A page of events in commit order.

Media typeapplication/json

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
data
required
Array<object>
<= 100 items
One of: discriminator: type

An alert was activated, cleared or acknowledged; data is the alert snapshot.

object
id
required

Stable across feed reads, webhook retries and redelivery.

string format: uuid
schema_version
required
Allowed value: integration-event.v1
type
required
string
Allowed values: alert.activated.v1 alert.cleared.v1 alert.acknowledged.v1
occurred_at
required

When the source transition happened.

string format: date-time
recorded_at
required

When the event was written to the journal (not its commit time).

string format: date-time
data
required

A snapshot of one alert episode. The same object is the data of the alert.*.v1 events.

object
uuid
required
string format: uuid
episode
required
integer
>= 1
condition
required
string
Allowed values: active cleared
activated_at
required
string | null format: date-time
cleared_at
required
string | null format: date-time
acknowledged_at
required
string | null format: date-time
workflow_uuid
required
string format: uuid
workflow_name
required
string
device_uuid
required
string format: uuid
execution_stopped_reason
required

Why the alert’s workflow stopped evaluating, for example binding_changed.

string | null
next_cursor
required

Save it even when data is empty; it moves past skipped events.

string
>= 1 characters
has_more
required
boolean

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
}
Cache-Control
required
string
/(^|[ ,])no-store([ ,]|$)/

Responses to authenticated integration requests are never cached. The header also carries private.

Example
no-store, private

No valid credentials: no session (first-party API), or a missing, invalid, expired or revoked application token (integration API).

Media typeapplication/json

The body of most error responses.

object
message
required
string

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.

Media typeapplication/json

The body of most error responses.

object
message
required
string

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).

Media typeapplication/json

The body of most error responses.

object
message
required
string

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.

Media typeapplication/json

The body of most error responses.

object
message
required
string

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).

Media typeapplication/json
Any of:

422 for input that failed validation.

object
message
required

The first error, followed by a count of the others.

string
errors
required

Messages per field, keyed by the field’s dotted path. A rejection by the device runtime appears under runtime.

object
runtime
Array<string>
key
additional properties
Array<string>

Example generated

{
"message": "example",
"errors": {
"runtime": [
"example"
]
}
}

A rate limit was reached; see x-rate-limits on the operation.

Media typeapplication/json

The body of most error responses.

object
message
required
string

Example generated

{
"message": "example"
}
Retry-After
required
integer

Seconds to wait before retrying.

Report a problem with this page