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

# How to return a Word file from the OpenAI API

> Pass doconda.tools() as functions in Chat Completions: the model calls create_document and returns links to the .docx and its PDF.

The OpenAI API returns text, not files. Install `doconda` (or `@doconda/sdk`), pass `doconda.tools()` as `tools` in
`chat.completions.create` and, when the model calls `create_document`, run it with `run()`: you get the Word file
(`.docx`) and its PDF with their download links.

## Steps

1. Put your OpenAI key in `OPENAI_API_KEY` and your Doconda key (dashboard → **API keys**) in `DOCONDA_API_KEY`.
2. Turn each tool into OpenAI's `function` format.
3. Run the loop: while the message has `tool_calls`, run each tool and hand the result back.

<CodeGroup>
  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  # pip install openai doconda
  import json

  from doconda import Doconda
  from openai import OpenAI

  openai = OpenAI()
  tools = Doconda().tools()
  specs = [{"type": "function", "function": {"name": t.name, "description": t.description, "parameters": t.input_schema}} for t in tools]
  messages = [{"role": "user", "content": "Write a Word memo for the team: the office is closed on Friday"}]

  while True:
      message = openai.chat.completions.create(model="gpt-5", messages=messages, tools=specs).choices[0].message
      messages.append(message)
      if not message.tool_calls:
          break
      for call in message.tool_calls:
          out = next(t for t in tools if t.name == call.function.name).run(json.loads(call.function.arguments))
          messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(out)})

  print(message.content)
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  // npm install openai @doconda/sdk
  import OpenAI from "openai"
  import { Doconda } from "@doconda/sdk"

  const openai = new OpenAI()
  const docondaTools = new Doconda().tools()
  const tools = docondaTools.map((t) => ({ type: "function" as const, function: { name: t.name, description: t.description, parameters: t.inputSchema } }))
  const messages: any[] = [{ role: "user", content: "Write a Word memo for the team: the office is closed on Friday" }]

  while (true) {
    const res = await openai.chat.completions.create({ model: "gpt-5", messages, tools })
    const message = res.choices[0]?.message
    if (!message) break
    messages.push(message)
    if (!message.tool_calls?.length) break
    for (const call of message.tool_calls) {
      if (call.type !== "function") continue
      const result = await docondaTools.find((t) => t.name === call.function.name)!.run(JSON.parse(call.function.arguments))
      messages.push({ role: "tool", tool_call_id: call.id, content: JSON.stringify(result) })
    }
  }
  ```
</CodeGroup>

Already have the model's text and don't need an agent? Call `doconda.documents.create(format="docx",
content={"markdown": text})` directly with its answer.

## What you get back

```json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
{
  "id": "doc_01JAB3…",
  "format": "docx",
  "status": "ready",
  "links": { "docx": "https://…", "pdf": "https://…" },
  "links_note": "Links expire in 5 minutes: call get_document for fresh ones."
}
```

* An editable Word file: the look lives in its styles (Normal, Heading 1…), so anything added later keeps the design.
* `status`: `ready`, `ready_with_warnings`, `needs_review` or `failed` (not charged).
* Links expire after 5 minutes; the agent gets fresh ones with `get_document`.

## FAQ

<AccordionGroup>
  <Accordion title="Can I download the file on my server instead of passing the link?">
    Yes. With the `id` the tool returns, `doconda.documents.download(id, "docx")` gives you the bytes.
  </Accordion>

  <Accordion title="What if I want a PDF?">
    Ask for it in the message: `create_document` accepts `format: "pdf"` (PDF only). A Word file always comes with its
    PDF.
  </Accordion>

  <Accordion title="Does it work with Azure OpenAI?">
    Yes, the same code with `AzureOpenAI()`. See [Azure OpenAI](/en/agents/azure).
  </Accordion>

  <Accordion title="How much does it cost?">
    You pay per delivered document; creating from your own Markdown costs less than from a prompt. See
    [pricing](/en/guides/account#pricing).
  </Accordion>
</AccordionGroup>

## Keep reading

* [OpenAI](/en/agents/openai): the full guide, also with OpenAI Codex.
* [Quickstart](/en/quickstart).


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