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

# Webhooks & Events

> How event systems work on the JTL platform: AppBridge events, lifecycle hooks, and SCX polling events.

The JTL platform has three different event systems depending on what you're building and what kind of events you need to handle. This guide explains each one, how they differ, and when to use which.

## Event Systems at a Glance

| System               | Model                           | Used by              | Use when                                                                                                                   |
| -------------------- | ------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **AppBridge Events** | Real-time, bidirectional (push) | Cloud Apps           | Communication between your app and the JTL App Shell like reacting to user actions and notifying the host of state changes |
| **Lifecycle Hooks**  | iframe handshake                | Cloud Apps           | App installation: onboarding UI and the setup handshake                                                                    |
| **SCX Events**       | Polling (pull)                  | Marketplace Channels | Consuming seller actions: new offers, order updates, attribute changes                                                     |

```mermaid theme={null}
flowchart LR
    subgraph EventSystems["JTL Event Systems"]
        direction TB

        subgraph AB["AppBridge Events"]
            ABDesc["Real-time, bidirectional"]
        end

        subgraph LH["Lifecycle Hooks"]
            LHDesc["Iframe handshake on install"]
        end

        subgraph SCX["SCX Events"]
            SCXDesc["Polling-based"]
        end
    end

    YourApp["Your App"] <-->|"publish / subscribe (iframe postMessage)"| Shell["App Shell"]
    Platform["JTL Platform"] -->|"loads configurationUrl in an iframe"| YourBackend["Your App"]
    YourChannel["Your Channel"] -->|"GET then DELETE /v1/channel/event"| SCXAPI["SCX API"]

    AB ~~~ YourApp
    LH ~~~ Platform
    SCX ~~~ YourChannel

    style AB fill:#FFF2EB,stroke:#FB581F,stroke-width:2px,color:#0B1B45
    style LH fill:#FFF2EB,stroke:#FB581F,stroke-width:2px,color:#0B1B45
    style SCX fill:#E8F4FF,stroke:#89D2FF,stroke-width:2px,color:#0B1B45
    style Shell fill:#EEEEE7,stroke:#0B1B45,stroke-width:2px,color:#0B1B45
    style Platform fill:#EEEEE7,stroke:#0B1B45,stroke-width:2px,color:#0B1B45
    style SCXAPI fill:#E8F4FF,stroke:#89D2FF,stroke-width:2px,color:#0B1B45
    style YourApp fill:#fff,stroke:#0B1B45,stroke-width:1px,color:#0B1B45
    style YourBackend fill:#fff,stroke:#0B1B45,stroke-width:1px,color:#0B1B45
    style YourChannel fill:#fff,stroke:#0B1B45,stroke-width:1px,color:#0B1B45
```

## AppBridge Events

<Info>
  **In development:** AppBridge publish/subscribe events are in development and not yet available. This section will be updated when the API ships.
</Info>

**What they will be:** Real-time, bidirectional events between your Cloud App and the App Shell. Your app can both **publish** events (tell the host something happened) and **subscribe** to events (react when the host tells you something happened).

**How they will work:** AppBridge events use the iframe messaging channel. When your app publishes an event, the App Shell receives it instantly. When the App Shell publishes an event, your app's subscriber callback fires immediately. Communication is asynchronous and non-blocking, so your app continues executing while the message is delivered (no HTTP request, polling, or delay).

**When to use them (planned):**

* Notifying the JTL App Shell that your app completed an action (e.g. order verification finished)
* Reacting to user navigation or context changes in the JTL-Wawi
* Coordinating between your app and other platform components

### Publish and Subscribe

AppBridge events will support two capabilities:

* **Publishing events**: your app notifies the host that something happened (for example, a verification step completed or a generated description is ready to insert).
* **Subscribing to events**: your app listens for events from the host and reacts when context changes (for example, the merchant navigates to a different record).

