> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shoppex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook Events

> Supported webhook event names and example payloads

## Event Types

Shoppex supports order, subscription, product, query, feedback, and affiliate webhooks. Event names use colons as separators, like `order:paid`.

<Note>
  When creating webhooks through the Dev API, send explicit event names like `order:paid` — wildcard patterns like `invoice.*` are not supported. Fetch the full allowlist from `GET /dev/v1/webhooks/events`.
</Note>

<Info>
  These event payloads are not the same as the `dynamic_webhook` callback used by `DYNAMIC` products.
  For that contract, see [Dynamic Product Delivery](/api-reference/webhooks/dynamic-delivery).
</Info>

***

## Supported Event Names

<Tabs>
  <Tab title="Order Events">
    | Event                          | Description                          |
    | ------------------------------ | ------------------------------------ |
    | `order:created`                | Order created                        |
    | `order:updated`                | Order updated                        |
    | `order:partial`                | Partial payment received             |
    | `order:paid`                   | Order fully paid                     |
    | `order:cancelled`              | Order cancelled or expired           |
    | `order:disputed`               | Order dispute opened                 |
    | `order:created:product`        | Order created with product payload   |
    | `order:updated:product`        | Order updated with product payload   |
    | `order:partial:product`        | Partial payment with product payload |
    | `order:paid:product`           | Paid order with product payload      |
    | `order:cancelled:product`      | Cancelled order with product payload |
    | `order:disputed:product`       | Disputed order with product payload  |
    | `order:manual_payment_pending` | Manual payment review required       |

    <Note>
      For paid product purchases, subscribe to `order:paid` or `order:paid:product`.
      If that purchase reduces available stock, Shoppex does not emit a separate `product:stock` event for the same checkout.
    </Note>

    ### Payload Families

    #### Invoice Payload

    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`

    #### Invoice Payload With Products

    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`

    ### Example Payloads

    #### order:paid

    Triggered when an order/invoice is successfully paid.

    ```json theme={"system"}
    {
      "event": "order:paid",
      "data": {
        "uniqid": "abc123def456",
        "type": "PRODUCT",
        "status": "COMPLETED",
        "gateway": "STRIPE",
        "total": 49.99,
        "total_display": 49.99,
        "currency": "USD",
        "exchange_rate": 1,
        "crypto_exchange_rate": 0,
        "crypto_gateway": null,
        "apm_method": "CARD",
        "customer_email": "customer@example.com",
        "country": "US",
        "quantity": 1,
        "product_id": "prod_xyz",
        "product_title": "Pro License",
        "is_developer_invoice": false,
        "created_at": "2026-01-15T09:10:00.000Z",
        "updated_at": "2026-01-15T10:10:00.000Z"
      },
      "created_at": 1705318200
    }
    ```

    <Note>
      Dashboard simulation for `order:paid` uses this same envelope shape and the same core fields, just with synthetic values.
    </Note>

    #### order:cancelled

    Triggered when an order is cancelled or expires.

    ```json theme={"system"}
    {
      "event": "order:cancelled",
      "data": {
        "uniqid": "abc123def456",
        "type": "PRODUCT",
        "status": "VOIDED",
        "gateway": null,
        "total": 49.99,
        "total_display": 49.99,
        "currency": "USD",
        "exchange_rate": 1,
        "crypto_exchange_rate": 0,
        "crypto_gateway": null,
        "apm_method": null,
        "customer_email": "customer@example.com",
        "product_id": "prod_xyz",
        "product_title": "Pro License",
        "created_at": "2026-01-15T09:10:00.000Z",
        "updated_at": "2026-01-16T09:03:20.000Z"
      },
      "created_at": 1705400600
    }
    ```

    #### order:paid:product

    Same as `order:paid` but includes full product details in the payload.

    ```json theme={"system"}
    {
      "event": "order:paid:product",
      "data": {
        "uniqid": "abc123def456",
        "type": "PRODUCT",
        "status": "COMPLETED",
        "gateway": "STRIPE",
        "total": 49.99,
        "total_display": 49.99,
        "currency": "USD",
        "exchange_rate": 1,
        "crypto_exchange_rate": 0,
        "crypto_gateway": null,
        "apm_method": "CARD",
        "customer_email": "customer@example.com",
        "product_id": "prod_xyz",
        "product_title": "Pro License",
        "products": [
          {
            "uniqid": "prod_xyz",
            "title": "Pro License",
            "description": "Full access to all features",
            "price": 49.99,
            "price_display": 49.99,
            "currency": "USD",
            "type": "SERVICE"
          }
        ],
        "created_at": "2026-01-15T09:10:00.000Z",
        "updated_at": "2026-01-15T10:10:00.000Z"
      },
      "created_at": 1705318200
    }
    ```

    #### order:cancelled:product

    Same as `order:cancelled` but includes full product details.

    #### order:manual\_payment\_pending

    Triggered when Shoppex is waiting for an offline or manual payment review.

    ```json theme={"system"}
    {
      "event": "order:manual_payment_pending",
      "data": {
        "uniqid": "abc123def456",
        "type": "PRODUCT",
        "status": "PENDING",
        "gateway": "MANUAL",
        "total": 49.99,
        "total_display": 49.99,
        "currency": "USD",
        "exchange_rate": 1,
        "crypto_exchange_rate": 0,
        "crypto_gateway": null,
        "apm_method": null,
        "customer_email": "customer@example.com",
        "country": "US",
        "quantity": 1,
        "product_id": "prod_xyz",
        "product_title": "Pro License",
        "is_developer_invoice": false,
        "created_at": "2026-01-15T09:10:00.000Z",
        "updated_at": "2026-01-15T09:20:00.000Z"
      },
      "created_at": 1705315200
    }
    ```
  </Tab>

  <Tab title="Subscription Events">
    | Event                                | Description                                 |
    | ------------------------------------ | ------------------------------------------- |
    | `subscription:trial:started`         | Trial started                               |
    | `subscription:trial:ended`           | Trial ended                                 |
    | `subscription:created`               | Subscription created                        |
    | `subscription:updated`               | Subscription updated                        |
    | `subscription:renewed`               | Subscription renewed                        |
    | `subscription:cancelled`             | Subscription cancelled                      |
    | `subscription:upcoming`              | Upcoming renewal reminder                   |
    | `subscription:trial:started:product` | Trial started with product payload          |
    | `subscription:trial:ended:product`   | Trial ended with product payload            |
    | `subscription:created:product`       | Subscription created with product payload   |
    | `subscription:updated:product`       | Subscription updated with product payload   |
    | `subscription:renewed:product`       | Subscription renewed with product payload   |
    | `subscription:cancelled:product`     | Subscription cancelled with product payload |
    | `subscription:upcoming:product`      | Upcoming renewal with product payload       |

    ### Payload Family

    These events use the same subscription payload shape as `subscription:created`:

    * `subscription:trial:started`
    * `subscription:trial:ended`
    * `subscription:created`
    * `subscription:updated`
    * `subscription:renewed`
    * `subscription:cancelled`
    * `subscription:upcoming`
    * `subscription:trial:started:product`
    * `subscription:trial:ended:product`
    * `subscription:created:product`
    * `subscription:updated:product`
    * `subscription:renewed:product`
    * `subscription:cancelled:product`
    * `subscription:upcoming:product`

    ### Example Payloads

    #### subscription:created

    Triggered when a new subscription starts.

    ```json theme={"system"}
    {
      "event": "subscription:created",
      "data": {
        "id": "sub_abc123",
        "status": "ACTIVE",
        "gateway": "STRIPE",
        "customer_id": "cust_xyz789",
        "current_period_start": "2026-01-15T00:00:00.000Z",
        "current_period_end": "2026-02-15T00:00:00.000Z",
        "created_at": "2026-01-15T00:00:00.000Z"
      },
      "created_at": 1705314600
    }
    ```

    #### subscription:cancelled

    Triggered when a subscription is cancelled.

    ```json theme={"system"}
    {
      "event": "subscription:cancelled",
      "data": {
        "id": "sub_abc123",
        "status": "CANCELLED",
        "gateway": "STRIPE",
        "customer_id": "cust_xyz789",
        "current_period_start": "2026-01-15T00:00:00.000Z",
        "current_period_end": "2026-02-15T00:00:00.000Z",
        "created_at": "2026-01-15T00:00:00.000Z"
      },
      "created_at": 1705918200
    }
    ```

    #### subscription:renewed

    Triggered when a subscription renews for a new billing period.

    ```json theme={"system"}
    {
      "event": "subscription:renewed",
      "data": {
        "id": "sub_abc123",
        "status": "ACTIVE",
        "gateway": "STRIPE",
        "customer_id": "cust_xyz789",
        "current_period_start": "2026-02-15T00:00:00.000Z",
        "current_period_end": "2026-03-15T00:00:00.000Z",
        "created_at": "2026-01-15T00:00:00.000Z"
      },
      "created_at": 1707991800
    }
    ```
  </Tab>

  <Tab title="Reseller Events">
    | Event                               | Description                                             |
    | ----------------------------------- | ------------------------------------------------------- |
    | `reseller:invited`                  | Reseller invitation created                             |
    | `reseller:accepted`                 | Reseller accepted an invitation                         |
    | `reseller:suspended`                | Reseller relationship suspended                         |
    | `reseller:terminated`               | Reseller relationship terminated                        |
    | `reseller:embed_campaign_created`   | Reseller created an embed campaign                      |
    | `reseller:embed_campaign_updated`   | Reseller embed campaign changed status or metadata      |
    | `reseller:sale`                     | Invoice sale attributed to a reseller                   |
    | `reseller:payout_requested`         | Reseller requested a payout                             |
    | `reseller:stock_purchase_requested` | Reseller requested wholesale stock                      |
    | `reseller:stock_purchase_paid`      | Stock purchase invoice was paid                         |
    | `reseller:stock_purchase_revoked`   | Stock purchase request was revoked                      |
    | `reseller:stock_allocated`          | Stock was allocated to reseller inventory               |
    | `reseller:stock_item_delivered`     | Reseller delivered an inventory item to an end customer |

    ### Payload Notes

    Reseller webhook payloads are merchant-scoped. They include stable IDs plus snapshots needed by external systems.

    For example:

    * `relationship_id` identifies the reseller relationship with the merchant.
    * `reseller_user_id` identifies the reseller user.
    * `campaign_id` or `embed_campaign_id` identifies a reseller-owned embed campaign when available.
    * Stock events use `transfer_id` and inventory delivery events use `item_id`.

    ### Example Payloads

    #### reseller:sale

    Triggered when a completed invoice is attributed to a reseller link or reseller-owned embed.

    ```json theme={"system"}
    {
      "event": "reseller:sale",
      "data": {
        "relationship_id": "rel_123",
        "reseller_user_id": "usr_123",
        "invoice_id": "inv_db_123",
        "invoice_uniqid": "abc123def456",
        "affiliate_link_id": "aff_123",
        "embed_campaign_id": "emb_123",
        "product_id": "prod_123",
        "variant_id": "var_123",
        "retail_amount": 49.99,
        "commission_amount": 5,
        "currency": "USD",
        "mode": "AFFILIATE"
      },
      "created_at": 1777111200
    }
    ```

    #### reseller:stock\_purchase\_requested

    Triggered when a reseller requests wholesale stock.

    ```json theme={"system"}
    {
      "event": "reseller:stock_purchase_requested",
      "data": {
        "relationship_id": "rel_123",
        "reseller_user_id": "usr_123",
        "transfer_id": "rst_123",
        "product_id": "prod_123",
        "variant_id": null,
        "quantity": 25,
        "wholesale_unit_price": 7.5,
        "currency": "USD"
      },
      "created_at": 1777111200
    }
    ```

    #### reseller:stock\_item\_delivered

    Triggered when reseller inventory is delivered to an end customer.

    ```json theme={"system"}
    {
      "event": "reseller:stock_item_delivered",
      "data": {
        "relationship_id": "rel_123",
        "reseller_user_id": "usr_123",
        "transfer_id": "rst_123",
        "item_id": "rsi_123",
        "product_id": "prod_123",
        "variant_id": null,
        "serial_id": "ser_123",
        "delivered_to_email": "customer@example.com"
      },
      "created_at": 1777111200
    }
    ```

    <Note>
      `reseller:purchase` is accepted by the webhook event allowlist for integrations that already subscribed to the broad purchase name, but new integrations should use the more specific stock purchase events above.
    </Note>
  </Tab>

  <Tab title="Other Events">
    | Event                        | Description                                                   |
    | ---------------------------- | ------------------------------------------------------------- |
    | `product:created`            | Product created                                               |
    | `product:edited`             | Product updated                                               |
    | `product:stock`              | Product stock changed through a direct catalog/product update |
    | `product:dynamic`            | Dynamic product webhook dispatched                            |
    | `query:created`              | Support query created                                         |
    | `query:replied`              | Support query replied                                         |
    | `feedback:received`          | Feedback received                                             |
    | `affiliate:payout_requested` | Affiliate payout requested                                    |

    ### Payload Notes

    #### Invoice-Context Product Payload

    `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.

    #### Runtime-Specific Events

    `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`.

    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.

    ### Example Payload

    #### product:dynamic

    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.

    ```json theme={"system"}
    {
      "event": "product:dynamic",
      "data": {
        "uniqid": "abc123def456",
        "type": "PRODUCT",
        "status": "COMPLETED",
        "gateway": "STRIPE",
        "total": 49.99,
        "total_display": 49.99,
        "currency": "USD",
        "customer_email": "customer@example.com",
        "country": "US",
        "quantity": 1,
        "product_id": "prod_xyz",
        "product_title": "Dynamic Role",
        "is_developer_invoice": false,
        "created_at": "2026-01-15T09:10:00.000Z",
        "updated_at": "2026-01-15T10:10:00.000Z"
      },
      "created_at": 1705318200
    }
    ```
  </Tab>
</Tabs>

***

## Common Fields

All webhook payloads include these top-level fields:

| Field        | Type   | Description                           |
| ------------ | ------ | ------------------------------------- |
| `event`      | string | Event type (e.g., `order:paid`)       |
| `data`       | object | Event-specific payload                |
| `created_at` | number | Unix timestamp when event was created |

<Note>
  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.
</Note>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Webhooks Overview" icon="webhook" href="/api-reference/webhooks/overview">
    Setup, verification, and best practices
  </Card>

  <Card title="Dynamic Delivery" icon="truck-fast" href="/api-reference/webhooks/dynamic-delivery">
    Deliver products in real-time via webhook response
  </Card>
</CardGroup>
