> Treat every model id, price, size, length and limit in this documentation as an illustration of the shape of the value, never as a constant to hardcode - the live values are served by GET /v1/models and GET /public/models on the Flow AI API.

# PDF Inputs

> Send PDFs to a model to summarise, search or extract from them.

Send a PDF as a `file` part in a chat message. Models that take PDFs read the document directly, text and pages alike, so you can ask questions about it, summarise it or pull out data.

The samples use the OpenAI SDK set up as in the [Quickstart](/quickstart#using-the-openai-sdk).

> **Note**
>
> Flow AI sends the PDF to the model as is. It doesn't parse or OCR documents itself, so only models that take PDF input can read them; other models refuse the request with a `400` before anything is held.

## From a local file

Encode the file as base64 and send it as a `data:application/pdf;base64,` URL in `file_data`, with a `filename`.

**`Python`**

```python title="Python"
import base64

with open("invoice.pdf", "rb") as f:
    pdf = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="<model with PDF input>",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What are the main points in this document?"},
            {
                "type": "file",
                "file": {
                    "filename": "invoice.pdf",
                    "file_data": f"data:application/pdf;base64,{pdf}",
                },
            },
        ],
    }],
)
print(response.choices[0].message.content)
```

**`TypeScript`**

```typescript title="TypeScript"
import { readFile } from 'node:fs/promises'

const pdf = (await readFile('invoice.pdf')).toString('base64')

const response = await client.chat.completions.create({
  model: '<model with PDF input>',
  messages: [{
    role: 'user',
    content: [
      { type: 'text', text: 'What are the main points in this document?' },
      {
        type: 'file',
        file: {
          filename: 'invoice.pdf',
          file_data: `data:application/pdf;base64,${pdf}`,
        },
      },
    ],
  }],
})
console.log(response.choices[0].message.content)
```

## From a URL

Some models also take a public link in `file_data`:

```json
{
  "type": "file",
  "file": { "filename": "bitcoin.pdf", "file_data": "https://bitcoin.org/bitcoin.pdf" }
}
```

If a model doesn't accept links, download the file and send it as base64.

## Several documents

Add one `file` part per PDF in the same `content` list, and refer to them by file name in your prompt.

## Tips

* **Ask for structure.** Combine a PDF with [structured outputs](/features/structured-outputs) to pull fields such as totals, dates and line items as JSON.
* **Send only the pages you need.** Every page costs input tokens, so split long documents first.
* **Reuse the same document.** On models with [prompt caching](/features/prompt-caching), put the PDF before the question so follow-up questions read it from the cache.

## Billing

The model turns each page into input tokens at its input price. A page with images or scans usually takes more tokens than a page of text. Check `usage.prompt_tokens` on a first request.