> ## Documentation Index
> Fetch the complete documentation index at: https://developer.jtl-software.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Product Sync

> Synchronize product and offer listings between JTL and marketplace channels via the Channel API

This guide covers how product and offer listings flow from JTL-Wawi to your channel, how to report listing status back to sellers, and how to keep stock levels synchronized.

## Listing Sync Flow

Listings are transmitted by the `Seller:Offer.New` and `Seller:Offer.Update` events.
Each time listing data changes, JTL-Wawi transmits the entire listing again.

```mermaid theme={null}
sequenceDiagram
    participant Seller as Seller (JTL-Wawi)
    participant SCX as SCX Platform
    participant Channel as Channel Integration
    participant MP as Marketplace

    Seller->>SCX: Creates/updates listing
    SCX->>SCX: Emits Seller:Offer.New or Seller:Offer.Update event

    Channel->>SCX: GET /v1/channel/event
    SCX-->>Channel: Returns offer event with full listing data
    Channel->>SCX: DELETE /v1/channel/event (acknowledge)

    Channel->>MP: Submit listing to marketplace

    alt Listing accepted
        MP-->>Channel: Listing live
        Channel->>SCX: POST /v1/channel/offer/listed
    else Listing rejected
        MP-->>Channel: Validation error
        Channel->>SCX: POST /v1/channel/offer/listing-failed
    end
```

## Essential Properties

It is generally not necessary to provide attributes for essential data, as each listing already implements a set of
essential properties by default, including title, description, GTIN, quantity, and price.

## Pictures and Images

Product or listing images are transmitted as a link along with the listing event.

<Warning>
  Image links have a lifetime of **7 days** after the listing event was triggered. Make sure to download and store images
  if you need them beyond that period.
</Warning>

The filename is generated based on the file content, so each separate image will have a unique filename derived from its content.

## Listing State

We recommend informing the seller about the processing status of their listings. Most marketplaces use an
asynchronous listing process during which the listing data is curated in a semi-automated process that may take some time.

```mermaid theme={null}
stateDiagram-v2
    [*] --> InProgress: Offer event received
    InProgress --> Listed: Listing successful
    InProgress --> Failed: Listing rejected
    Failed --> InProgress: Seller resubmits offer
    Listed --> InProgress: Seller updates offer
```

The three states are reported through their own endpoints.

<Tabs>
  <Tab title="In-Progress">
    Send this state to inform the seller that the listing process is now in progress:

    ```json theme={null}
    // POST /v1/channel/offer/in-progress
    {
      "offerList": [
        {
          "offerId": 1,
          "sellerId": "1",
          "startedAt": "2022-11-28T01:00:13+00"
        }
      ]
    }
    ```
  </Tab>

  <Tab title="Successful">
    Inform the seller once a listing is successfully listed on the connected marketplace.
    The optional `listingUrl` allows the seller to visit and directly check the listing.

    ```json theme={null}
    // POST /v1/channel/offer/listed
    {
      "offerList": [
        {
          "sellerId": "1",
          "offerId": 1,
          "listedAt": "2022-11-28T01:00:13+00",
          "listingUrl": "https://marketplace.de/offer1",
          "channelOfferId": "AFGHDHDFH"
        }
      ]
    }
    ```
  </Tab>

  <Tab title="Failed">
    You need to inform the seller if the listing process for a listing failed:

    ```json theme={null}
    // POST /v1/channel/offer/listing-failed
    {
      "offerList": [
        {
          "sellerId": "1",
          "offerId": 1,
          "errorList": [
            {
              "code": "123",
              "message": "A listing error occurred",
              "longMessage": "A serious listing error occurred."
            }
          ],
          "failedAt": "2019-02-09T05:33:12+00:00"
        }
      ]
    }
    ```
  </Tab>
</Tabs>

## Stock Updates

The Stock Updates API enables channels to keep their inventory synchronized with seller stock levels.

### Available Methods

There are multiple ways to synchronize stock:

