Skip to content
Docs

AI Gateway File and PDF Input

Send a document with a question to summarize its contents or extract information. These examples send a PDF directly in the request. For photos and screenshots, see vision.

Set AI_GATEWAY_API_KEY, install your SDK or API client, and save a PDF as document.pdf in your working directory. Use a model that supports PDF input.

File support depends on the model and provider. A file part does not make every document format compatible. Extract text from unsupported office documents before sending it as a text part. For scanned pages, choose a model that can also interpret the page images.

These examples send the PDF bytes and request a summary. The SDK examples print the summary; cURL prints the JSON response containing it:

file-input.ts
import { readFileSync } from 'node:fs';
import { generateText } from 'ai';
 
const { text } = await generateText({
  model: 'anthropic/claude-sonnet-5',
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: 'Summarize this document in one sentence.' },
        {
          type: 'file',
          data: readFileSync('document.pdf'),
          mediaType: 'application/pdf',
        },
      ],
    },
  ],
});
 
console.log(text);
file-input_ai.py
import asyncio
from pathlib import Path
import ai
 
 
async def main():
    model = ai.get_model("anthropic/claude-sonnet-5")
    messages = [
        ai.user_message(
            "Summarize this document in one sentence.",
            ai.file_part(
                Path("document.pdf").read_bytes(), media_type="application/pdf"
            ),
        )
    ]
    async with ai.stream(model, messages) as stream:
        async for event in stream:
            if isinstance(event, ai.events.TextDelta):
                print(event.chunk, end="", flush=True)
    print()
 
 
asyncio.run(main())
file-input-chat.ts
import { readFileSync } from 'node:fs';
import OpenAI from 'openai';
 
const client = new OpenAI({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh/v1',
});
const data = readFileSync('document.pdf').toString('base64');
 
const response = await client.chat.completions.create({
  model: 'anthropic/claude-sonnet-5',
  messages: [
    {
      role: 'user',
      content: [
        {
          type: 'text',
          text: 'Summarize this document in one sentence.',
        },
        {
          type: 'file',
          file: {
            filename: 'document.pdf',
            file_data: `data:application/pdf;base64,${data}`,
          },
        },
      ],
    },
  ],
});
 
console.log(response.choices[0]?.message.content);
file-input_chat.py
import base64
import os
from pathlib import Path
from openai import OpenAI
 
client = OpenAI(
    api_key=os.environ["AI_GATEWAY_API_KEY"],
    base_url="https://ai-gateway.vercel.sh/v1",
)
data = base64.b64encode(Path("document.pdf").read_bytes()).decode("ascii")
 
response = client.chat.completions.create(
    model="anthropic/claude-sonnet-5",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Summarize this document in one sentence."},
                {
                    "type": "file",
                    "file": {
                        "filename": "document.pdf",
                        "file_data": f"data:application/pdf;base64,{data}",
                    },
                },
            ],
        }
    ],
)
 
print(response.choices[0].message.content)
file-input-chat.sh
FILE_BASE64=$(base64 < document.pdf | tr -d '\n')
 
printf '{
  "model": "anthropic/claude-sonnet-5",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Summarize this document in one sentence."
        },
        {
          "type": "file",
          "file": {
            "filename": "document.pdf",
            "file_data": "data:application/pdf;base64,%s"
          }
        }
      ]
    }
  ]
}' "$FILE_BASE64" | \
curl --fail-with-body https://ai-gateway.vercel.sh/v1/chat/completions \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @-
file-input-messages.ts
import { readFileSync } from 'node:fs';
import Anthropic from '@anthropic-ai/sdk';
 
const client = new Anthropic({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh',
});
const data = readFileSync('document.pdf').toString('base64');
 
const response = await client.messages.create({
  model: 'anthropic/claude-sonnet-5',
  max_tokens: 1024,
  messages: [
    {
      role: 'user',
      content: [
        {
          type: 'text',
          text: 'Summarize this document in one sentence.',
        },
        {
          type: 'document',
          source: {
            type: 'base64',
            media_type: 'application/pdf',
            data: data,
          },
        },
      ],
    },
  ],
});
 
