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

# Connect threads and lanes

> How a Connect thread models one order: participant roles, pairwise lanes with per-role visibility, an order-driven lifecycle, identity privacy, and retention.

A **thread** is the conversation home of one order. It carries the participants, the lanes they talk in, the order's status, and your `custom_data` — and it moves through its life without your backend babysitting it.

## Roles

Every participant joins with a role: `customer`, `merchant`, or `courier`. Roles are what Connect reasons about — visibility, Supervisor behavior, and analytics are all per-role, so you never hand-manage who belongs in which channel.

Participants are identified by **your** IDs (`external_id`). Connect never exposes phone numbers or emails between participants — the thread *is* the contact channel, so a customer can reach the courier without either seeing the other's number.

## Lanes

A lane is a pairwise conversation inside the thread. Each participant sees only their own lanes; the Supervisor sees all of them.

| Lane                | Customer sees | Merchant sees | Courier sees | Default                 |
| ------------------- | ------------- | ------------- | ------------ | ----------------------- |
| `customer_merchant` | ✓             | ✓             | —            | On                      |
| `customer_courier`  | ✓             | —             | ✓            | On                      |
| `merchant_courier`  | —             | ✓             | ✓            | Off — enable per thread |

Why lanes instead of one open room? Because a merchant's "we're out of the grilled chicken, substitute?" belongs with the customer, while a courier's "parking is a nightmare, use the back entrance" belongs with the merchant — and neither should read the other's traffic. Lanes give you a three-touchpoint conversation with 1:1 privacy.

A lane is `waiting` until both of its roles are present (the customer↔courier lane before courier assignment), `active` while the thread is open, and `closed` when the thread locks.

## Lifecycle — the order drives it

You report order status with a single [PATCH](/api-reference/connect/update-thread); Connect translates it into conversation behavior.

```mermaid theme={"dark"}
stateDiagram-v2
  direction LR
  [*] --> open : thread created
  open --> wrap_up : order_status = delivered
  open --> locked : order_status = cancelled
  wrap_up --> locked : grace window ends (default 24h)
  locked --> archived : retention window ends (default 30d)
  archived --> [*]
```

| You send `order_status` | Connect does                                                         |
| ----------------------- | -------------------------------------------------------------------- |
| `confirmed`             | Thread opens; `customer_merchant` lane active                        |
| `preparing`, `ready`    | Status chip updates in the UI; Supervisor uses it to answer ETAs     |
| `picked_up`             | Courier lane messaging emphasized; merchant lane winds down          |
| `delivered`             | Wrap-up window starts; when it ends, thread locks read-only          |
| `cancelled`             | Thread locks immediately; Supervisor handles "why was it cancelled?" |

Locked threads stay readable to participants and your team but accept no new messages — participants who need more help get one tap into your regular support flow via the Supervisor. Archived threads leave the apps entirely and remain queryable by [API](/api-reference/connect/list-threads) until retention deletes them.

Grace and retention windows are configurable per org in **Connect → Lifecycle**, and per thread at [creation](/api-reference/connect/create-thread).

## Reassignment

Couriers change; threads shouldn't. [Remove](/api-reference/connect/remove-participant) the old courier and [add](/api-reference/connect/add-participant) the new one:

* The removed courier loses access immediately — including history.
* The new courier joins the same lane with fresh context; the Supervisor briefs them with a one-line summary ("Customer asked to leave the order at the gate, code 4411").
* The customer keeps one continuous conversation instead of starting over.

## What the thread carries

* **`reference`** — your order ID. Unique per org, idempotency key for creation, and the join key for everything analytics.
* **`custom_data`** — arbitrary JSON (vertical, basket value, promo flags). Surfaced to the Supervisor as answering context and returned on every read.
* **Messages** — text and attachments, each stamped with lane, sender participant, and per-language `translations`.
* **Events** — join/leave, status changes, Supervisor interventions: the full audit trail of the order conversation, exportable via [API](/api-reference/connect/list-messages) and streamed via [webhooks](/connect/webhooks).

## Privacy defaults

* No participant ever sees another's contact details — identity is display name + role, full stop.
* The Supervisor masks phone numbers, emails, and payment details typed into any lane (see [AI Supervisor](/connect/ai-supervisor)); attempts to move the conversation off-platform are flagged to you by webhook.
* Locked-thread history is retained for disputes exactly as long as your retention window — then it's gone everywhere.

<CardGroup cols={2}>
  <Card title="AI Supervisor" icon="shield-halved" href="/connect/ai-supervisor">
    The fourth participant: observe, assist, and resolve modes per lane.
  </Card>

  <Card title="Create a thread" icon="code" href="/api-reference/connect/create-thread">
    Full request/response reference for thread creation.
  </Card>
</CardGroup>
