Events API
Events endpoints exposed by the Devotel CPaaS API Base path:/api/v1/events
Endpoint count: 9
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’sorbit.request() helper.
List event history — GET /events
Page through the tenant’s recent-event history newest-first. The first request omitscursor; each page’s meta.pagination.cursor feeds the next request
while has_more is true.
Step 1 — first page
Node.js
has_more is true
Node.js
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 itsid — 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
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 yourLast-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)
?lastEventId=
query parameter (EventSource re-sends it as the Last-Event-ID header
automatically).
Sample stream frames
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
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
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/eventscursor 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}id from the tenant’s recent-event history. The id may be either the canonical stream id (<ms>-<seq>) 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 (
<ms>-<seq>) 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/consumemeta.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-groupsstring (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-registryGET /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?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/commitapplied: 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 (
<ms>-<seq>, typically meta.next_offset from a consume batch) or 0.Seek a consumer group (replay / backfill)
POST /api/v1/events/consume/seekto (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/trackOrder 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.