Event envelope
CloudEvents is a CNCF specification for describing event data in a common, transport-independent way. Every event Listo emits is a CloudEvents 1.0 document.
If you've never used CloudEvents before, the only thing you need to
know is that an event is a JSON object with a small set of standard
top-level fields ("attributes") plus an arbitrary payload under
data. The standard attributes — id, source, type, time, etc.
— let any consumer log, route, deduplicate, and correlate events
without parsing the payload.
The envelope is the Service Bus delivery format. The Sessions API returns the screening payload directly without an envelope; see REST reference.
This page describes the envelope. The payload schema is on Screening completed.
Required attributes
Listo always sets the following attributes on every event:
| Attribute | Type | Example | Meaning |
|---|---|---|---|
specversion | string | "1.0" | CloudEvents spec version. Always "1.0" in v1. |
id | string (UUID) | "7c4e6a41-7e70-4f3d-9e24-1c3f0c1c2a01" | Unique per delivery. Use this to deduplicate. |
source | URI-reference | "https://api.<environment>/screener" | Logical producer; stable per environment. |
type | string | "com.auditdata.listo.screening.completed.v1" | Event type with version suffix. |
time | RFC 3339 timestamp | "2026-05-08T09:30:00Z" | When the event was emitted (UTC, always with Z). |
datacontenttype | string | "application/json" | Always "application/json" in v1. |
data | object | { … screening … } | The screening payload. See Screening completed. |
Two different IDs
There are two id values in flight on every event. Don't mix them up.
| ID | Where | What it identifies |
|---|---|---|
id (envelope) | top-level id on the CloudEvent | A specific delivery. Fresh UUID per emission, used for dedup against Service Bus redeliveries. |
data.id | inside the payload | The session in Listo's database. Stable across redeliveries; identical between the queue copy and the Sessions API copy. |
If you want "have I processed this session before?", key on data.id.
If you want "have I processed this exact message before?", key on the
envelope id. The two answer different questions; in practice you usually
want data.id-keyed idempotency at the application layer plus envelope
id-keyed dedup right at the receive boundary.
Stability of source
source is a stable URI per environment. It identifies the producer
system, not any per-(integrating system, tenant) subset of it — so it
does not vary per integrating system, per tenant, or per session, even
though events are routed to a different queue for each (integrating
system, tenant) pair.
The exact source value is determined at deployment and may differ
between sandbox and production. Don't hard-code a comparison against
a specific URL.
Stability of type
type is the contract identifier for the payload schema. The full pattern
is:
com.auditdata.listo.<domain>.<event>.v<major>
For v1 there is exactly one value:
com.auditdata.listo.screening.completed.v1
Future event types will follow the same convention. New versions of an
existing event ship as a new type (...completed.v2). New optional
fields may be added to the data payload of an existing version
without a bump — see
Versioning & compatibility.
Worked example envelope
{
"specversion": "1.0",
"id": "7c4e6a41-7e70-4f3d-9e24-1c3f0c1c2a01",
"source": "https://api.<environment>/screener",
"type": "com.auditdata.listo.screening.completed.v1",
"time": "2026-05-08T09:30:00Z",
"datacontenttype": "application/json",
"data": {
"id": 1138291,
"...": "see screening-completed.md for the full payload"
}
}
Optional attributes we don't set
CloudEvents 1.0 defines a few optional attributes (subject,
dataschema) that we deliberately don't set in v1. If they appear on a
future event type, we'll document them at the same time we ship that
type — they will not silently start appearing on screening.completed.v1.
Where to next
- Screening completed — the full
datapayload schema. - Delivery semantics — what at-least-once means for your dedup.