# Event stream hub

In addition to a [webhook-based](https://docs.commercelayer.io/core/real-time-webhooks) event handling, Commerce Layer also provides a [Change Data Capture (CDC)](https://en.wikipedia.org/wiki/Change_data_capture) system to capture and track changes to data instantly.

Leveraging [Server-Sent Events (SSE)](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events), we enable clients to receive real-time notifications for [any changes](#supported-events) to the resources exposed by our platform (e.g. SKUs, orders, customers, etc.) just by subscribing to an event stream and consume updates as they happen.

{% hint style="danger" %}
The Stream Hub is in **beta**, and it's available only to our **enterprise** customers who [enable](#how-to-enable-the-stream-hub) it, meaning that only the changes to resources belonging to enterprise organizations with this feature enabled are pushed to the event stream. At the moment, there are no time limits on the event history storage. We will use this beta period before the official release to run load tests and determine how long to retain past event information.
{% endhint %}

SSE provides a lightweight, one-way communication channel from the server to the client over a single long-lived HTTP connection. It’s ideal for real-time feeds, system monitoring, or keeping local caches in sync with backend state. The protocol uses standard **HTTP** and the `text/event-stream` content type to send a stream of **UTF-8** encoded messages from the server to the client. Once connected, the client listens for incoming messages without needing to poll until the connection is closed.

{% hint style="warning" %}
If, for any reason, the connection to the stream hub drops before being intentionally closed, ensure that your stream reader app handles a reconnection/retry policy. Keep in mind that the disconnected stream is considered stale after 5 secs, so you cannot request a new real-time stream until **5 secs** after the connection drop.
{% endhint %}

Once reconnected, any event message that you hadn't received yet but the consumers had already started to process in the last **30 mins** is re-pushed to the live stream. Previous messages (dating back over half an hour from the disconnection) can always be [recovered](#event-recovery-and-replay-by-resource) by passing a specific time frame to the `/replay` endpoint of the stream hub.

{% hint style="info" %}
Both the real-time stream and the replay stream show only the events related to the [environment](https://docs.commercelayer.io/core/api-specification#environments) (*test* or *live*) associated with the integration token used to [authenticate the API call](#connecting-to-the-event-stream).
{% endhint %}

## Supported events

Currently, the list of events pushed to the Commerce Layer Stream Hub includes all the **create**, **update**, and **delete** operations on [any Core API resource](https://app.gitbook.com/o/-Lfu_B3DKew-kvoEWzTk/s/RWJeylueWkzLadK710XZ/).&#x20;

<table><thead><tr><th width="229.7890625">Event type</th><th>Description</th></tr></thead><tbody><tr><td><strong><code>heartbeat</code></strong></td><td>Checks the connection to the stream every <strong>10 secs</strong>.</td></tr><tr><td><strong><code>create</code></strong></td><td>A new resource has been created.</td></tr><tr><td><strong><code>update</code></strong></td><td>An existing resource has been updated.</td></tr><tr><td><strong><code>destroy</code></strong></td><td>An existing resource has been destroyed.</td></tr><tr><td><strong><code>anonymization_request</code></strong></td><td>The anonymization of a customer's data has been requested (available for the customer resource only).</td></tr><tr><td><strong><code>anonymization_cancel</code></strong></td><td>An ongoing customer's data anonymization request has been revoked (available for the customer resource only).</td></tr></tbody></table>

{% hint style="success" %}
In the near future, more information will be added to the stream (e.g. external payloads so as to be able to track events like: webhooks received from payment gateways, API calls made to third-party services, other side-effects tied to a specific resource, etc.).
{% endhint %}

## Connecting to the event stream

To start a connection to the Commerce Layer Stream Hub, you just need to send a GET request to the following endpoint:

```http
https://stream.commercelayer.io/{{your_domain}}
```

Where `{{your_domain}}` is the unique subdomain of your Commerce Layer organization.

{% hint style="warning" %}
Any call to the stream endpoints must be [authenticated](https://docs.commercelayer.io/core/authentication/client-credentials) using [integration](https://docs.commercelayer.io/core/api-credentials#integration) API credentials.
{% endhint %}

{% hint style="info" %}
This endpoint automatically acknowledges messages as they are streamed to the client.
{% endhint %}

Once connected, each message in the stream follows a simple format:

<table><thead><tr><th width="230.12109375">Key</th><th>Description</th></tr></thead><tbody><tr><td><strong><code>event</code></strong></td><td>The <a href="#supported-events">type of event</a>.</td></tr><tr><td><strong><code>id</code></strong></td><td>A unique identifier for the event.</td></tr><tr><td><strong><code>data</code></strong></td><td>A JSON object representing the resource and highlighting the delta of the change (or just a timestamp in case of heartbeats).</td></tr></tbody></table>

{% hint style="info" %}
The `data` object of each event message (other than the heartbeats) basically contains the whole related [event store resource object](https://app.gitbook.com/s/RWJeylueWkzLadK710XZ/event_stores/object), providing information about the type of change, the affected resource, the object changes payload, the actor who triggered the change, the exact timestamp of the change, and more (see the response in the [example](#example) below).
{% endhint %}

### Example

{% tabs %}
{% tab title="Request" %}
The following request starts a connection to the event stream of the enterprise organization with slug `my-org`:

```sh
curl -g -X GET \
  'https://stream.commercelayer.io/my-org' \
  -H 'Authorization: Bearer your-access-token' 
```

{% endtab %}

{% tab title="Response" %}
On success, the API responds with a `200 OK` status code, returning a continuous type-based event stream:

<pre class="language-http"><code class="lang-http"><strong>event: heartbeat
</strong>id: 1753710752696-0
data: {
  "event": "heartbeat",
  "timestamp": "2025-07-28T13:52:02Z"
}

<strong>event: heartbeat
</strong>id: 1753710752697-0
data: {
  "event": "heartbeat",
  "timestamp": "2025-07-28T13:52:12Z"
}

<strong>event: create
</strong>id: 1753710752698-0
data: {
  "event": "create",
  "resource_type": "skus",
  "resource_id": "CALKSWJxwW",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "code": {
      "from": null,
      "to": "MMOUSEMUG"
    },
    "name": {
      "from": null,
      "to": "Mickey Mouse Mug"
    },
      "description": {
      "from": null,
      "to": "A Mickey Mouse branded mug."
    },
    "pieces_per_pack": {
      "from": null,
      "to": 1
    },
    "weight": {
      "from": null,
      "to": 400.0
    },
    "unit_of_weight": {
      "from": null,
      "to": "gr"
    },
    "hs_tariff_number": {
      "from": null,
      "to": ""
    },
    "id": {
      "from": null,
      "to": 42231
    },
    "created_at": {
      "from": null,
      "to": "2025-07-28T13:52:22.000Z"
    },
    "updated_at": {
      "from": null,
      "to": "2025-07-28T13:52:22.000Z"
    }
  },
  "ip_address": "93.21.228.116",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "uuid": "45ff6e19293a2887ss78fde16d143ad8659a1dd1a6b0fbe6e2d3bac103c02cfcc",
  "test": false,
  "created_at": "2025-07-28T13:52:22.000Z",
  "updated_at": "2025-07-28T13:52:22.000Z",
  "who": {
    "application": {
      "id": "FKjbrtebqV",
      "client_id": "app_Cl13NTYd-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "sRmwmSGRfg",
      "type": "User",
      "email": "john@example.com",
      "first_name": "John",
      "last_name": "Doe"
    }
  }
}

<strong>event: heartbeat
</strong>id: 1753710752699-0
data: {
  "event": "heartbeat",
  "timestamp": "2025-07-28T13:52:32Z"
}

<strong>event: heartbeat
</strong>id: 1753710752699-0
data: {
  "event": "heartbeat",
  "timestamp": "2025-07-28T13:52:42Z"
}

<strong>event: destroy
</strong>id: 1753710752700-0
data: {
  "event": "destroy",
  "resource_type": "skus",
  "resource_id": "CALKSWJxwW",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "code": {
      "from": "MMOUSEMUG",
      "to": null
    },
    "name": {
      "from": "Mickey Mouse Mug",
      "to": null
    },
    "description": {
      "from": "A Mickey Mouse branded mug.",
      "to": null
    },
    "pieces_per_pack": {
      "from": 1,
      "to": null
    },
    "weight": {
      "from": 400.0,
      "to": null
    },
    "unit_of_weight": {
      "from": "gr",
      "to": null
    },
    "hs_tariff_number": {
      "from": "",
      "to": null
    },
    "do_not_ship": {
      "from": false,
      "to": null
    },
    "do_not_track": {
      "from": false,
      "to": null
    },
    "id": {
      "from": 42231,
      "to": null
    },
    "created_at": {
      "from": "2025-07-28T13:52:52.000Z",
      "to": null
    },
    "updated_at": {
      "from": "2025-07-28T13:52:52.000Z",
      "to": null
    },
    "metadata": {
      "from": {},
      "to": null
    }
  },
  "ip_address": "93.21.228.116",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "uuid": "f416778f7043a81266rf70e0a9f9337cf7508d32a1dccc7001f1826dc7150912",
  "test": false,
  "created_at": "2025-07-28T13:52:52.000Z",
  "updated_at": "2025-07-28T13:52:52.000Z",
  "who": {
    "application": {
      "id": "FKjbrtebqV",
      "client_id": "app_Cl13NTYd-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "sRmwmSGRfg",
      "type": "User",
      "email": "john@example.com",
      "first_name": "John",
      "last_name": "Doe"
    }
  }
}

<strong>event: heartbeat
</strong>id: 1753710752701-0
data: {
  "event": "heartbeat",
  "timestamp": "2025-07-28T13:53:02Z"
}

<strong>event: update
</strong>id: 1753710752702-0
data: {
  "event": "update",
  "resource_type": "skus",
  "resource_id": "WJoqSjzGjB",
  "organization_id": "XClEOFrjef",
    "payload": {
      "updated_at": {
        "from": "2025-07-29T15:22:20.884Z",
        "to": "2025-07-28T13:53:12.000Z"
      }
    },
  "ip_address": "93.45.228.116",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "uuid": "65bdc067600c4879c903c8252d4e03hhb75b818ca2464fa9217b4f0e755b45d9",
  "test": true,
  "created_at": "2025-07-28T13:53:12.000Z",
  "updated_at": "2025-07-28T13:53:12.000Z",
  "who": {
    "application": {
      "id": "DMjvdiebqM",
      "client_id": "myApp-Cl13nt-IDr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "sCfwmSNRed",
      "type": "User",
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe"
    }
  }
}

<strong>event: create
</strong>id: 1753710752703-0
data: {
  "event": "create",
  "resource_type": "events",
  "resource_id": "wXmBMUlxpL",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "name": {
      "from": null,
      "to": "skus.tagged"
    },
    "id": {
      "from": null,
      "to": 2422087
    },
    "created_at": {
      "from": null,
      "to": "2025-07-28T13:53:12.000Z"
    },
    "updated_at": {
      "from": null,
      "to": "2025-07-28T13:53:12.000Z"
    }
  },
  "ip_address": "93.45.228.116",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "uuid": "65bdc078600c4879c903c8252d4e03cca75b818ca2464fa9217b4f0e755b45d9",
  "test": true,
  "created_at": "2025-07-28T13:53:12.000Z",
  "updated_at": "2025-07-28T13:53:12.000Z",
  "who": {
    "application": {
      "id": "DMjvdiebqM",
      "client_id": "myApp-Cl13nt-IDr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "sCfwmSNRed",
      "type": "User",
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe"
    }
  }
}

<strong>event: heartbeat
</strong>id: 1753710752704-0
data: {
  "event": "heartbeat",
  "timestamp": "2025-07-28T13:53:22Z"
}

<strong>event: heartbeat
</strong>id: 1753710752705-0
data: {
  "event": "heartbeat",
  "timestamp": "2025-07-28T13:53:32Z"
}

...
        
</code></pre>

{% endtab %}
{% endtabs %}

## Event recovery and replay by resource

Along with the live stream, the Commerce Layer Stream Hub service offers an additional endpoint that queues a replay job to retrieve historical events:

```http
https://stream.commercelayer.io/{{your_domain}}/replay
```

This is useful for clients that were disconnected, are syncing a local store, or need to audit events over a given timeframe. The same endpoint can also be used to fetch the events related to a specific resource or to a set of specific instances of that resource.

{% hint style="warning" %}
The replay timeframe cannot exceed **7 days**.
{% endhint %}

The `/replay` endpoint accepts the desired timeframe, resource type, and optional resource IDs as query parameters:

<table><thead><tr><th width="166.921875">Query parameter</th><th width="106.6484375" data-type="checkbox">Required</th><th width="321.23046875">Description</th><th width="240.2890625">Example</th></tr></thead><tbody><tr><td><strong><code>date_from</code></strong></td><td>true</td><td>The <a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO8601</a> timestamp for the start of the replay window (YYYY-MM-DDTHH:MM:SSZ) — must be no more than 7 days before <code>date_to</code>, optional if you're passing <code>resource_id_in</code>.</td><td><code>2025-01-10T12:15:00Z</code></td></tr><tr><td><strong><code>date_to</code></strong></td><td>true</td><td>The <a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO8601</a> timestamp for the start of the replay window (YYYY-MM-DDTHH:MM:SSZ) — must be no more than 7 days after <code>date_from</code>, optional if you're passing <code>resource_id_in</code>.</td><td><code>2025-01-16T12:15:00Z</code></td></tr><tr><td><strong><code>resource_type_eq</code></strong></td><td>false</td><td>The type of resource for which you need to replay the event changes — required if you're passing <code>resource_id_in</code>.</td><td><code>skus</code></td></tr><tr><td><strong><code>resource_id_in</code></strong></td><td>false</td><td>A comma-separated list of IDs of the specified resource type (no space after the comma).</td><td><code>AYqPSwAqDW,WRfaDFdGeOK</code></td></tr></tbody></table>

The `/replay` endpoint also introduces two additional types of events to notify of the beginning and the completion of the replay stream:

<table><thead><tr><th width="229.7890625">Event type</th><th>Description</th></tr></thead><tbody><tr><td><strong><code>replay_started</code></strong></td><td>A replay stream has started.</td></tr><tr><td><strong><code>stream_complete</code></strong></td><td>A replay stream has been completed.</td></tr></tbody></table>

{% hint style="info" %}
Of course, being a replay, no heartbeat will show in the stream in this case.
{% endhint %}

### Examples

#### Replay by timeframe

{% tabs %}
{% tab title="Request" %}
The following request replays the events streamed within a specified time window:

```sh
curl -g -X GET \
  'https://stream.commercelayer.io/my-org/replay?date_from=2025-07-30T16:00:00Z&date_to=2025-07-31T16:30:00Z' \
  -H 'Authorization: Bearer your-access-token' 
```

{% endtab %}

{% tab title="Response" %}
On success, the API responds with a `200 OK` status code, returning the event stream related to the specified time window:

<pre><code><strong>event: replay_started
</strong>id: 1753973120642-0
data: {
  "event": "replay_started",
  "timestamp": "2025-07-31T14:30:00Z"
}

<strong>event: create
</strong>id: 1753973120739-0
data: {
  "id": "1753971708673-0",
  "event": "create",
  "resource_type": "transactions",
  "resource_id": "GbwPUnYXnj",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "number": {
      "from": null,
      "to": "2662594/T/002"
    },
    "type": {
      "from": null,
      "to": "Authorization"
    },
    "currency_code": {
      "from": null,
      "to": "EUR"
    },
    "amount_cents": {
      "from": null,
      "to": "9900.0"
    },
    "succeeded": {
      "from": null,
      "to": false
    },
    "message": {
      "from": null,
      "to": "Pending"
    },
    "token": {
      "from": null,
      "to": "pay_gplxkwz7lghurncpzx4fv6zxny"
    },
    "gateway_transaction_id": {
      "from": null,
      "to": "pay_gplxkwz7lghurncpzx4fv6zxny"
    },
    "id": {
      "from": null,
      "to": "KbwPUnYXaj"
    },
    "created_at": {
      "from": null,
      "to": "2025-07-31T14:21:48.628Z"
    },
    "updated_at": {
      "from": null,
      "to": "2025-07-31T14:21:48.628Z"
    },
    "order_id": {
      "from": null,
      "to": "qRKahzeREv"
    },
    "payment_source_id": {
      "from": null,
      "to": "MPnWZTeybl"
    },
    "payment_source_type": {
      "from": null,
      "to": "CheckoutComPayment"
    }
  },
  "who": {
    "application": {
      "id": "DNOvYirRpn",
      "client_id": "app_cLi3nT-IDFgefXpyTYabocYTOwAGmC3I1Npc",
      "kind": "sales_channel",
      "public": true
    },
    "owner": {
      "id": "QKmohgwbyn",
      "type": "Customer",
      "email": "mark@example.com"
    }
  },
  "uuid": "0725c0a24c721f6625479612415ecb084578ee535cdf46561f1a79a0485aa03c",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "83.67.219.209",
  "test": true,
<strong>  "created_at": "2025-07-31T14:21:48.000+00:00"
</strong>}

...

<strong>event: destroy
</strong>id: 1753973120745-0
data: {
  "id": "1753971693969-0",
  "event": "destroy",
  "resource_type": "line_items",
  "resource_id": "kAjVtPobbv",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "quantity": {
      "from": "1.0",
      "to": null
    },
    "unit_amount_cents": {
      "from": "0.0",
      "to": null
    },
    "compare_at_amount_cents": {
      "from": "0.0",
      "to": null
    },
    "options_amount_cents": {
      "from": "0.0",
      "to": null
    },
    "discount_cents": {
      "from": "0.0",
      "to": null
    },
    "name": {
      "from": "Adyen Payment",
      "to": null
    },
    "item_type": {
      "from": "PaymentMethod",
      "to": null
    },
    "id": {
      "from": "kAjVtPobbv",
      "to": null
    },
    "created_at": {
      "from": "2025-07-31T14:21:10.940Z",
      "to": null
    },
    "updated_at": {
      "from": "2025-07-31T14:21:10.940Z",
      "to": null
    },
    "metadata": {
      "from": {},
      "to": null
    },
    "order_id": {
      "from": "qRKahzeREv",
      "to": null
    },
    "discount_breakdown": {
      "from": {},
      "to": null
    },
    "tax_breakdown": {
      "from": {},
      "to": null
    },
    "rule_outcomes": {
      "from": [],
      "to": null
    }
  },
  "who": {
    "application": {
      "id": "DNOvYirRpn",
      "client_id": "app_cLi3nT-IDFgefXpyTYabocYTOwAGmC3I1Npc",
      "kind": "sales_channel",
      "public": true
    },
    "owner": {
      "id": "QKmohgwbyn",
      "type": "Customer",
      "email": "mark@example.com"
    }
  },
  "uuid": "0725c0a24c721f6625479612415ecb084578ee535cdf46561f1a79a0485aa03c",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "83.67.219.209",
  "test": true,
<strong>  "created_at": "2025-07-31T14:21:10.000+00:00"
</strong>}

...

<strong>event: update
</strong>id: 1753973120763-0
data: {
  "id": "1753971672060-0",
  "event": "update",
  "resource_type": "orders",
  "resource_id": "qSKahzeREv",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "updated_at": {
      "from": "2025-07-31T14:21:10.944Z",
      "to": "2025-07-31T14:21:12.044Z"
    },
    "payment_source_id": {
      "from": null,
      "to": "KZBkghKqkm"
    },
    "payment_source_type": {
      "from": null,
      "to": "AdyenPayment"
    }
  },
  "who": {
    "application": {
      "id": "DNOvYirRpn",
      "client_id": "app_cLi3nT-IDFgefXpyTYabocYTOwAGmC3I1Npc",
      "kind": "sales_channel",
      "public": true
    },
    "owner": {
      "id": "QKmohgwbyn",
      "type": "Customer",
      "email": "mark@example.com"
    }
  },
  "uuid": "0725c0a24c721f6625479612415ecb084578ee535cdf46561f1a79a0485aa03c",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "83.67.219.209",
  "test": true,
<strong>  "created_at": "2025-07-31T14:21:12.000+00:00"
</strong>}

