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

# Build grounded answers into your product

> Call MITHUNAI from your own backend to ask questions, stream cited answers, manage knowledge and assistants, and read usage, with a server-held API key.

The HTTP API gives your own software everything the console can do: ask questions, stream answers, manage knowledge and assistants, and read usage.

## How to integrate

Call the API from your **backend**. Your server holds the API key, calls MITHUNAI, and returns answers and citations to your interface.

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
sequenceDiagram
    participant U as Your user
    participant B as Your backend
    participant M as MITHUNAI
    U->>B: Question
    B->>M: POST /conversations/{id}/messages:stream<br/>Authorization: Bearer arukz_sk_…
    M-->>B: answer.delta … answer.sources … answer.completed
    B-->>U: Answer and citations
```

Browsers cannot call the API directly from another origin, and must not hold an API key. The only endpoints designed for browsers on your own site are the [widget endpoints](/channels/widget).

## A minimal integration

<CodeGroup>
  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import os
  import requests

  BASE = f"{os.environ['MITHUNAI_URL']}/arukz/api/v1"
  HEADERS = {"Authorization": f"Bearer {os.environ['MITHUNAI_API_KEY']}"}


  def ask(assistant_id: str, question: str, conversation_id: str | None = None) -> dict:
      if conversation_id is None:
          conversation = requests.post(
              f"{BASE}/conversations", headers=HEADERS, json={"assistant_id": assistant_id}, timeout=30
          )
          conversation.raise_for_status()
          conversation_id = conversation.json()["id"]

      turn = requests.post(
          f"{BASE}/conversations/{conversation_id}/messages",
          headers=HEADERS,
          json={"text": question},
          timeout=120,
      )
      turn.raise_for_status()
      answer = turn.json()["answer"]
      return {
          "conversation_id": conversation_id,
          "text": answer["text"],
          "abstained": answer["abstained"],
          "citations": [{"title": c["title"], "url": c["url"]} for c in answer["citations"]],
      }
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const BASE = `${process.env.MITHUNAI_URL}/arukz/api/v1`
  const HEADERS = {
    Authorization: `Bearer ${process.env.MITHUNAI_API_KEY}`,
    'Content-Type': 'application/json',
  }

  export async function ask(assistantId, question, conversationId) {
    if (!conversationId) {
      const res = await fetch(`${BASE}/conversations`, {
        method: 'POST',
        headers: HEADERS,
        body: JSON.stringify({ assistant_id: assistantId }),
      })
      if (!res.ok) throw new Error(`MITHUNAI ${res.status}`)
      conversationId = (await res.json()).id
    }

    const res = await fetch(`${BASE}/conversations/${conversationId}/messages`, {
      method: 'POST',
      headers: HEADERS,
      body: JSON.stringify({ text: question }),
    })
    if (!res.ok) throw new Error(`MITHUNAI ${res.status}`)
    const { answer } = await res.json()
    return {
      conversationId,
      text: answer.text,
      abstained: answer.abstained,
      citations: answer.citations.map(({ title, url }) => ({ title, url })),
    }
  }
  ```
</CodeGroup>

Reuse the `conversation_id` for follow-up questions so the assistant keeps the context of the conversation.

## Build a good client

* **Render citations.** Link each citation's `title` to its `url`. Verification is most of the value.
* **Treat abstention as a normal answer.** Show it as a reply; do not retry it or fall back to another model. Consider offering a "report missing content" action.
* **Stream for people, wait for machines.** Use [streaming](/api-reference/streaming) when a person is watching, and the complete-answer endpoint for scripts and jobs.
* **Send an idempotency key** with each question so a retry after a network failure returns the original answer rather than asking, and paying, twice.
* **One question at a time per conversation.** A second concurrent question in the same conversation is refused with `409`.
* **Back off on `429`**, honouring `Retry-After`. See [Rate limits](/api-reference/rate-limits).
* **Ignore unknown fields and event types.** New optional fields can be added within `v1`.

## Next

<Columns cols={2}>
  <Card title="Authentication" icon="key-round" href="/api-reference/authentication">
    Create and use API keys.
  </Card>

  <Card title="API reference" icon="square-terminal" href="/api-reference/introduction">
    Every endpoint, with examples.
  </Card>
</Columns>
