Skip to main content

Events API

Events endpoints exposed by the Devotel CPaaS API Base path: /api/v1/events Endpoint count: 9
Track events power more than campaigns and journeys. They feed the Customer-360 workspace timeline, where one snapshot call aggregates a contact’s events, conversations, voice calls, tickets, and more into a single workspace view.

Worked sequences

The four operations below are a complete walk-through of the Events surface, in the order an integration typically uses them: page through history, look up a single event, tail the live stream, and publish your own events. Every response below is a worked copy of the wire shape, and the Node examples route through the SDK’s orbit.request() helper.

List event history — GET /events

Page through the tenant’s recent-event history newest-first. The first request omits cursor; each page’s meta.pagination.cursor feeds the next request while has_more is true. Step 1 — first page
Node.js
Response (first page)
Step 2 — page forward while has_more is true
Node.js
Send the cursor verbatim — it is the id of the last event from the prior page (<ms>-<seq> form). When has_more comes back false, history is exhausted.

Get event details — GET /events/:id

Fetch one event by its id — either the canonical stream id from a list page (1755008400000-0) or a legacy publisher-minted evt_* id. Both resolve against the same history window. Request
Response
An id outside the retained history window returns a 404 with the NOT_FOUND error envelope.

Live tail — GET /events/stream (SSE)

For a live dashboard, open a Server-Sent Events connection instead of polling. The stream replays anything buffered after your Last-Event-ID (or ?lastEventId=), then tails events as they publish. A 30-second : heartbeat comment frame keeps the connection open between events. curl (server-side, secret API key)
Browser EventSource (Clerk session cookie)
Non-browser Node clients can keep a durable cursor on the ?lastEventId= query parameter (EventSource re-sends it as the Last-Event-ID header automatically). Sample stream frames
Each frame is id:, event:, and data: separated by a blank line. On reconnect, re-send the last id you saw and the replay pass fills the gap before the live tail resumes. ?types= narrows both the replay and the live tail to the comma-separated event types.

Publish a tracked event — POST /events/track

Record a domain event for a contact — Order Placed, Subscription Renewed, Trial Converted — to drive lifecycle campaigns, journey triggers, and the customer-360 timeline. The body is validated against the same per-event contract the schema registry publishes; GET /events/schema-registry returns that catalog (dialect, per-type JSON Schema, example payload, and a drift-detecting fingerprint) so you can pin the shape client-side. Request
Response
event is required; contact_email or contact_phone identify the contact (unmatched events are still recorded and stitch later). properties carries event attributes, message_id is a client-side dedup key, and timestamp is the client event time — the server’s receipt time remains the canonical sort key. A retry with the same Idempotency-Key or message_id returns deduped: true without writing a second row. The registry is fetched with a plain GET:
Node.js
Poll data.catalog_version to detect any change to the platform event contract cheaply, then diff each schema’s fingerprint to see which event types moved.

List event history

GET /api/v1/events
Cursor-paginated history of recent platform events for the authenticated tenant. Returns the standard paginated envelope; pass cursor from a prior page’s meta.pagination.cursor (an event id) to page forward. For a live tail use GET /events/stream (SSE) instead of polling.
string
Opaque pagination cursor from a prior page’s meta.pagination.cursor (an event id). Omit for the first page.
integer
Page size (1–200, default 25).
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Get event details

GET /api/v1/events/{id}
Fetch a single platform event by its id from the tenant’s recent-event history. The id may be either the canonical stream id (&lt;ms&gt;-&lt;seq&gt;) or a publisher-minted evt_* id carried in the payload. Returns 404 when no event with the given id is within the current history window for the tenant.
string
required
Event id — the canonical stream id (&lt;ms&gt;-&lt;seq&gt;) or a legacy evt_* payload id.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Consume events for a consumer group

GET /api/v1/events/consume
Poll the next batch of platform events for a managed consumer group. Reads in order from the group’s server-side committed offset and does NOT advance it — commit meta.next_offset via POST /events/consume/commit only after you have durably processed the batch. This is at-least-once: a crash before commit re-delivers the same batch, so deduplicate on each event’s id. A group that has never committed starts at the beginning of the retained window.
string
required
Consumer-group name (1–128 chars of letters, digits, ._:-, starting alphanumeric). Offsets are tracked per group, so independent consumers use distinct groups.
integer
Maximum events to return (1–500, default 100).
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

List consumer groups

GET /api/v1/events/consumer-groups
List the tenant’s managed event-stream consumer groups with each group’s committed offset and approximate lag (retained events after the committed offset).
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Get the versioned event schema registry

GET /api/v1/events/schema-registry
Machine-readable, versioned catalog of every event type the firehose (GET /events/stream, GET /events/consume) and webhooks emit. Each entry carries a Draft-07 envelope JSON Schema (with the type literal pinned), a realistic example payload, and a deterministic fingerprint. Poll the top-level catalog_version to learn — in one field — whether the platform event contract changed at all, then diff each entry’s fingerprint to see which event schemas moved, so a data-warehouse or SIEM consumer can pin schemas and regenerate types only when they actually drift. The catalog is identical for every tenant.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Subscribe to the real-time platform event stream (SSE)

GET /api/v1/events/stream
Server-Sent Events stream of platform events for the tenant (message, call, and other resource lifecycle events) so live dashboards can be built without polling GET /events or running a webhook receiver. Authenticate a browser EventSource with the Clerk session cookie (withCredentials) or ?token=; server-side callers pass the secret API key. Optional ?types= narrows the event types delivered; reconnect with the Last-Event-ID header (or ?lastEventId=) to replay buffered events and resume without gaps.
string
Comma-separated allowlist of event types to deliver (e.g. message.delivered,message.failed). Applied to both the Last-Event-ID replay pass and the live tail. Omit to receive all event types for the tenant.
string
Resume cursor — the id of the last event the client received. Replays buffered events newer than this id before live streaming.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Commit a consumer-group offset

POST /api/v1/events/consume/commit
Advance a consumer group’s committed offset after you have processed a batch. Monotonic: a stale, duplicated, or out-of-order commit never rewinds the offset and returns applied: false. To move backwards (replay/backfill) use POST /events/consume/seek.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.
string
required
Consumer-group name.
string
required
The offset to commit — a stream id (&lt;ms&gt;-&lt;seq&gt;, typically meta.next_offset from a consume batch) or 0.

Seek a consumer group (replay / backfill)

POST /api/v1/events/consume/seek
Reset a consumer group’s offset to replay or backfill events. Provide exactly one of to (beginning = replay the full retained window, end = skip everything currently retained and consume only new events) or offset (an explicit stream id / 0). Unlike commit, seek may move the offset backwards.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.
string
required
Consumer-group name.
string (enum: beginning|end)
Relative seek target. Mutually exclusive with offset.
string
Explicit offset (stream id or 0). Mutually exclusive with to.

Track a product event

POST /api/v1/events/track
Records a domain event for a contact in your workspace, such as Order Placed, Subscription Renewed, or Trial Converted, to drive lifecycle campaigns, journey triggers, and the customer-360 timeline. Authenticate with your secret API key via the X-API-Key header. The JSON body requires event (the event name) and may identify the contact with contact_email or contact_phone; events with no matching contact are still recorded and can be stitched to a contact later. Optionally pass properties (an object of event attributes), message_id (a client-supplied de-duplication key), and timestamp (an ISO-8601 client event time, while the server receipt time stays the canonical sort key). Send an Idempotency-Key header to make retries safe. Returns { received, event_id, contact_id, deduped }.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.