...

<strong>event: stream_complete
</strong>data: {
  "event": "stream_complete",
  "message": "Replay stream completed successfully",
  "timestamp": "2025-07-31T14:30:03Z"
}     
</code></pre>

{% endtab %}
{% endtabs %}

#### Replay by resource type

{% tabs %}
{% tab title="Request" %}
The following request replays only the events related to SKUs, streamed within a specified time window:

```sh
curl -g -X GET \
  'https://stream.commercelayer.io/my-org/replay?date_from=2025-07-30T15:15:00Z&date_to=2025-07-31T16:30:00Z&resource_type_eq=skus' \
  -H 'Authorization: Bearer your-access-token' 
```

{% endtab %}

{% tab title="Response" %}
On success, the API responds with a `200 OK` status code, returning the event stream related to the specified time window and resource type:

<pre><code><strong>event: replay_started
</strong>id: 1753977869951-0
data: {
  "event": "replay_started",
  "timestamp": "2025-07-31T14:30:00Z"
}

<strong>event: create
</strong>id: 1753977870001-0
{
  "id": "1753977666209-0",
  "event": "create",
<strong>  "resource_type": "skus",
</strong>  "resource_id": "BfvMSwEyJW",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "code": {
      "from": null,
      "to": "NEWCARPETXXX"
    },
    "name": {
      "from": null,
      "to": "New Carpet"
    },
    "description": {
      "from": null,
      "to": "Wonderful carpet: 260x180cm."
    },
    "id": {
      "from": null,
      "to": "BgvMSwEyJW"
    },
    "created_at": {
      "from": null,
      "to": "2025-07-31T16:01:06.160Z"
    },
    "updated_at": {
      "from": null,
      "to": "2025-07-31T16:01:06.160Z"
    },
    "shipping_category_id": {
      "from": null,
      "to": "gKkerFnawZ"
    },
    "pieces_per_pack": {
      "from": null,
      "to": "1.0"
    },
    "weight": {
      "from": null,
      "to": "2000.0"
    },
    "unit_of_weight": {
      "from": null,
      "to": "gr"
    }
  },
  "who": {
    "application": {
      "id": "FMjvdiebqM",
      "client_id": "CappID-cl1ent-26Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "gEmwmSNRed",
      "type": "User",
      "email": "jack@example.com",
      "first_name": "Jack",
      "last_name": "Doe"
    }
  },
  "uuid": "e8a069b6e5a2619e350357ea5bf32678b91bdca683709fb4e0c9edc737fbcfed",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.87.228.116",
  "test": true,
