Event catalog

The business events the revenexx commerce apps publish, with the topic to subscribe to, when each one fires and the fields every payload carries.

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, so placed under Orders is revenexx.orders.order.placed.
  • Required fields. The data fields every payload of that topic carries. Most events also carry optional fields, which the data_schema in your catalog lists.
  • Business events only. Most apps also publish a created, updated or deleted topic 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 to order.placed, not to order.created, which fires before any position exists. See Which order event to subscribe to.
This list was checked against each app's declared events and the code that publishes them (as of 2026-10). A tenant sees only the events of the apps it has installed, and an App you build adds its own. Treat your tenant's catalog as the contract.

Buying and orders

Orders — revenexx.orders.<event>

EventFires whenRequired fields
order.placedAn order is placed and needs no approvalorder_id, number, status, currency, grand_total, item_count, items
order.requestedAn order is submitted and has to wait for approvalThe order.placed fields, plus approval_reason
order.acknowledgedThe fulfilling system has taken the order overorder_id, number
order.cancelledThe whole order is cancelledorder_id, number, item_count, grand_total
order.item_cancelledOne position is cancelledorder_id, number, item_id, quantity_cancelled, quantity_remaining
order.shipment_createdA shipment is createdorder_id, number, shipment_id, items, fulfillment_status
order.completedThe order is closed: by hand, through a shipment or by a paymentorder_id, number, via
order.payment_status_changedThe payment status of the order changesorder_id, number, from, to
order.heldThe order is put on holdorder_id, number
order.unheldThe hold is liftedorder_id, number
order.return_registeredA return is registeredorder_id, number, return_id, return_number, positions
order.return_receivedA return arrivesorder_id, number, return_id, return_number
order.return_completedA return is completedorder_id, number, return_id, return_number, restock
order.return_rejectedA return is rejectedorder_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>

EventFires whenRequired fields
payment.authorizedMoney is reservedpayment_id, method, amount, currency, authorized_at
payment.capturedMoney has movedpayment_id, method, amount, currency, captured_amount
payment.failedThe payment will not happenpayment_id, method, amount, currency, error_code, error_message
payment.refundedA captured payment is paid back in fullpayment_id, method, amount, currency, refunded_amount
payment.cancelledThe payment is called off before money movedpayment_id, method, amount, currency
payment.action_requiredThe buyer has to act, for example a 3-D Secure check or a redirectpayment_id, method, amount, currency, next_action_kind
payment.dunning_advancedAn overdue payment moves to the next dunning stagepayment_id, from_stage, to_stage, days_overdue

Quotes — revenexx.quotes.<event>

EventFires whenRequired fields
quote.requestedA buyer requests a quote, or a seller opens one for a buyerquote_id, number
quote.quotedAn offer is sentquote_id, number
quote.rejectedThe request is rejectedquote_id, number, reason
quote.decidedThe buyer accepts or declinesquote_id, number, status
quote.messageA customer-visible message is added to the quote. Internal notes publish nothingquote_id, number
quote.expiringA quoted offer is close to its valid_until date. A setting can turn the warning offquote_id, number
quote.expiredThe offer has expiredquote_id, number

Carts — revenexx.carts.<event>

EventFires whenRequired fields
cart.orderedA cart is turned into an ordercart_id, currency, item_count, subtotal, items
cart.abandonedA cart goes idle past its limit, or is abandoned by handcart_id, item_count, subtotal, last_activity_at, abandon_after_minutes, reason
cart.mergedTwo active carts are merged, including when a sign-in merges a guest cart into an existing onesource_cart_id, target_cart_id, strategy, resulting_item_count
cart.reopenedAn abandoned cart is reopenedcart_id, item_count

Order lists — revenexx.orderlists.<event>

EventFires whenRequired fields
order_list.converted_to_orderA list is turned into an orderlist_id, list_kind, order_id, item_count
order_list.added_to_cartThe lines of a list are added to a cartlist_id, list_kind, cart_id, item_count, added, skipped

Punchout — revenexx.punchout.<event>

