Event catalog
This page lists the business events the revenexx commerce apps publish, so you can plan a subscription before you have a tenant. It is a starting point, not the authority: your tenant's own list is GET /v1/events/catalog, which returns the events of the apps installed on that tenant, with a sample and a data_schema for each. How topics are named and how payloads change is on Event types, and Consuming events shows how to subscribe. Delivery is at least once and ordering is best effort, so key your handler on the event id: see Events.
How to read the tables
- Topic. Each heading gives the prefix, such as
revenexx.orders.. The topic you subscribe to is the prefix plus the event name in the table, soplacedunder Orders isrevenexx.orders.order.placed. - Required fields. The
datafields every payload of that topic carries. Most events also carry optional fields, which thedata_schemain your catalog lists. - Business events only. Most apps also publish a
created,updatedordeletedtopic when a record changes. They are not listed here, and they tell you that a record changed, not why. To act on a new order, subscribe toorder.placed, not toorder.created, which fires before any position exists. See Which order event to subscribe to.
Buying and orders
Orders — revenexx.orders.<event>
| Event | Fires when | Required fields |
|---|---|---|
order.placed | An order is placed and needs no approval | order_id, number, status, currency, grand_total, item_count, items |
order.requested | An order is submitted and has to wait for approval | The order.placed fields, plus approval_reason |
order.acknowledged | The fulfilling system has taken the order over | order_id, number |
order.cancelled | The whole order is cancelled | order_id, number, item_count, grand_total |
order.item_cancelled | One position is cancelled | order_id, number, item_id, quantity_cancelled, quantity_remaining |
order.shipment_created | A shipment is created | order_id, number, shipment_id, items, fulfillment_status |
order.completed | The order is closed: by hand, through a shipment or by a payment | order_id, number, via |
order.payment_status_changed | The payment status of the order changes | order_id, number, from, to |
order.held | The order is put on hold | order_id, number |
order.unheld | The hold is lifted | order_id, number |
order.return_registered | A return is registered | order_id, number, return_id, return_number, positions |
order.return_received | A return arrives | order_id, number, return_id, return_number |
order.return_completed | A return is completed | order_id, number, return_id, return_number, restock |
order.return_rejected | A return is rejected | order_id, number, return_id, return_number |
An order that waits for approval emits order.requested instead of order.placed, and emits order.placed once it is approved, with approved_by added; a rejected order is cancelled and never does. See Hand an order to the ERP.
Subscribe to these or to order_event.created, never both. order_event.created carries every entry in an order's trail, so using both processes a change twice.
Payments — revenexx.payments.<event>
| Event | Fires when | Required fields |
|---|---|---|
payment.authorized | Money is reserved | payment_id, method, amount, currency, authorized_at |
payment.captured | Money has moved | payment_id, method, amount, currency, captured_amount |
payment.failed | The payment will not happen | payment_id, method, amount, currency, error_code, error_message |
payment.refunded | A captured payment is paid back in full | payment_id, method, amount, currency, refunded_amount |
payment.cancelled | The payment is called off before money moved | payment_id, method, amount, currency |
payment.action_required | The buyer has to act, for example a 3-D Secure check or a redirect | payment_id, method, amount, currency, next_action_kind |
payment.dunning_advanced | An overdue payment moves to the next dunning stage | payment_id, from_stage, to_stage, days_overdue |
Quotes — revenexx.quotes.<event>
| Event | Fires when | Required fields |
|---|---|---|
quote.requested | A buyer requests a quote, or a seller opens one for a buyer | quote_id, number |
quote.quoted | An offer is sent | quote_id, number |
quote.rejected | The request is rejected | quote_id, number, reason |
quote.decided | The buyer accepts or declines | quote_id, number, status |
quote.message | A customer-visible message is added to the quote. Internal notes publish nothing | quote_id, number |
quote.expiring | A quoted offer is close to its valid_until date. A setting can turn the warning off | quote_id, number |
quote.expired | The offer has expired | quote_id, number |
Carts — revenexx.carts.<event>
| Event | Fires when | Required fields |
|---|---|---|
cart.ordered | A cart is turned into an order | cart_id, currency, item_count, subtotal, items |
cart.abandoned | A cart goes idle past its limit, or is abandoned by hand | cart_id, item_count, subtotal, last_activity_at, abandon_after_minutes, reason |
cart.merged | Two active carts are merged, including when a sign-in merges a guest cart into an existing one | source_cart_id, target_cart_id, strategy, resulting_item_count |
cart.reopened | An abandoned cart is reopened | cart_id, item_count |
Order lists — revenexx.orderlists.<event>
| Event | Fires when | Required fields |
|---|---|---|
order_list.converted_to_order | A list is turned into an order | list_id, list_kind, order_id, item_count |
order_list.added_to_cart | The lines of a list are added to a cart | list_id, list_kind, cart_id, item_count, added, skipped |
Punchout — revenexx.punchout.<event>
| Event | Fires when | Required fields |
|---|---|---|
session.opened | A punchout visit begins | session_id, psid, account_id, protocol, channel_code, expires_at, opened_at |
session.closed | The visit ends | session_id, psid, account_id, protocol, status, closed_at |
cart.imported | A cart arrives from the buyer's system | session_id, psid, account_id, protocol, cart_id, imported_lines, failed_lines, imported_at |
cart.transferred | A cart is handed back to the buyer's system | session_id, psid, account_id, protocol, transfer_id, correlation_key, transferred_at |
revenexx.punchout.cart.imported and the revenexx.carts. topics share event names but not prefixes. Always subscribe with the full topic.
Procurement — revenexx.procurement.<event>
| Event | Fires when | Required fields |
|---|---|---|
purchase_request_event.created | A step of a purchase request is recorded. name says which: purchase_request.requested, .approved, .declined, .cancelled, .ordered or .notification, plus budget.confirmed and budget.withdrawn for budget moves | A snapshot of the request: purchase_request_id, number, status, contact_id, organization_id, currency, grand_total, order_id, cart_id |
Set up purchase approvals walks through how to react to a decision.
Catalog, stock and pricing
Inventories — revenexx.inventories.<event>
| Event | Fires when | Required fields |
|---|---|---|
stock_level.low | A stock level is at or below its reorder point. Announced at most once per UTC day while it stays low, see Send low-stock alerts to the ERP | stock_level_id, location_code, available, reorder_point, shortfall |
stock_level.out_of_stock | Available stock drops to zero or below | stock_level_id, location_code, on_hand, reserved, available, previous_available, detected_at |
stock_level.back_in_stock | Available stock rises above zero again | The stock_level.out_of_stock fields |
reservation.expired | A stock reservation runs out | reservation_id, stock_level_id, location_code, order_ref, quantity, held_since, expired_at |
Products — revenexx.products.<event>
| Event | Fires when | Required fields |
|---|---|---|
product.completeness_changed | The completeness score of a product changes | product_id, family_id, score, required, filled, missing_attributes |
category.recomputed | The members of a rule-based category are recomputed | category_id, added, removed, rule_match, rule_hash, done |
product.trashed, category.trashed, manufacturer.trashed, asset.trashed | A record goes to the trash. One event per record that goes with it, so a model with three variants fires four product.trashed, and each category of a subtree fires its own | id, trash_batch, root_id, deleted_at |
product.restored, category.restored, manufacturer.restored, asset.restored | A record comes back from the trash, again one event per record | id, trash_batch, root_id, restored_at |
Prices — revenexx.prices.<event>
| Event | Fires when | Required fields |
|---|---|---|
price_list.entries_changed | Entries of a price list change in bulk | price_list_id, operation, changed_count, currency, scope |
price_list.default_changed | The default price list changes | price_list_id, previous_default_id |
price_list.trashed | A price list goes to the trash | price_list_id, trash_batch, deleted_at |
price_list.restored | A price list comes back from the trash | price_list_id, trash_batch, restored_at |
Promotions — revenexx.promotions.<event>
| Event | Fires when | Required fields |
|---|---|---|
redemption.committed | A redemption is recorded against an order | redemption_id, promotion_id, order_id, amount, currency |
redemption.released | A redemption is released | redemption_id, promotion_id, amount, reason |
promotion.exhausted | A promotion's limit or budget is used up | promotion_id, limit_kind, consumed |
promotion.trashed | A promotion goes to the trash | promotion_id, trash_batch, deleted_at |
promotion.restored | A promotion comes back from the trash | promotion_id, trash_batch, restored_at |
Markets — revenexx.markets.<event>
| Event | Fires when | Required fields |
|---|---|---|
market.default_changed | The default market changes | market_id, code, previous_default_id, previous_default_code, changed_at |
Customers and content
Customers — revenexx.customers.<event>
These payloads carry personal data, such as a contact's email address.
| Event | Fires when | Required fields |
|---|---|---|
contact.registered | A contact registers | contact_id, email, registration_status, self_registered, registered_at |
contact.registration_approved | A registration is approved | contact_id, from, approved_at |
contact.registration_rejected | A registration is rejected | contact_id, reason, cause, rejected_at |
contact.blocked | A contact is blocked | contact_id, previous_status, blocked_at |
organization.blocked | An organization is blocked | organization_id, name, previous_status, blocked_at |
segment.recomputed | The members of a segment are recomputed | segment_id, added, removed, rule_match, rule_hash, done |
organization.metrics_refreshed | Organization order metrics are rebuilt | organizations_refreshed, orders_considered, window, refreshed_at |
organization.trashed, contact.trashed, segment.trashed | A record goes to the trash. An organization's contacts go with it, and each gets its own contact.trashed | <record>_id (such as contact_id), trash_batch, group, deleted_at |
organization.restored, contact.restored, segment.restored | A record comes back from the trash | <record>_id, trash_batch, restored, restored_at |
Forms — revenexx.forms.<event>
| Event | Fires when | Required fields |
|---|---|---|
form.submitted | A form is submitted | Not declared. Read the data_schema and sample in your tenant's catalog |
Pages — revenexx.pages.<event>
| Event | Fires when | Required fields |
|---|---|---|
page.published | A page is published | page_id, revision_id, published_at |
page.scheduled | A publication is scheduled | page_id, scheduled_for |
page.unscheduled | A scheduled publication is cancelled | page_id |
page.reverted | Draft changes are discarded | page_id, discarded_mutations |
comment.resolved | A comment is resolved | page_id, comment_uuid |
Deletes and the trash
Products, categories, manufacturers, assets, price lists, promotions, organizations, contacts and segments go to the trash when you delete them, and their topics follow that:
- The first delete fires
<record>.trashed, not<record>.deleted. For a product the topic isrevenexx.products.product.trashed. The record stops acting and drops out of the lists, but it still exists, and it can come back. <record>.deletedfires only when the record is gone for good: on a second delete, when the trash is emptied, when the platform removes a record that has sat in the trash longer than the tenant's retention (90 days unless the tenant set another) and that nothing still blocks, and when a contact is erased, which skips the trash.- A restore fires
<record>.restored. It brings back every record that shares thetrash_batch, and each of them fires its own event. - Records that also publish
<record>.updatedfire it whenever the record is written, and that includes the trash, the restore and the platform's daily bookkeeping on a record held in the trash. These are products, price lists, promotions, organizations and contacts. Act ontrashedandrestoredinstead of readingdeleted_atoff an update.
The payload fields that tie a group together:
trash_batchis shared by every record that went to the trash in the same delete. Restoring the record the delete was called on brings the whole batch back.root_id(products, categories, manufacturers and assets) is the record the delete or the restore was called on, such as the model whose variants or the category whose subtree went with it.group(promotions and customers) lists the ids that went with the delete, andrestoredlists the ids that came back.
If your integration removes a record from an ERP, a search index or a PIM on <record>.deleted alone, a trashed record stays there until the platform deletes it for good, and a record that something still blocks is never deleted. Subscribe to <record>.trashed to take it out, and to <record>.restored to put it back. Keep handling <record>.deleted as well, for records that skip the trash, such as an erased contact.
Apps with record topics only
Channels, cost centers and shipping have no business events listed here. Cost centers declare budget.stale, but nothing emits it (as of 2026-10). Their created, updated and deleted topics are in your tenant's catalog when the app is installed.
Where to go next
- Event types: topic naming, payload versions and how to find your tenant's catalog.
- Consuming events: react from an App handler or a webhook.
- Receive platform events: a worked receiver.