<strong>  "created_at": "2025-07-31T16:01:06.000+00:00"
</strong>}

<strong>event: create
</strong>id: 1753977870003-0
data: {
  "id": "1753975304905-0",
  "event": "create",
<strong>  "resource_type": "skus",
</strong>  "resource_id": "nQrOSKprmZ",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "code": {
      "from": null,
      "to": "NEWCAPXXX"
    },
    "name": {
      "from": null,
      "to": "New Cap"
    },
    "description": {
      "from": null,
      "to": "A brand new cap."
    },
    "id": {
      "from": null,
      "to": "nQrOSKprmZ"
    },
    "created_at": {
      "from": null,
      "to": "2025-07-31T15:21:44.883Z"
    },
    "updated_at": {
      "from": null,
      "to": "2025-07-31T15:21:44.883Z"
    },
    "shipping_category_id": {
      "from": null,
      "to": "VNoxGFBywb"
    },
    "pieces_per_pack": {
      "from": null,
      "to": "1.0"
    },
    "weight": {
      "from": null,
      "to": "100.0"
    },
    "unit_of_weight": {
      "from": null,
      "to": "gr"
    }
  },
  "who": {
    "application": {
      "id": "FMjvdiebqM",
      "client_id": "CappID-cl1ent-26Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "gEmwmSNRed",
      "type": "User",
      "email": "jack@example.com",
      "first_name": "Jack",
      "last_name": "Doe"
    }
  },
  "uuid": "e8a069b6e5a2619e350357ea5bf32678b91bdca683709fb4e0c9edc737fbcfed",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.87.228.116",
  "test": true,
