Events
Things happen on your tenant all the time: an order is placed, a customer is activated, stock changes, a price is updated. Each of those is an event — a small, structured record of something that occurred, published the moment it happens. The event stream is how your code finds out, without polling and without the part of the platform that changed having to know you exist.
You don't read the stream over a raw connection. You react to it two ways:
- From an App — declare which events your app subscribes to, and the platform runs your handler when one arrives. Today only the lifecycle events
app.installedandapp.uninstalledare verified for App handlers (as of 2026-09); Events you receive has the detail. - At your own HTTP endpoint — register a Webhook and the platform delivers matching events to your URL.
Both draw on the same stream. Pick the App handler for an app's own lifecycle, such as seeding defaults on install; pick a Webhook when the reaction to a business event lives in your own infrastructure. Choose an event surface compares the options.
What an event looks like
Every event the platform publishes shares one envelope. These are the fields you can rely on being there:
{
"tenant_id": "acme-eu",
"topic": "revenexx.orders.order.placed",
"id": "evt_01jc8m4yq2…",
"data": { "number": "A-10482", "grand_total": 185.16, "currency": "EUR", "item_count": 3, "cart_id": "…" },
"metadata": { "source": "checkout" },
"time": "2026-05-31T10:00:00Z"
}
| Field | Type | What it is |
|---|---|---|
tenant_id | string | The tenant the event belongs to (your tenant slug). |
topic | string | What happened, e.g. revenexx.orders.order.placed. See Event types. |
id | string | A stable, unique id for this event. Use it to deduplicate. |
data | object | The payload. Its fields depend on the topic. |
metadata | object | Routing context, projected onto delivery headers. Values are strings. May be empty. |
time | string | ISO-8601 UTC instant the event occurred. |
data and metadata are always JSON objects. An empty one is {}, never null and never an array.
data object as the request body — the id, topic and metadata reach your endpoint as headers instead.metadata becomes delivery headers
When an event reaches a webhook, each metadata key
arrives as an X-Revenexx-<key> request header — "source": "checkout" arrives
as X-Revenexx-Source: checkout. So:
- Values are strings. Structured data belongs in
data. - Never put a secret in
metadata. Headers get logged along the way. - Don't name a key
event-id,topicortimestamp. Those would replace the platform's own delivery headers of the same name.
Topics name what happened
A topic is a dot-separated, lower-case name whose final segment is the action,
in the past tense. Real producers publish a namespaced form — <vendor>.<app>.<entity>.<action>,
as in acme.billing.invoice.settled — so names can never collide between
publishers. The name an App declares in its manifest is the short <entity>.<action> part; the topic you subscribe to puts the vendor and app in front of it. Event
types has the full taxonomy; subscribe using
the exact topic string the catalog lists for the event you want.
You subscribe by topic. An App lists the events it wants in its manifest; a Webhook destination is configured with the topics it should receive. Either way, you only get the topics you ask for.
Delivery you can rely on
Webhook deliveries are at least once. A failed delivery is retried, so a transient failure on your side doesn't lose the event — but the same event can arrive more than once. Retries don't go on forever: a webhook gets about 8.5 hours, see Delivery. Build handlers to be idempotent: key off the event id (the X-Revenexx-Event-Id header on a webhook) and ignore one you've already processed.
The delivery semantics of an App handler — ordering, retries, at-least-once versus at-most-once — are not settled enough to document (as of 2026-09). Write an App handler to survive a duplicate, an out-of-order delivery and a missing one; Events you receive shows how.
Order is best-effort, not guaranteed. Don't assume order.acknowledged always lands after order.placed; reconstruct sequence from the entity's own state and timestamps when it matters. A webhook delivery does not carry the event's time.
What's in this section
- Event types — how topics are named, the shape of payloads, and where to find the exact catalog for your tenant.
- Event catalog — the business events the revenexx commerce apps publish, with the fields each carries.
- Consuming events — the two ways to react: App handlers and Webhooks, and how to choose.
Where to go next
- Choose an event surface — which consumer to use for a given reaction: a webhook, a workflow trigger or an App handler.
- Webhooks — deliver events to your own HTTP endpoint.
- Apps — build installable logic that publishes and subscribes to events inside Revenue Cloud.
- Integration Studio — when an event should trigger a durable workflow against an external system.