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

# Conversational API

> Create a conversational API for your application

Create a chat API endpoint that handles streaming responses from the C1 model.

<Steps>
  <Step title="Install required dependencies">
    Install the necessary packages for your backend API:

    <CodeGroup dropdown>
      ```bash npm theme={null}
      npm install openai @crayonai/stream
      ```

      ```bash pip theme={null}
      pip install openai fastapi uvicorn thesys-genui-sdk
      ```
    </CodeGroup>
  </Step>

  <Step title="Create the message store">
    First, create a simple in-memory message store to manage conversation history.
    This in-memory store just stores the list of messages for a given `threadId`
    including messages that are not sent to the client like the tool call messages.

    <CodeGroup dropdown>
      ```ts app/api/chat/messageStore.ts theme={null}
      import OpenAI from "openai";

      export type DBMessage = OpenAI.Chat.ChatCompletionMessageParam & {
        id?: string;
      };

      const messagesStore: {
        [threadId: string]: DBMessage[];
      } = {};

      export const getMessageStore = (threadId: string) => {
        if (!messagesStore[threadId]) {
          messagesStore[threadId] = [];
        }
        const messageList = messagesStore[threadId];
        return {
          addMessage: (message: DBMessage) => {
            messageList.push(message);
          },
          getOpenAICompatibleMessageList: () => {
            return messageList.map((m) => {
              const message = { ...m };
              delete message.id;
              return message;
            });
          },
        };
      };
      ```

      ```python message_store.py theme={null}
      from typing import Dict, List, Any

      # Type alias for messages
      DBMessage = Dict[str, Any]

      messages_store: Dict[str, List[DBMessage]] = {}


      class MessageStore:
          def __init__(self, thread_id: str):
              if thread_id not in messages_store:
                  messages_store[thread_id] = []
              self.message_list = messages_store[thread_id]

          def add_message(self, message: DBMessage):
              self.message_list.append(message)

          def get_openai_compatible_message_list(self) -> List[Dict[str, Any]]:
              return [
                  {k: v for k, v in msg.items() if k != "id"}
                  for msg in self.message_list
              ]


      def get_message_store(thread_id: str) -> MessageStore:
          return MessageStore(thread_id)
      ```
    </CodeGroup>
  </Step>

  <Step title="Create the chat endpoint">
    Create the main API endpoint that handles incoming chat requests with streaming:

    <CodeGroup dropdown>
      ```ts app/api/chat/route.ts theme={null}
      import { NextRequest, NextResponse } from "next/server";
      import OpenAI from "openai";
      import { transformStream } from "@crayonai/stream";
      import { DBMessage, getMessageStore } from "./messageStore";

      export async function POST(req: NextRequest) {
        const { prompt, threadId, responseId } = (await req.json()) as {
          prompt: DBMessage;
          threadId: string;
          responseId: string;
        };

        // Initialize the OpenAI client
        const client = new OpenAI({
          baseURL: "https://api.thesys.dev/v1/embed/",
          apiKey: process.env.THESYS_API_KEY,
        });

        // Get message store and add user message
        const messageStore = getMessageStore(threadId);
        messageStore.addMessage(prompt);

        // Create streaming chat completion
        const llmStream = await client.chat.completions.create({
          model: "c1/anthropic/claude-sonnet-4/v-20251230",
          messages: messageStore.getOpenAICompatibleMessageList(),
          stream: true,
        });

        // Transform the response stream
        const responseStream = transformStream(
          llmStream,
          (chunk) => {
            return chunk.choices[0].delta.content;
          },
          {
            onEnd: ({ accumulated }) => {
              const message = accumulated.filter((message) => message).join("");
              messageStore.addMessage({
                role: "assistant",
                content: message,
                id: responseId,
              });
            },
          }
        ) as ReadableStream;

        // Return the streaming response
        return new NextResponse(responseStream, {
          headers: {
            "Content-Type": "text/event-stream",
            "Cache-Control": "no-cache, no-transform",
            Connection: "keep-alive",
          },
        });
      }
      ```

      ```python main.py theme={null}
      import os
      from fastapi import FastAPI
      from pydantic import BaseModel
      from openai import OpenAI
      from thesys_genui_sdk.fast_api import with_c1_response
      from thesys_genui_sdk.context import write_content, get_assistant_message
      from message_store import get_message_store, DBMessage

      app = FastAPI()


      class ChatRequest(BaseModel):
          prompt: DBMessage
          threadId: str
          responseId: str


      @app.post("/api/chat")
      @with_c1_response()
      async def chat(request: ChatRequest):
          # Initialize the OpenAI client
          client = OpenAI(
              api_key=os.environ["THESYS_API_KEY"],
              base_url="https://api.thesys.dev/v1/embed",
          )

          # Get message store and add user message
          message_store = get_message_store(request.threadId)
          message_store.add_message(request.prompt)

          # Create streaming chat completion
          stream = client.chat.completions.create(
              model="c1/anthropic/claude-sonnet-4/v-20251230",
              messages=message_store.get_openai_compatible_message_list(),
              stream=True,
          )

          # Stream the response
          for chunk in stream:
              content = chunk.choices[0].delta.content
              if content:
                  await write_content(content)

          # Get and store the assistant message
          assistant_message = get_assistant_message()
          assistant_message["id"] = request.responseId
          message_store.add_message(assistant_message)
      ```
    </CodeGroup>
  </Step>

  <Step title="Set your API key">
    Make sure to set your Thesys API key as an environment variable:

    ```bash theme={null}
    export THESYS_API_KEY=<your-api-key>
    ```

    <CodeGroup dropdown>
      ```bash Next.js (.env.local) theme={null}
      THESYS_API_KEY=<your-api-key>
      ```

      ```bash Python (.env) theme={null}
      THESYS_API_KEY=<your-api-key>
      ```
    </CodeGroup>
  </Step>
</Steps>

Your API endpoint is now ready to handle streaming chat conversations with the C1 model!