<strong>  "created_at": "2025-07-31T15:21:44.000+00:00"
</strong>}

<strong>event: update
</strong>id: 1753977869996-0
data: {
  "id": "1753975080985-0",
  "event": "update",
<strong>  "resource_type": "skus",
</strong>  "resource_id": "WJoqSjzGjB",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "name": {
      "from": "Batman Coffee Mug",
      "to": "Batman Mug"
    },
    "description": {
      "from": "Batman branded mug. Ideal for coffee.",
      "to": "Batman branded mug."
    },
    "updated_at": {
      "from": "2025-07-31T13:58:58.798Z",
      "to": "2025-07-31T15:18:00.950Z"
    },
    "weight": {
      "from": "400.0",
      "to": "300.0"
    }
  },
  "who": {
    "application": {
      "id": "DMjvdiebqM",
      "client_id": "app-ID-Cl1ent-oIc326Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "pthwmSNSed",
      "type": "User",
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe"
    }
  },
  "uuid": "31acbaf6f6c36552b0bab4dd683b02e9ab3a028bd14330f9b9dc0d1190763aab",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.43.228.116",
  "test": true,
<strong>  "created_at": "2025-07-31T15:18:00.000+00:00"
</strong>}

<strong>event: update
</strong>id: 1753977869997-0
data: {
  "id": "1753975114234-0",
  "event": "update",
<strong>  "resource_type": "skus",
</strong>  "resource_id": "WJoqSjzGjB",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "description": {
      "from": "Batman branded mug.",
      "to": "Batman branded mug. Top seller!"
    },
    "updated_at": {
      "from": "2025-07-31T15:18:00.950Z",
      "to": "2025-07-31T15:18:34.201Z"
    }
  },
  "who": {
    "application": {
      "id": "DMjvdiebqM",
      "client_id": "app-ID-Cl1ent-oIc326Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "pthwmSNSed",
      "type": "User",
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe"
    }
  },
  "uuid": "31acbaf6f6c36552b0bab4dd683b02e9ab3a028bd14330f9b9dc0d1190763aab",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.43.228.116",
  "test": true,
