---
title: "Multimodal RAG for PDFs, images, and web pages | Calypso Context"
canonical_url: "https://www.calypso.so/context/sources"
last_updated: "2026-09-16T00:41:14.672Z"
meta:
  description: "What Calypso Context reads: PDFs as text and page images, PNG and JPEG for content, DOCX, Markdown, CSV, JSON, code, and living web pages. Upload one file, import by URL, or batch up to 100, then wait for one ready bit."
  keywords: "multimodal RAG for PDFs and images, chat with PDFs and images, ingest website into knowledge base, RAG for screenshots and diagrams, RAG ingestion API"
  "og:description": "What Calypso Context reads: PDFs as text and page images, PNG and JPEG for content, DOCX, Markdown, CSV, JSON, code, and living web pages. Upload one file, import by URL, or batch up to 100, then wait for one ready bit."
  "og:title": "Multimodal RAG for PDFs, images, and web pages | Calypso Context"
  "twitter:description": "What Calypso Context reads: PDFs as text and page images, PNG and JPEG for content, DOCX, Markdown, CSV, JSON, code, and living web pages. Upload one file, import by URL, or batch up to 100, then wait for one ready bit."
  "twitter:title": "Multimodal RAG for PDFs, images, and web pages | Calypso Context"
---

Calypso home

**Calypso Context · Sources**

# PDFs, images, pages, and data. Read, not just stored.

A source is accepted if Calypso can read it and rejected at upload if it cannot. PDFs are read as text and as page images, images for what they depict, web pages as living sources. Every source lands in a bucket and reports one ready bit when it is searchable.

[**Read the ingest docs**](https://docs.calypso.so/context/ingest) [**Start 14-day free trial**](https://context.calypso.so/join)

**The example**

## One call in. One bit to wait for.

Upload a file with one multipart request, or hand Calypso a URL. Either way the result is a source in a bucket, and ready tells you when an agent can cite it.

**CALYPSO_API_KEY**

```
curl -X POST "https://api.calypso.so/v1/buckets/support-handbook/files" \
  -H "Authorization: Bearer $CALYPSO_API_KEY" \
  -H "Idempotency-Key: crm-doc-123" \
  -F "file=@refund_policy_2026.pdf" \
  -F "title=Refund policy 2026" \
  -F "tags=policy,returns"

# 202 → { "id": "src_…", "ready": false, "status": "queued", … }
```

**What it reads**

## The accepted types, and what a citation points at.

Modality decides how a source is read. Where the citation points decides what your users can check.

| Family | Types | Modality | Citations point at |
| --- | --- | --- | --- |
| **PDF** | .pdf | Multimodal: text and page images | The page |
| **Images** | .png .jpg .jpeg | Image, read for content, not filename | The image |
| **Documents** | .docx | Text | The document |
| **Text** | .md .txt and other text/* | Text | The document |
| **Data** | .csv .json | Text | The document |
| **Code** | .py .ts .tsx .js .jsx .java .go .rs .sql .html .css .scss .yml .yaml .toml .ini .env .sh | Text | The document |

PDFs are the only document type read visually as well as textually, which is why they are the only ones that can cite a specific page. Excel files are not accepted: export the sheet to CSV before uploading.

**A URL**

## Two doors, one decision.

You have a URL. There are two different things you might be asking Calypso to do with it, and they are different promises.

### **Import a file by URL**

<dl>

<dt>**You are asking**</dt>
<dd>Copy this exact document.</dd>

<dt>**Endpoint**</dt>
<dd>POST /v1/buckets//files/import</dd>

<dt>**Identity**</dt>
<dd>Each import creates a new source.</dd>

<dt>**Lifecycle**</dt>
<dd>A snapshot, frozen at import time.</dd></dl>

### **Add a web page**

<dl>

<dt>**You are asking**</dt>
<dd>Make Calypso know this page.</dd>

<dt>**Endpoint**</dt>
<dd>POST /v1/buckets//pages</dd>

<dt>**Identity**</dt>
<dd>The normalized URL is the identity: one per team.</dd>

<dt>**Lifecycle**</dt>
<dd>A living page source, crawled and analyzed.</dd></dl>

Pick the wrong door and the API tells you: a file import that receives HTML returns url_is_web_page, a page ingestion that receives a document returns url_is_file. Both point at the other door; force: true overrides.

**How it works**

## Bucket first, then send, then wait for ready.

1. 01 ### **Provision the bucket**

   PUT /v1/buckets/ is idempotent: it creates the bucket or returns the one that exists. Scripts can call it on every run.
2. 02 ### **Send the source**

   One multipart call for a file, a direct-to-storage session for anything large, a JSON body for a URL, or a batch of up to 100 files.
3. 03 ### **Wait for ready**

   Finalize means durably accepted, not searchable. Poll GET /v1/sources/ until ready is true, then test retrieval.

**Readiness**

## Ready means searchable, not just uploaded.

An accepted upload is not yet an answerable source. The ready bit covers both indexing and bucket sync, so it is the only state a test needs.

1. 1 / 4 ### **Accepted**

   The bytes are stored and the request is durable. A 202 here is not retrieval readiness.
2. 2 / 4 ### **Indexed**

   The source has been read for its modality: text extracted, pages rendered, images described.
3. 3 / 4 ### **Bucket active**

   The bucket store that agents search has the source. bucket_sync_status shows the ladder if you need it.
4. 4 / 4 ### **Ready**

   ready: true. An agent bound to this bucket can retrieve and cite the source.

**From the docs**

## The numbers that matter.

| **Max file size** | 25 MB |
| --- | --- |
| **Files per batch** | 1 to 100, direct-to-storage sessions, one finalize |
| **Rate limit** | 5 create requests per second per team |
| **Metadata** | 8 KB per source, up to 20 tags |
| **Readiness check** | GET /v1/sources/{id} → ready: true |
| **Web page identity** | The normalized URL, one per team; a duplicate returns 409 with the existing source id |
| **Excel** | Not accepted. Export to CSV first. |

**Questions and answers**

## Before you upload.

**Keep reading**

[<h3>**Buckets **</h3>Scoped, durable source memory. Provision by slug, bind to agents.](https://www.calypso.so/context/buckets) [<h3>**Agents **</h3>One default, any number of named agents with their own scope and policy.](https://www.calypso.so/context/agents) [<h3>**Citations **</h3>A source on every answer: annotations by offset, a structured source list, native mode.](https://www.calypso.so/context/citations) [<h3>**Search **</h3>Retrieval without generation: the passages an answer would cite, ranked.](https://www.calypso.so/context/search) [<h3>**Privacy **</h3>Yours, isolated: no training on your data, export or delete any time, keys with explicit scopes.](https://www.calypso.so/context/privacy) [<h3>**Ingest in the docs **</h3>The reference this page is written from, with every endpoint and field.](https://docs.calypso.so/context/ingest)

**Start today**

## **Load your first bucket today.**

Create a project API key, upload a PDF, and ask a question that cites the page.

[**Start 14-day free trial**](https://context.calypso.so/join) [**Read the developer docs**](https://docs.calypso.so/context/ingest)