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

# Quickstart

<Steps>
  <Step title="The shopper asks for products">
    > **Shopper:** I need waterproof hiking boots for day hikes, under \$200

    That's the whole request. Next you mint a token and send this message — Channel3 opens the conversation, searches, and streams the reply.
  </Step>

  <Step title="Mint a token and run the turn">
    Keep the API key on the server. The browser only ever sees a client token.

    <CodeGroup>
      ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
      import { Channel3 } from "@channel3/sdk";

      const server = new Channel3(); // reads CHANNEL3_API_KEY

      export async function POST() {
        const created = await server.conversations.clientTokens.create();
        return Response.json({
          token: created.token,
          expiresAt: created.expires_at,
        });
      }
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
      from channel3_sdk import Channel3

      server = Channel3()  # reads CHANNEL3_API_KEY

      created = server.conversations.client_tokens.create()
      # created.token, created.expires_at
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.trychannel3.com/v1/conversations/client_tokens \
        -H "x-api-key: $CHANNEL3_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{}'
      ```
    </CodeGroup>

    Send the shopper's message with **no** conversation ID. Read the stream: save `conversation_id` from `turn.started`, append text deltas, and take the full answer from `turn.completed`.

    <CodeGroup>
      ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
      import { Channel3 } from "@channel3/sdk";

      const client = new Channel3({
        auth: () =>
          Promise.resolve({
            headers: { Authorization: `Bearer ${token}` },
          }),
      });

      let conversationId: string | undefined;

      const stream = await client.conversations.createTurnStream({
        message: {
          role: "user",
          parts: [
            {
              type: "text",
              text: "I need waterproof hiking boots for day hikes, under $200",
            },
          ],
        },
      });

      for await (const event of stream) {
        if (event.type === "turn.started") {
          conversationId = event.conversation_id; // conv_… — save this
        }
        if (event.type === "part.delta") {
          // append event.delta to the assistant text
        }
        if (event.type === "turn.completed") {
          // full answer in event.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" }]
          }
        }'
      ```
    </CodeGroup>

    > **Agent:** Let me pull up some options.

    Product cards with titles, images, prices, and buy links.

    > **Agent:** Here are a few solid day-hiking picks under \$200. The Salomon has the best waterproofing if your trails get wet.
  </Step>

  <Step title="The shopper refines">
    > **Shopper:** in brown instead

    Send only the new message plus the saved conversation ID. Channel3 already knows you were talking about sub-\$200 waterproof day-hiking boots, so it runs a new search for brown ones.

    <CodeGroup>
      ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
      const stream = await client.conversations.createTurnStream({
        message: {
          role: "user",
          parts: [{ type: "text", text: "in brown instead" }],
        },
        conversation_id: conversationId, // from turn.started
      });
      ```

      ```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": "in brown instead" }]
          },
          "conversation_id": "conv_REPLACE_ME"
        }'
      ```
    </CodeGroup>

    > **Agent:** On it — pulling up brown options in that same price range.

    Fresh product cards, then a closing message about the brown options. The conversation ID does not change. Read this stream the same way as the first turn.
  </Step>
</Steps>