<strong>  "created_at": "2025-07-31T15:18:34.000+00:00"
</strong>}

<strong>event: destroy
</strong>id: 1753977869999-0
data: {
  "id": "1753977604269-0",
  "event": "destroy",
<strong>  "resource_type": "skus",
</strong>  "resource_id": "nQrOSKprmZ",
  "organization_id": "XMlEOFrjdf",
  "payload": {
    "code": {
      "from": "NEWCAPXXX",
      "to": null
    },
    "name": {
      "from": "New Cap",
      "to": null
    },
    "description": {
      "from": "A brand new cap.",
      "to": null
    },
    "do_not_ship": {
      "from": false,
      "to": null
    },
      "do_not_track": {
      "from": false,
      "to": null
    },
    "id": {
      "from": "nQrOSKprmZ",
      "to": null
    },
    "created_at": {
      "from": "2025-07-31T15:21:44.883Z",
      "to": null
    },
    "updated_at": {
      "from": "2025-07-31T15:21:44.883Z",
      "to": null
    },
    "metadata": {
      "from": {},
      "to": null
    },
    "shipping_category_id": {
      "from": "VNoxGFBywb",
      "to": null
    },
    "pieces_per_pack": {
      "from": "1.0",
      "to": null
    },
    "weight": {
      "from": "100.0",
      "to": null
    },
    "unit_of_weight": {
      "from": "gr",
      "to": null
    }
  },
  "who": {
    "application": {
      "id": "FMjvdiebqM",
      "client_id": "CappID-cl1ent-26Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "gEmwmSNRed",
      "type": "User",
      "email": "jack@example.com",
      "first_name": "Jack",
      "last_name": "Doe"
    }
  },
  "uuid": "e8a069b6e5a2619e350357ea5bf32678b91bdca683709fb4e0c9edc737fbcfed",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.87.228.116",
  "test": true,
<strong>  "created_at": "2025-07-31T15:15:44.000+00:00"
</strong>}