Topics will follow a `resource:action` naming convention (for example, `order:verification:complete` or `inventory:updated`) so the intent of an event is clear from its name alone.

### Key Characteristics

| Property         | Value                                                                |
| ---------------- | -------------------------------------------------------------------- |
| **Direction**    | Bidirectional: your app ↔ App Shell                                  |
| **Delivery**     | Instant (through the iframe)                                         |
| **Scope**        | Only within the current user session. Events don't persist or queue. |
| **Availability** | Cloud Apps running inside the App Shell only                         |

## Lifecycle Hooks

**What they are:** A URL defined in your app's `manifest.json` that JTL loads in an iframe when a merchant installs your app.

**How they work:** You define a `configurationUrl` in the `lifecycle` section of your manifest. When a merchant installs your app, JTL loads that URL inside the JTL Hub. Your app shows its onboarding UI, completes the AppBridge handshake, and signals setup is done by calling `appBridge.method.call('setupCompleted')`.

**When to use it:**

* Showing onboarding UI when a merchant installs your app
* Verifying the session token from AppBridge and persisting the tenant connection
* Collecting any configuration the merchant needs to provide

### Manifest Configuration

The lifecycle hook is defined in your `manifest.json`:

```json theme={null}
{
  "lifecycle": {
    "configurationUrl": "https://app.yourcompany.com/setup"
  }
}
```

| Hook               | When it's triggered                 | What to do                                                                                                                                                                                      |
| ------------------ | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `configurationUrl` | Merchant initiates app installation | Display a setup screen inside the App Shell. Verify the session token from AppBridge, persist the tenant connection, and complete the handshake with `appBridge.method.call('setupCompleted')`. |

### Key Characteristics

| Property         | Value                                         |
| ---------------- | --------------------------------------------- |
| **Direction**    | One-way — JTL Hub loads your URL in an iframe |
| **Delivery**     | Iframe render in the merchant's browser       |
| **Scope**        | Per-tenant onboarding                         |
| **Availability** | Cloud Apps with a registered manifest         |

<Warning>
  The `configurationUrl` is the most important lifecycle hook. It's the entry point for the merchant's first interaction with your app. If this URL is unreachable when a merchant tries to install your app, the installation fails. Make sure it's always available.
</Warning>

For implementation details, see the [Quick Start: From Scratch](/get-started/quick-start/from-scratch) guide, which walks through the full setup handshake.

## SCX Events (Polling)

**What they are:** An event queue for marketplace channel integrations. When sellers (merchants using JTL) take actions like creating a new product offer, updating prices, or shipping an order, those actions are queued as events. Your channel integration polls the queue, processes the events, and acknowledges them.

**How they work:** This is a **pull-based** system, not push-based. JTL doesn't send events to your server. Instead, your app periodically calls `GET /v1/channel/event` to check for new events, processes them, and then calls `DELETE /v1/channel/event` to acknowledge them. Unacknowledged events are redelivered.

**When to use them:**

* Processing new product listings from sellers
* Handling order status updates (paid, shipped, cancelled)
* Syncing attribute and category changes

### Poll → Process → Acknowledge

```mermaid theme={null}
sequenceDiagram
  autonumber
 
  participant App as Your Channel App
  participant SCX as SCX Channel API
 
  loop Every ~60 seconds
    App->>SCX: GET /v1/channel/event
    SCX-->>App: eventList (0 or more events)
 
    alt Events received
      App->>App: Process each event
      App->>SCX: DELETE /v1/channel/event (eventIdList)
      SCX-->>App: Acknowledged
    end
  end
```

1. **Poll**: Your app calls `GET /v1/channel/event` at regular intervals (recommended: every 60 seconds)
2. **Process**: Handle each event based on its `type` (new offer, order update, attribute change, etc.)
3. **Acknowledge**: Call `DELETE /v1/channel/event` with the IDs of events you've successfully processed

### Event Structure

Each event in the `eventList` has this shape:

