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

# Watch the document live

> Get each paragraph as it is written, the pages as they are generated, and the end.

`documents.stream` creates the document and gives you its [events](/en/guides/events) as they happen.

```ts theme={null}
for await (const event of doconda.documents.stream({ format: "docx", prompt: "Report on remote work" })) {
  switch (event.type) {
    case "content.block_delta":
      process.stdout.write(String(event.data.text)) // the text as it is written
      break
    case "preview.page_ready":
      console.log(`\npage ${event.data.page} of ${event.data.total}`)
      break
    case "document.ready":
      console.log("\ndone!")
      break
    case "document.failed":
      console.error(event.data.error)
  }
}
```

Each event carries `display.es`: a short text ("Revisando…", "¡Listo!") meant to be shown as is in your interface.

## On your site

The API key cannot go to the browser, so your server acts as a bridge: it receives the events with the SDK and
forwards them to your page. For example, with a Next.js route:

```ts app/api/report/route.ts theme={null}
import { Doconda } from "@doconda/sdk"

const doconda = new Doconda()

export async function POST(req: Request) {
  const { prompt } = await req.json()
  const encoder = new TextEncoder()
  const body = new ReadableStream({
    async start(controller) {
      for await (const event of doconda.documents.stream({ format: "docx", prompt }, { signal: req.signal })) {
        controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`))
      }
      controller.close()
    },
  })
  return new Response(body, { headers: { "content-type": "text/event-stream" } })
}
```

If the user closes the page, `signal` cuts the stream. The document keeps being created anyway; you can get it with
`documents.get(id)`.

## Follow a document that already exists

If you created it in the background, or the connection dropped, follow its events from where you left off:

```ts theme={null}
let last = 0
for await (const event of doconda.documents.events(doc.id, { after: last })) {
  last = event.sequence // store it: with it you resume without losing or repeating events
}
```

## Cancel

```ts theme={null}
await doconda.documents.cancel(doc.id) // queued or in progress; if it already finished, it does nothing
```


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