Skip to main content

Reading Document Content

A customer sends a voice note on WhatsApp. A PDF lands in one of your collections. You want that content in your own system — the words spoken, the text on the page, even what's inside an embedded image.

Docana transcribes and extracts every document it ingests. Read the result with one endpoint: GET /api/v1/documents/{id}/content/. The user's locale guides generated transcriptions and media descriptions. The content API does not accept a request language parameter.

What you get, by file type

The same endpoint serves every type — only the kind of content differs:

File typeWhat comes back
AudioVerbatim transcription with speaker labels, split into time windows
VideoPer time window: the spoken transcription, a description of the scene, and any text shown on screen
ImageA detailed visual description, plus the text read from the image (OCR)
PDF, Word, spreadsheetsThe extracted text, split into chunks. Embedded images and charts are described too

Scanned PDFs work — Docana runs OCR, so a PDF with no selectable text still returns its content.

The flow

Content is ready once a document finishes ingesting. Three steps:

  1. Find the document id. Where you get it depends on the source (see below).
  2. Wait until it's ready with GET /api/v1/documents/{id}/status/ — content is available when the status is COMPLETED.
  3. Read the content with GET /api/v1/documents/{id}/content/.

Every call uses the ApiKey header (see API Overview):

Authorization: ApiKey YOUR_API_KEY

1. Find the document id

There is no single "list documents" call — you get the id from wherever the document came from:

  • A chat or WhatsApp attachment — the message carries it. Read the thread's messages and look at the file part in the message content:

    curl "https://platform.docana.com/api/v1/threads/${THREAD_ID}/messages/" \
    -H "Authorization: ApiKey ${API_KEY}"
    {
    "role": "USER",
    "content": [
    {
    "type": "file",
    "mediaType": "audio/mp4",
    "documentId": 67508,
    "url": "https://platform.docana.com/api/v1/documents/67508/download/",
    "viewUrl": "https://platform.docana.com/api/documents/67508/download/?vid=…"
    }
    ]
    }

    The documentId is what you need; the url downloads the original file (with your API key). The viewUrl serves the same bytes without credentials — hand it to anything that can't send your API key, like a chat client rendering an image or an MCP host attaching the file. It expires after a few hours; re-fetch the message for a fresh one. Document listings (GET /api/v1/collections/{id}/documents/, GET /api/v1/documents/{id}/) carry the same pair as downloadUrl/viewUrl per document.

    Older WhatsApp messages may predate document-backed attachments. The first time you fetch one by id (GET /api/v1/messages/{id}/), Docana repairs it on the spot — ingesting the attachment and assigning it a documentId. While that happens the call can return 202, 409, or 503 with a Retry-After header and a body like { "attachmentRepair": { "status": "PROCESSING" } }. Just retry after the indicated delay; within a few seconds the message comes back complete. An attachment that can't be recovered comes back as a placeholder part with "unavailable": true.

  • A document in a collection (uploaded or synced from a connector) — list the collection's documents and take each id:

    curl "https://platform.docana.com/api/v1/collections/${COLLECTION_ID}/documents/" \
    -H "Authorization: ApiKey ${API_KEY}"

    Uploading a document returns its id too, so you can skip the list when you just uploaded it.

2. Wait until it's ready

Transcription runs right after a file arrives — usually seconds. Poll the status until it's COMPLETED:

curl "https://platform.docana.com/api/v1/documents/67508/status/" \
-H "Authorization: ApiKey ${API_KEY}"
{ "id": 67508, "status": "COMPLETED" }

Before it's COMPLETED, the content call returns an empty chunks list.

3. Read the content

curl "https://platform.docana.com/api/v1/documents/67508/content/" \
-H "Authorization: ApiKey ${API_KEY}"

For audio and video, each chunk is one transcribed time window:

{
"id": 67508,
"status": "COMPLETED",
"version": 1,
"chunks": [
{
"index": 0,
"content": "# Timestamp: [0:00 - 0:28]\n\n# Transcription:\nSpeaker 1: Good afternoon, I'd like to ask about...",
"startOffsetSec": 0,
"endOffsetSec": 28
}
],
"totalCount": 1
}

For a PDF or document, each chunk is a piece of the document — a paragraph, a heading, a table, or the description of an embedded image:

{
"id": 12345,
"status": "COMPLETED",
"version": 1,
"chunks": [
{ "index": 0, "content": "Customer Satisfaction Report — Q2 2026" },
{
"index": 1,
"content": "3. Satisfaction by segment\nMost respondents rated..."
},
{
"index": 2,
"content": "[Image: bar chart of satisfaction by age group; '18-25' at ~72%, '26-40' at ~85%]"
}
],
"totalCount": 8
}

To rebuild the whole document, join the chunks in index order. startOffsetSec and endOffsetSec are present only for audio and video, which are time-based. Docana processes media across its full duration in internal slices. Slice duration is an implementation detail, not a public duration limit.

Long documents

Chunks are paginated. Pass page and limit, and use totalCount to know when you've read everything:

curl "https://platform.docana.com/api/v1/documents/67508/content/?page=2&limit=100" \
-H "Authorization: ApiKey ${API_KEY}"

Next Steps