EventFires whenRequired fields
session.openedA punchout visit beginssession_id, psid, account_id, protocol, channel_code, expires_at, opened_at
session.closedThe visit endssession_id, psid, account_id, protocol, status, closed_at
cart.importedA cart arrives from the buyer's systemsession_id, psid, account_id, protocol, cart_id, imported_lines, failed_lines, imported_at
cart.transferredA cart is handed back to the buyer's systemsession_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>

EventFires whenRequired fields
purchase_request_event.createdA 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 movesA 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>

EventFires whenRequired fields
stock_level.lowA 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 ERPstock_level_id, location_code, available, reorder_point, shortfall
stock_level.out_of_stockAvailable stock drops to zero or belowstock_level_id, location_code, on_hand, reserved, available, previous_available, detected_at
stock_level.back_in_stockAvailable stock rises above zero againThe stock_level.out_of_stock fields
reservation.expiredA stock reservation runs outreservation_id, stock_level_id, location_code, order_ref, quantity, held_since, expired_at

Products — revenexx.products.<event>

EventFires whenRequired fields
product.completeness_changedThe completeness score of a product changesproduct_id, family_id, score, required, filled, missing_attributes
category.recomputedThe members of a rule-based category are recomputedcategory_id, added, removed, rule_match, rule_hash, done
product.trashed, category.trashed, manufacturer.trashed, asset.trashedA 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 ownid, trash_batch, root_id, deleted_at
product.restored, category.restored, manufacturer.restored, asset.restoredA record comes back from the trash, again one event per recordid, trash_batch, root_id, restored_at

Prices — revenexx.prices.<event>

EventFires whenRequired fields
price_list.entries_changedEntries of a price list change in bulkprice_list_id, operation, changed_count, currency, scope
price_list.default_changedThe default price list changesprice_list_id, previous_default_id
price_list.trashedA price list goes to the trashprice_list_id, trash_batch, deleted_at
price_list.restoredA price list comes back from the trashprice_list_id, trash_batch, restored_at

Promotions — revenexx.promotions.<event>

EventFires whenRequired fields
redemption.committedA redemption is recorded against an orderredemption_id, promotion_id, order_id, amount, currency
redemption.releasedA redemption is releasedredemption_id, promotion_id, amount, reason
promotion.exhaustedA promotion's limit or budget is used uppromotion_id, limit_kind, consumed
promotion.trashedA promotion goes to the trashpromotion_id, trash_batch, deleted_at
promotion.restoredA promotion comes back from the trashpromotion_id, trash_batch, restored_at

Markets — revenexx.markets.<event>

EventFires whenRequired fields
market.default_changedThe default market changesmarket_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.

EventFires whenRequired fields
contact.registeredA contact registerscontact_id, email, registration_status, self_registered, registered_at
contact.registration_approvedA registration is approvedcontact_id, from, approved_at
contact.registration_rejectedA registration is rejectedcontact_id, reason, cause, rejected_at
contact.blockedA contact is blockedcontact_id, previous_status, blocked_at
organization.blockedAn organization is blockedorganization_id, name, previous_status, blocked_at
segment.recomputedThe members of a segment are recomputedsegment_id, added, removed, rule_match, rule_hash, done
organization.metrics_refreshedOrganization order metrics are rebuiltorganizations_refreshed, orders_considered, window, refreshed_at
organization.trashed, contact.trashed, segment.trashedA 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.restoredA record comes back from the trash<record>_id, trash_batch, restored, restored_at

Forms — revenexx.forms.<event>

EventFires whenRequired fields
form.submittedA form is submittedNot declared. Read the data_schema and sample in your tenant's catalog

Pages — revenexx.pages.<event>

EventFires whenRequired fields
page.publishedA page is publishedpage_id, revision_id, published_at
page.scheduledA publication is scheduledpage_id, scheduled_for
page.unscheduledA scheduled publication is cancelledpage_id
page.revertedDraft changes are discardedpage_id, discarded_mutations
comment.resolvedA comment is resolvedpage_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 is revenexx.products.product.trashed. The record stops acting and drops out of the lists, but it still exists, and it can come back.
  • <record>.deleted fires 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 the trash_batch, and each of them fires its own event.
  • Records that also publish <record>.updated fire 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 on trashed and restored instead of reading deleted_at off an update.

The payload fields that tie a group together:

  • trash_batch is 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, and restored lists 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

Was this page helpful?