```json theme={null}
{
  "id": "63623b997d2c89a4e3e9f3c7",
  "type": "Seller:Offer.New",
  "createdAt": "2022-11-02T14:38:53+00:00",
  "event": {
    "sellerId": "1",
    "offerId": 822,
    "sku": "843609",
    "title": "Fahrrad Halterung",
    "quantity": "0",
    "taxPercent": "19",
    "priceList": [ ... ],
    "channelAttributeList": [ ... ]
  }
}
```

| Field       | Description                                                                           |
| ----------- | ------------------------------------------------------------------------------------- |
| `id`        | Unique event identifier — use this for acknowledgement                                |
| `type`      | The event type (e.g. `Seller:Offer.New`, `Seller:Meta.SellerAttributesUpdateRequest`) |
| `createdAt` | When the event was created (ISO 8601)                                                 |
| `event`     | The event payload that varies by event type                                           |

### Acknowledging Events

After processing, acknowledge events by sending their IDs:

```json theme={null}
// DELETE /v1/channel/event
{
  "eventIdList": [
    "63623b997d2c89a4e3e9f3c7",
    "636280fd65a66c4430ec0d67"
  ]
}
```

<Warning>
  **Always acknowledge events after successful processing.** If you don't acknowledge an event, it will be redelivered after a timeout — up to **10 times**. After 10 delivery attempts, the event becomes a **failed event** and is permanently discarded.
</Warning>

### Key Characteristics

| Property         | Value                                                                                       |
| ---------------- | ------------------------------------------------------------------------------------------- |
| **Direction**    | Pull: your app polls the SCX API                                                            |
| **Delivery**     | Queued. Events wait until your app fetches them.                                            |
| **Reliability**  | Guaranteed delivery (up to 10 retries). Events persist until acknowledged or dead-lettered. |
| **Ordering**     | Events are returned in creation order                                                       |
| **Scope**        | Seller events for your connected channel                                                    |
| **Availability** | SCX Channel API (Marketplace Channels only)                                                 |

### Best Practices for SCX Event Polling

| Practice                                  | Why                                                                                                                                   |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Poll every \~60 seconds**               | Balances responsiveness with rate limit usage                                                                                         |
| **Acknowledge in batches**                | Send all processed event IDs in a single DELETE call, not one per event                                                               |
| **Process idempotently**                  | Events can be redelivered if acknowledgement fails. Design handlers that produce the same result if called twice with the same event. |
| **Handle unknown event types gracefully** | New event types may be added. Log and acknowledge events your app doesn't recognise rather than failing.                              |
| **Monitor for dead letters**              | If events are dead-lettering, your processing pipeline has a problem that needs investigation.                                        |

## Choosing the Right Event System

| I'm building...       | I need to...                                        | Use                  |
| --------------------- | --------------------------------------------------- | -------------------- |
| A Cloud App           | React to user actions in real time                  | **AppBridge Events** |
| A Cloud App           | Handle app install onboarding                       | **Lifecycle Hooks**  |
| A Marketplace Channel | Process seller actions (offers, orders, attributes) | **SCX Events**       |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Cloud Apps: Handling Webhooks" icon="bell" href="/guides/cloud-apps/handling-webhooks">
    Implementation guide for AppBridge events and lifecycle hooks in Cloud Apps.
  </Card>

  <Card title="Marketplace Channels: Channel API" icon="store" href="/guides/marketplace-channels/channel-api-overview">
    Full guide to building a marketplace channel integration, including SCX event handling.
  </Card>

  <Card title="Rate Limiting" icon="gauge" href="/guides/essentials/common-patterns/rate-limiting">
    Manage your API usage when polling for events at regular intervals.
  </Card>

  <Card title="Error Handling" icon="triangle-alert" href="/guides/essentials/common-patterns/error-handling">
    Handle failures in event processing and API calls.
  </Card>
</CardGroup>