for (const block of response.content) {
  if (block.type === 'text') console.log(block.text);
}
file-input_messages.py
import base64
import os
from pathlib import Path
from anthropic import Anthropic
 
client = Anthropic(
    api_key=os.environ["AI_GATEWAY_API_KEY"],
    base_url="https://ai-gateway.vercel.sh",
)
data = base64.b64encode(Path("document.pdf").read_bytes()).decode("ascii")
 
response = client.messages.create(
    model="anthropic/claude-sonnet-5",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Summarize this document in one sentence."},
                {
                    "type": "document",
                    "source": {
                        "type": "base64",
                        "media_type": "application/pdf",
                        "data": data,
                    },
                },
            ],
        }
    ],
)
 
for block in response.content:
    if block.type == "text":
        print(block.text)
file-input-messages.sh
FILE_BASE64=$(base64 < document.pdf | tr -d '\n')
 
printf '{
  "model": "anthropic/claude-sonnet-5",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Summarize this document in one sentence."
        },
        {
          "type": "document",
          "source": {
            "type": "base64",
            "media_type": "application/pdf",
            "data": "%s"
          }
        }
      ]
    }
  ]
}' "$FILE_BASE64" | \
curl --fail-with-body https://ai-gateway.vercel.sh/v1/messages \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  --data-binary @-
file-input-responses.ts
import { readFileSync } from 'node:fs';
import OpenAI from 'openai';
 
const client = new OpenAI({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh/v1',
});
const data = readFileSync('document.pdf').toString('base64');
 
const response = await client.responses.create({
  model: 'anthropic/claude-sonnet-5',
  input: [
    {
      role: 'user',
      content: [
        {
          type: 'input_text',
          text: 'Summarize this document in one sentence.',
        },
        {
          type: 'input_file',
          filename: 'document.pdf',
          file_data: `data:application/pdf;base64,${data}`,
        },
      ],
    },
  ],
});
 
console.log(response.output_text);
file-input_responses.py
import base64
import os
from pathlib import Path
from openai import OpenAI
 
client = OpenAI(
    api_key=os.environ["AI_GATEWAY_API_KEY"],
    base_url="https://ai-gateway.vercel.sh/v1",
)
data = base64.b64encode(Path("document.pdf").read_bytes()).decode("ascii")
 
response = client.responses.create(
    model="anthropic/claude-sonnet-5",
    input=[
        {
            "role": "user",
            "content": [
                {
                    "type": "input_text",
                    "text": "Summarize this document in one sentence.",
                },
                {
                    "type": "input_file",
                    "filename": "document.pdf",
                    "file_data": f"data:application/pdf;base64,{data}",
                },
            ],
        }
    ],
)
 
print(response.output_text)
file-input-responses.sh
FILE_BASE64=$(base64 < document.pdf | tr -d '\n')
 
printf '{
  "model": "anthropic/claude-sonnet-5",
  "input": [
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "Summarize this document in one sentence."
        },
        {
          "type": "input_file",
          "filename": "document.pdf",
          "file_data": "data:application/pdf;base64,%s"
        }
      ]
    }
  ]
}' "$FILE_BASE64" | \
curl --fail-with-body https://ai-gateway.vercel.sh/v1/responses \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @-

See the AI SDK file-part guide and Python beta multimodal-message guide for constructing SDK messages. The table below compares those messages with the HTTP formats.

FormatInput representationDetails
AI SDK 7file part with mediaType: 'application/pdf'Pass bytes, a data URL, or a supported URL. See file parts.
AI SDK for Python (beta)ai.file_part(..., media_type="application/pdf")See Python file parts.
Chat Completionsfile with filename and a file_data data URLAI Gateway maps the file to the selected provider. See file requests.
Messages APIdocument with a base64 PDF sourceSee Messages documents.
Responses / OpenResponsesinput_file with filename and a file_data data URLFor non-OpenAI models, AI Gateway translates the request through OpenResponses. Native Responses models have their own input support.

Inline base64 increases the request size. Check the selected model's context and file-size limits, and keep any fallback models compatible with the input type. When using a hosted URL, make sure the provider can retrieve it without your application's browser session.

For request details and failures, inspect AI Gateway logs. See Inputs & Tools to choose another capability.

Last updated September 8, 2026

Was this helpful?

supported.