...

<strong>event: stream_complete
</strong>data: {
  "event": "stream_complete",
  "message": "Replay stream completed successfully",
  "timestamp": "2025-07-31T14:30:03Z"
}     
</code></pre>

{% endtab %}
{% endtabs %}

#### Replay by resource IDs

{% tabs %}
{% tab title="Request" %}
The following request replays only the events related to the SKUs identified by the IDs `nQrOSKprmZ` and `WJoqSjzGjB` with no time window restriction:

```sh
curl -g -X GET \
  'https://stream.commercelayer.io/my-org/replay?resource_type_eq=skus&resource_id_in=nQrOSKprmZ,WJoqSjzGjB' \
  -H 'Authorization: Bearer your-access-token' 
```

{% endtab %}

{% tab title="Response" %}
On success, the API responds with a `200 OK` status code, returning the event stream related to the specified resource type and IDs:

<pre><code><strong>event: replay_started
</strong>id: 1753977869951-0
data: {
  "event": "replay_started",
  "timestamp": "2025-07-31T14:30:00Z"
}

<strong>event: create
</strong>id: 1753977870003-0
data: {
  "id": "1753975304905-0",
  "event": "create",
<strong>  "resource_type": "skus",
</strong><strong>  "resource_id": "nQrOSKprmZ",
</strong>  "organization_id": "XMlEOFrjdf",
  "payload": {
    "code": {
      "from": null,
      "to": "NEWCAPXXX"
    },
    "name": {
      "from": null,
      "to": "New Cap"
    },
    "description": {
      "from": null,
      "to": "A brand new cap."
    },
    "id": {
      "from": null,
      "to": "nQrOSKprmZ"
    },
    "created_at": {
      "from": null,
      "to": "2025-07-31T15:21:44.883Z"
    },
    "updated_at": {
      "from": null,
      "to": "2025-07-31T15:21:44.883Z"
    },
    "shipping_category_id": {
      "from": null,
      "to": "VNoxGFBywb"
    },
    "pieces_per_pack": {
      "from": null,
      "to": "1.0"
    },
    "weight": {
      "from": null,
      "to": "100.0"
    },
    "unit_of_weight": {
      "from": null,
      "to": "gr"
    }
  },
  "who": {
    "application": {
      "id": "FMjvdiebqM",
      "client_id": "CappID-cl1ent-26Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "gEmwmSNRed",
      "type": "User",
      "email": "jack@example.com",
      "first_name": "Jack",
      "last_name": "Doe"
    }
  },
  "uuid": "e8a069b6e5a2619e350357ea5bf32678b91bdca683709fb4e0c9edc737fbcfed",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.87.228.116",
  "test": true,
  "created_at": "2025-07-31T15:21:44.000+00:00"
}