| Method          | Endpoint                                  | Use Case                                                   |
| --------------- | ----------------------------------------- | ---------------------------------------------------------- |
| **Per-seller**  | `GET /v1/channel/offer/stock-updates`     | Parallel per-seller processing. Higher rate limit.         |
| **All sellers** | `GET /v1/channel/offer/stock-updates/all` | Get stock changes for all active sellers in a single call. |
| **Event-based** | `Seller:Offer.StockUpdate` event          | Consuming the seller event directly.                       |

<Warning>
  Use the stock update endpoints rather than the `Seller:Offer.StockUpdate` event. The event remains available, but the
  dedicated endpoints are the supported path for stock synchronization.
</Warning>

### Example Request and Response

The following request retrieves stock changes for all active sellers since a given timestamp.

```json theme={null}
// GET /v1/channel/offer/stock-updates/all?updatedAfter=2025-12-29T00:00:00+00:00
{
  "stockUpdateList": [
    {
      "channel": "MYCHANNEL",
      "sellerId": "SELLER001",
      "offerId": 4711,
      "channelOfferId": "SKU-WIDGET-001",
      "quantity": 25,
      "updatedAt": "2025-12-29T10:15:30+00:00"
    },
    {
      "channel": "MYCHANNEL",
      "sellerId": "SELLER002",
      "offerId": 8822,
      "channelOfferId": "SKU-GADGET-042",
      "quantity": 0,
      "updatedAt": "2025-12-29T11:22:45+00:00"
    }
  ],
  "lastUpdatedAt": "2025-12-29T11:22:45+00:00"
}
```

### Incremental Sync Pattern

Use the `lastUpdatedAt` cursor from each response to fetch only the changes since your last call.

<Tip>
  For efficient synchronization, use the `lastUpdatedAt` value from the response as the `updatedAfter` parameter in your next request.
</Tip>

```mermaid theme={null}
sequenceDiagram
    participant Channel as Channel Integration
    participant SCX as SCX Platform

    Channel->>SCX: GET /stock-updates/all?updatedAfter=2025-12-01T00:00:00Z
    SCX-->>Channel: stockUpdateList + lastUpdatedAt=2025-12-29T11:22:45Z

    Note over Channel: Wait for next sync interval

    Channel->>SCX: GET /stock-updates/all?updatedAfter=2025-12-29T11:22:45Z
    SCX-->>Channel: stockUpdateList + lastUpdatedAt=2025-12-29T14:30:00Z

    Note over Channel: Continue with cursor-based polling...
```

```text theme={null}
1. First call:    GET /v1/channel/offer/stock-updates/all?updatedAfter=2025-12-01T00:00:00Z
   Response:      lastUpdatedAt = "2025-12-29T11:22:45+00:00"

2. Next call:     GET /v1/channel/offer/stock-updates/all?updatedAfter=2025-12-29T11:22:45+00:00
   Response:      lastUpdatedAt = "2025-12-29T14:30:00+00:00"

3. Continue...
```

***

## What's Next?

<CardGroup cols={2}>
  <Card title="Order Management" icon="box" href="/guides/marketplace-channels/order-management">
    Handle orders, cancellations, returns, and refunds.
  </Card>

  <Card title="Channel API Overview" icon="store" href="/guides/marketplace-channels/channel-api-overview">
    Review events, metadata, and media content handling.
  </Card>

  <Card title="Seller Management" icon="workflow" href="/guides/marketplace-channels/seller-management">
    Seller sign-up, update, and unlink flows.
  </Card>

  <Card title="Rate Limits" icon="gauge" href="/guides/marketplace-channels/rate-limits">
    Per-endpoint quotas and 429 handling.
  </Card>

  <Card title="Channel API Reference" icon="code" href="/api-reference/scx/channel">
    Endpoint-level reference for the Channel API.
  </Card>

  <Card title="Postman Collection" icon="rocket" href="https://www.postman.com/jtl-eazyauction/workspace/jtl-scx-public">
    Try the API with ready-made requests.
  </Card>
</CardGroup>
