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

# Run a Turn

A **turn** is one shopper message in, one assistant reply out. `POST /v1/conversations` runs that turn. Omit `conversation_id` on the first message and Channel3 opens a conversation. Pass it on later turns to continue.

Stream with `createTurnStream` (the [quickstart](/conversations/quickstart.md) path). Use `createTurn` when you want one JSON body instead of a stream — for example a backend job.

**One turn at a time per conversation.** A second `POST` while a turn is still running returns `409`.

```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const stream = await client.conversations.createTurnStream({
  message: {
    role: "user",
    parts: [
      {
        type: "text",
        text: "I need waterproof hiking boots for day hikes, under $200",
      },
    ],
  },
  conversation_id: conversationId, // omit on the first message
});
```

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
stream = client.conversations.create_turn_stream(
    message={
        "role": "user",
        "parts": [
            {
                "type": "text",
                "text": "I need waterproof hiking boots for day hikes, under $200",
            }
        ],
    },
    conversation_id=conversation_id,  # omit on the first message
)
```

```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -N -X POST https://api.trychannel3.com/v1/conversations \
  -H "Authorization: Bearer c3_ct_..." \
  -H "Content-Type: application/json" \
  -d '{
    "message": {
      "role": "user",
      "parts": [{ "type": "text", "text": "I need waterproof hiking boots for day hikes, under $200" }]
    },
    "conversation_id": "conv_REPLACE_ME"
  }'
```

| Field | Rule |
| - | - |
| `message` | Required. Text and/or [image parts](/conversations/messages-and-parts.md). |
| `conversation_id` | Omit to create the conversation. Send to continue it. |
| `filters` | Optional. Pinned catalog filters for **this turn only**. |
| `config.collection_id` | Optional. Bind this turn's searches to a [collection](/guides/collections.md). Pass it on **every turn**. |
| `context` | Optional. Shopper and app notes. **Only on the first turn** (no `conversation_id`). |
| `stream` | Default `true`. Set `false` for one JSON response. |

The SDK sends your user id with `x-user-id` when you set it, so clicks and sales attach to your user. See [context](/conversations/context.md), [filters](/conversations/filters.md), and [streaming events](/conversations/streaming-events.md).

## One JSON reply

Set `stream: false`, or call `createTurn`. You get `message` (the full assistant reply) and `usage` (`credits_charged`, `searches_run`).

```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const result = await client.conversations.createTurn({
  message: {
    role: "user",
    parts: [{ type: "text", text: "Gift ideas for a new dad" }],
  },
});
// result.message — full assistant message
// result.usage.credits_charged, result.usage.searches_run
```

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
result = client.conversations.create_turn(
    message={
        "role": "user",
        "parts": [{"type": "text", "text": "Gift ideas for a new dad"}],
    },
)
# result.message, result.usage
```

```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.trychannel3.com/v1/conversations \
  -H "x-api-key: $CHANNEL3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "stream": false,
    "message": {
      "role": "user",
      "parts": [{"type": "text", "text": "Gift ideas for a new dad"}]
    }
  }'
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.