Skip to main content

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:

AttributeTypeExampleMeaning
specversionstring"1.0"CloudEvents spec version. Always "1.0" in v1.
idstring (UUID)"7c4e6a41-7e70-4f3d-9e24-1c3f0c1c2a01"Unique per delivery. Use this to deduplicate.
sourceURI-reference"https://api.<environment>/screener"Logical producer; stable per environment.
typestring"com.auditdata.listo.screening.completed.v1"Event type with version suffix.
timeRFC 3339 timestamp"2026-05-08T09:30:00Z"When the event was emitted (UTC, always with Z).
datacontenttypestring"application/json"Always "application/json" in v1.
dataobject{ … 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.

IDWhereWhat it identifies
id (envelope)top-level id on the CloudEventA specific delivery. Fresh UUID per emission, used for dedup against Service Bus redeliveries.
data.idinside the payloadThe 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