<strong>event: update
</strong>id: 1753977869996-0
data: {
  "id": "1753975080985-0",
  "event": "update",
<strong>  "resource_type": "skus",
</strong><strong>  "resource_id": "WJoqSjzGjB",
</strong>  "organization_id": "XMlEOFrjdf",
  "payload": {
    "name": {
      "from": "Batman Coffee Mug",
      "to": "Batman Mug"
    },
    "description": {
      "from": "Batman branded mug. Ideal for coffee.",
      "to": "Batman branded mug."
    },
    "updated_at": {
      "from": "2025-07-31T13:58:58.798Z",
      "to": "2025-07-31T15:18:00.950Z"
    },
    "weight": {
      "from": "400.0",
      "to": "300.0"
    }
  },
  "who": {
    "application": {
      "id": "DMjvdiebqM",
      "client_id": "app-ID-Cl1ent-oIc326Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "pthwmSNSed",
      "type": "User",
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe"
    }
  },
  "uuid": "31acbaf6f6c36552b0bab4dd683b02e9ab3a028bd14330f9b9dc0d1190763aab",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.43.228.116",
  "test": true,
  "created_at": "2025-07-31T15:18:00.000+00:00"
}

<strong>event: update
</strong>id: 1753977869997-0
data: {
  "id": "1753975114234-0",
  "event": "update",
<strong>  "resource_type": "skus",
</strong><strong>  "resource_id": "WJoqSjzGjB",
</strong>  "organization_id": "XMlEOFrjdf",
  "payload": {
    "description": {
      "from": "Batman branded mug.",
      "to": "Batman branded mug. Top seller!"
    },
    "updated_at": {
      "from": "2025-07-31T15:18:00.950Z",
      "to": "2025-07-31T15:18:34.201Z"
    }
  },
  "who": {
    "application": {
      "id": "DMjvdiebqM",
      "client_id": "app-ID-Cl1ent-oIc326Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "pthwmSNSed",
      "type": "User",
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe"
    }
  },
  "uuid": "31acbaf6f6c36552b0bab4dd683b02e9ab3a028bd14330f9b9dc0d1190763aab",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.43.228.116",
  "test": true,
  "created_at": "2025-07-31T15:18:34.000+00:00"
}

