Shoppex supports order, subscription, product, query, feedback, affiliate, and reseller webhooks. Event names use colons as separators, like order:paid.
When creating webhooks through the Dev API, send the exact event name, for example order:paid. Wildcard patterns like invoice.* do not work. Fetch the full allowlist from GET /dev/v1/webhooks/events.
These event payloads are not the same as the dynamic_webhook callback used by DYNAMIC products. For that contract, see Dynamic product delivery.
For paid product purchases, subscribe to order:paid or order:paid:product.
If that purchase reduces available stock, Shoppex does not send a separate product:stock event for the same checkout.
order:item.delivered and order:item.delivery_failed report per-line-item fulfillment after payment. See Asynchronous and Manual Fulfillment for their payloads and recovery flow.
These events use the same base invoice payload shape as order:paid:
order:created
order:updated
order:partial
order:paid
order:cancelled
order:disputed
order:manual_payment_pending
Each invoice payload includes line_items. Every entry includes the stable line-item
id, product snapshot, optional variant, quantity, delivery_status, and
delivered_at. Paid events also include license_keys on delivered SERIALS
line items. Other lifecycle events omit the keys.
These events use the same invoice payload plus the products array, like order:paid:product:
order:created:product
order:updated:product
order:partial:product
order:paid:product
order:cancelled:product
order:disputed:product
A shop-level subscription receives the complete order. A webhook configured on
a specific product receives only that product’s matching line_items and
products entries. In a cart containing multiple serial products, product A’s
endpoint therefore never receives product B’s license keys.
Dashboard simulation for order:paid uses this same envelope shape and the same core fields, just with synthetic values.
license_keys contains the unredacted product keys delivered to the buyer. Treat
the webhook body as sensitive, avoid recording it in application logs, and only
forward it to systems that are allowed to store the delivered product.
variant_id and variant_title are null when the product has no variant.
license_keys is omitted unless a paid SERIALS line has committed keys. Use
the line-item id as the stable correlation key; carts can contain the same
product more than once with different variants.
product:dynamic currently uses the same invoice-style payload family as the order events.
It is not the same as the direct dynamic_webhook delivery callback.
product:stock is for direct catalog stock changes, such as dashboard or API product edits.
For stock consumed by checkout, use the matching order event, usually order:paid:product.
Four enrollment-lifecycle events share one payload family: a single reseller object. They are
reseller:enrolled, reseller:application.created, reseller:application.rejected, and
reseller:suspended. reseller:order.completed, reseller:tier.advanced, and the two
reseller:supplier_order.* events each have their own shape, documented below.reseller:enrolled fires on all three enrollment paths (invite accepted, self-enrollment in
open mode, and merchant approval of an application). Reinstating a suspended reseller does not
send an event. There is no reseller:reinstated.The two reseller:supplier_order.* events belong to the reselling shop, not the supplier’s:
they tell you what happened when your own store auto-purchased a sold item from your supplier.The remaining supported event names on this page are listed as valid event values.
Dedicated public example payloads for product:created, product:edited, product:stock, query:created, query:replied, feedback:received, and affiliate:payout_requested are not expanded here yet.
Triggered after Shoppex starts dynamic product delivery for an invoice-backed purchase.
This webhook uses invoice context and is separate from the direct dynamic_webhook delivery request.
Triggered when a customer becomes an active reseller. reseller:application.created,
reseller:application.rejected and reseller:suspended carry the identical reseller object —
only status and the timestamp fields differ.
tier is null when no tier is assigned yet. application_note is only populated for
application-mode enrollments. lifetime_revenue is a decimal string, lifetime_orders an
integer.
Triggered when a wholesale reseller order is paid from the reseller’s balance and delivered.
The items array is the price snapshot frozen at order time. It is not re-derived from the
current tier or product prices.
Triggered when an order completion pushes a reseller’s lifetime totals past a tier’s
auto-advance threshold. This event only ever fires alongside reseller:order.completed —
there is no other code path that advances a tier automatically. Note the flat shape: the
reseller is identified by reseller_id and email at the top level, not by a nested
reseller object.
previous_tier is null when the reseller had no tier before. discount_percent is a number
on this event, unlike the decimal strings used for money fields.
Triggered when one of your products is fulfilled by an automatic wholesale purchase at your
supplier and the codes reached your buyer. Fires on your own shop.
amount is what was charged to your reseller balance at the supplier. A partial supplier
delivery still sends this event, with shortfall_quantity above zero.
Triggered when the automatic supplier purchase fails to deliver. status is REFUNDED when
the buyer was refunded and FAILED when no refund was possible. amount carries the refunded
sum or null. supplier_shop.invoice_uniqid is always null here, because no usable supplier
invoice exists.
failure_reason is a CODE: message string. Common codes are SUPPLIER_OUT_OF_STOCK,
ATTEMPTS_EXHAUSTED, and the guard failures for a disabled source, an inactive reseller
relationship, or a supply chain deeper than three shops.
All webhook payloads include these top-level fields:
Field
Type
Description
event
string
Event type, for example order:paid
data
object
Event-specific payload
created_at
number
Unix timestamp when the event was created
Top-level webhook created_at is a Unix timestamp.
Nested timestamps inside data, like invoice created_at / updated_at or subscription period fields, are ISO 8601 strings when present.
Webhooks
Setup, verification, and response handling
Dynamic delivery
Deliver products in real time through the webhook response