Event catalog
Events follow the
{resource}.{transition} naming convention. The payment_order.* namespace is reserved for orders managed by the Transactions Engine.
The envelope
Every event has the same outer shape:Sample payloads
payment_order.created — inbound
payment_order.success — inbound
Same data.id; later state. The instrument now has endToEndId populated and processedAt is set.
payment_order.created — outbound
payment_order.approved — outbound
payment_order.success — outbound
payment_order.failed — outbound
errorCode is a stable UPPER_SNAKE_CASE value. Common codes include INSUFFICIENT_FUNDS, RECIPIENT_INVALID, LIMIT_EXCEEDED, NETWORK_REJECTED.
payment_order.expired — inbound only
Routing
A reasonable handler shape:4xx an unknown event; that marks the delivery permanently failed.
Direction filtering
If you only care about inbound or outbound:data.direction field is always present on payment_order.* events.
Ordering caveats
Events on the same order can arrive out of order. For example, you may receivesuccess before processing if the underlying state machine advanced quickly and the processing delivery was retried after a transient failure on your side.
Use data.status as the source of truth. If a processing event arrives after you have already seen success, the order is still SUCCESS — the late event does not regress your local state.
A robust handler updates local state using a monotonic version (data.ordVersion), refusing to roll back to an older version:
Next
Webhooks overview
Delivery contract.
Verifying signatures
Verify before processing.
Best practices
Idempotent consumer pattern.