<strong>event: destroy
</strong>id: 1753977869999-0
data: {
  "id": "1753977604269-0",
  "event": "destroy",
<strong>  "resource_type": "skus",
</strong><strong>  "resource_id": "nQrOSKprmZ",
</strong>  "organization_id": "XMlEOFrjdf",
  "payload": {
    "code": {
      "from": "NEWCAPXXX",
      "to": null
    },
    "name": {
      "from": "New Cap",
      "to": null
    },
    "description": {
      "from": "A brand new cap.",
      "to": null
    },
    "do_not_ship": {
      "from": false,
      "to": null
    },
      "do_not_track": {
      "from": false,
      "to": null
    },
    "id": {
      "from": "nQrOSKprmZ",
      "to": null
    },
    "created_at": {
      "from": "2025-07-31T15:21:44.883Z",
      "to": null
    },
    "updated_at": {
      "from": "2025-07-31T15:21:44.883Z",
      "to": null
    },
    "metadata": {
      "from": {},
      "to": null
    },
    "shipping_category_id": {
      "from": "VNoxGFBywb",
      "to": null
    },
    "pieces_per_pack": {
      "from": "1.0",
      "to": null
    },
    "weight": {
      "from": "100.0",
      "to": null
    },
    "unit_of_weight": {
      "from": "gr",
      "to": null
    }
  },
  "who": {
    "application": {
      "id": "FMjvdiebqM",
      "client_id": "CappID-cl1ent-26Ugu6zl4kr-KOwFhtKMvQIvj-KZY",
      "kind": "skus",
      "public": false
    },
    "owner": {
      "id": "gEmwmSNRed",
      "type": "User",
      "email": "jack@example.com",
      "first_name": "Jack",
      "last_name": "Doe"
    }
  },
  "uuid": "e8a069b6e5a2619e350357ea5bf32678b91bdca683709fb4e0c9edc737fbcfed",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "ip_address": "93.87.228.116",
  "test": true,
  "created_at": "2025-07-31T15:15:44.000+00:00"
}

...

<strong>event: stream_complete
</strong>data: {
  "event": "stream_complete",
  "message": "Replay stream completed successfully",
  "timestamp": "2025-07-31T14:30:03Z"
}     
</code></pre>

{% endtab %}
{% endtabs %}

## Response codes

The Commerce Layer Stream Hub uses [HTTP response codes](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) to show the success or failure of a [request to connect](#connecting-to-the-event-stream) to the event stream.

### Success

In case of successful connection, the API responds with a `200 OK` status code and starts streaming data according to the SSE format.

### Error

In case of error, a descriptive error message is returned along with the related error code:

<table><thead><tr><th width="87.01171875">Code</th><th width="218.60546875"></th><th>Description</th></tr></thead><tbody><tr><td><strong><code>400</code></strong></td><td><code>Bad request</code></td><td>The date format is invalid or the date range validation failed.</td></tr><tr><td><strong><code>401</code></strong></td><td><code>Unauthorized</code></td><td>The JWT token is invalid (expired, not associated with integration API credentials, etc.) or missing.</td></tr><tr><td><strong><code>403</code></strong></td><td><code>Forbidden</code></td><td>An organization slug mismatch or validation error occurred.</td></tr><tr><td><strong><code>409</code></strong></td><td><code>Conflict</code></td><td>An active consumer already exists (you can kill the stream and retry in 5 secs).</td></tr><tr><td><strong><code>500</code></strong></td><td><code>Internal server error</code></td><td>Something went wrong and the stream hub failed to queue the replay job.</td></tr></tbody></table>

## How to enable the stream hub

Enterprise customers who want to leverage the power of our event stream hub must activate it at the organization level by environment. This can be done:

* [Directly from the Dashboard](#stream-settings)
* [Using the Provisioning API](#organization-config)

### Stream settings

To enable the event stream hub from the Dashboard UI, click on the *Settings* menu item of the left sidebar and access the *General > Organization* section:

<figure><img src="https://1360111082-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgByaSP8eKjad-MIuHE%2Fuploads%2FwTb43E0WPAwHOcMkT29h%2Forganization-settings.jpg?alt=media&#x26;token=1ac78820-cce1-4138-82c0-7f152d78e8b8" alt=""><figcaption></figcaption></figure>

Then select the stream scope from the dropdown menu and click *Update*:

<figure><img src="https://1360111082-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgByaSP8eKjad-MIuHE%2Fuploads%2FPUug0W9mF0KoHJVmekj5%2Fstream-settings.jpg?alt=media&#x26;token=1f2dbd97-4860-4aab-812a-eda61ae6df9e" alt=""><figcaption></figcaption></figure>

### Organization config

To enable the event stream hub via API, patch the [organizations](https://app.gitbook.com/s/xrdVVavnnBMHRCqrLp1y/api-reference/organizations) endpoint and pass the `api.stream` object within the `config` attribute, setting the stream `scope` (can be one of `none`, `live`, `test`, or `both`):

<pre class="language-json" data-title="organizations.config"><code class="lang-json">{
  "api": {
    "stream": {
<strong>      "scope": "live"
</strong>    }
  }
}
</code></pre>
