---
title: Webhook Event Payloads
slug: kq2v-webhook-event-payloads
docTags: 
createdAt: 2026-09-14T00:00:00.000Z
---

Chord's server events service subscribes to Shopify webhook topics and transforms each one into a CDP event. This page documents which topics produce which events, and the properties Chord adds that aren't present in the raw Shopify payload.

For the core property tables shared across all sources — client, Shopify, and Chord OMS — see the individual pages under **[Server Events > Track](docId\:z57EPqMJDr7cJ3wQ1JxDO)**.

# Supported webhook topics

| Shopify webhook topic           | Chord event            | Customer properties |
| ------------------------------- | ---------------------- | ------------------- |
| `orders/create`                 | Order Completed        | Yes                 |
| `orders/cancelled`              | Order Cancelled        | Yes                 |
| `orders/fulfilled`              | Order Fulfilled        | Yes                 |
| `checkouts/create`              | Checkout Started       | Yes                 |
| `refunds/create`                | Order Refunded         | Yes                 |
| `subscription_contracts/create` | Subscription Created   | Yes                 |
| `subscription_contracts/cancel` | Subscription Cancelled | Yes                 |
| `subscription_contracts/pause`  | Subscription Paused    | Yes                 |
| `fulfillments/create`           | Fulfillment Created    | No                  |
| `fulfillments/update`           | Fulfillment Updated    | No                  |
| `orders/delete`                 | Order Deleted          | No                  |
| `customers/delete`              | Customer Deleted       | No                  |
| `customers/merge`               | Customer Merged        | No                  |
| `locations/delete`              | Location Deleted       | No                  |
| `products/delete`               | Product Deleted        | No                  |

:::hint{type="info"}
Subscription contract topics are limited by Shopify to the app that created the contract. See [Enabling Subscription Events](docId\:F9xrfOppDl8EFLEBeDuXg) for details.
:::

# Customer properties

Shopify removed lifetime customer statistics such as `orders_count` from webhook payloads in the 2025-01 API version, and no webhook payload carries them today. Chord looks the customer up through the Shopify Admin API and adds the following properties to every event that carries a customer ID.

| Name                                 | Type       | Description                                                    |
| ------------------------------------ | ---------- | -------------------------------------------------------------- |
| `repeat`                             | `boolean`  | Whether the customer had ordered before this event             |
| `is_new_customer`                    | `number`   | The same signal as `repeat`, inverted, as `0` or `1`           |
| `customer_order_count`               | `number`   | Lifetime order count as Shopify reports it                     |
| `customer_lifetime_revenue`          | `number`   | Total the customer has spent across their lifetime             |
| `customer_lifetime_revenue_currency` | `string`   | ISO currency code for `customer_lifetime_revenue`              |
| `customer_since`                     | `string`   | Date and time the customer record was created in Shopify       |
| `customer_tags`                      | `string[]` | Tags applied to the customer in Shopify                        |
| `customer_subscriber_status`         | `string`   | Product subscriber status, e.g. `ACTIVE` or `NEVER_SUBSCRIBED` |

Both `repeat` and `is_new_customer` describe the same thing in two shapes, so destinations can read whichever convention they already expect without a migration.

## New versus returning

`repeat` and `is_new_customer` answer a single question: *had this customer ordered before the event being reported?*

Shopify counts an order against the customer as soon as it is created, so an order-scoped webhook reports a `customer_order_count` that already includes the order in the event. A first-time buyer's `orders/create` therefore arrives with `customer_order_count: 1`, and Chord excludes that order before deciding the flags:

```json
{
  "repeat": false,
  "is_new_customer": 1,
  "customer_order_count": 1
}
```

A returning customer placing their third order arrives as:

```json
{
  "repeat": true,
  "is_new_customer": 0,
  "customer_order_count": 3
}
```

On Checkout Started and the subscription events there is no order in the event, so no adjustment is made and the flags describe the customer's order history as it stands.

`customer_order_count` is always the raw figure Shopify returned, never adjusted.

## Requirements

The Admin API access token must include the `read_customers` scope in addition to `read_orders`. Without it, Shopify rejects the customer lookup and events are delivered without these properties.

:::hint{type="warning"}
Customer properties are added on a best-effort basis. If the lookup fails for any reason — a missing scope, an expired access token, a Shopify outage — Chord delivers the event without them rather than dropping or delaying it. If these properties are missing from your events, check the access token and its scopes first.
:::

## Timing

These values are read from Shopify at the moment the event is processed, rather than being carried in the webhook payload. If an event is retried after a delivery failure, it is enriched with the customer's state at retry time. In practice this only differs from the original attempt if the customer's order history changed in between.

# Verifying

Shopify's webhook testing doesn't send a payload that matches a real webhook, so complete a test transaction in your store to confirm events are flowing. You can view the delivered events in the **Debugger** tab of the Shopify webhook source in your CDP workspace.
