Ingest

Files

Upload one file into a bucket: a one-call multipart upload for the simple case, and direct-to-storage upload sessions for large files.

What Context can read

A file is accepted if its MIME type or extension resolves to one of these. Anything else is rejected at upload rather than silently indexed as junk.

FamilyTypesModalityCitations point at
Documents.pdfMultimodal — text and page imagesThe page
.docxTextThe document
Text.md, .txt, and other text/*TextThe document
Data.csv, .jsonTextThe document
Code.py, .ts, .tsx, .js, .jsx, .java, .go, .rs, .sql, .html, .css, .scss, .yml, .yaml, .toml, .ini, .env, .shTextThe document
Images.png, .jpg, .jpegImage — read for content, not filenameThe image

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. Images are indexed for what they depict, so a product photo answers a question about the product.

Excel files are not accepted..xlsx does not resolve to a supported type — export the sheet to .csv before uploading. Google Sheets is a separate integration for writing rows back out, not a knowledge source.

Two paths, one destination

PathWhen
One-call uploadPOST /v1/buckets/{bucket}/filesYour file is on hand. The simple case, made simple.
Upload sessionPOST /v1/buckets/{bucket}/uploadsBrowser-direct uploads, or retry-safe pipelines that want resumable storage uploads.

Both land the file in the path bucket, queue indexing, and converge on the same source object with the same ready bit. The 25 MB per-file cap applies to both — a session buys resumability, not headroom, and a session create declaring a size_bytes over the cap is rejected up front with 413 file_too_large.

One-call upload

curl -X POST "https://api.calypso.so/v1/buckets/support-handbook/files" \
  -H "Authorization: Bearer sk-..." \
  -H "Idempotency-Key: crm-doc-123" \
  -F "file=@/path/to/contract.pdf" \
  -F "title=Customer Contract" \
  -F "tags=legal,customer"

Multipart form fields: file (required), title, tags (comma-separated), metadata (JSON string). The response returns the source id and indexing task; poll GET /v1/sources/{id} until ready: true.

Upload sessions

The session flow uploads bytes directly to storage, keeping your API calls small and letting an interrupted transfer resume:

  1. Create the session:
POST /v1/buckets/{bucket}/uploads
Authorization: Bearer sk-...
Idempotency-Key: your-stable-upload-key
{
  "filename": "contract.pdf",
  "content_type": "application/pdf",
  "size_bytes": 184233,
  "title": "Customer Contract",
  "tags": ["legal", "customer"]
}
{
  "session_id": "sess_123",
  "upload_strategy": "gcs_resumable",
  "upload_url": "https://storage.googleapis.com/...",
  "expires_at": "2026-06-08T21:00:00Z",
  "request_id": "req_current"
}

Treat upload_url as a short-lived bearer capability — do not log it or store it durably.

  1. Upload the bytes directly to the returned URL:
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/pdf" \
  -H "Content-Range: bytes 0-184232/184233" \
  --data-binary @/absolute/path/to/contract.pdf
  1. Finalize:
curl -X POST "https://api.calypso.so/v1/buckets/support-handbook/uploads/$SESSION_ID/finalize" \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{}'

The finalize response returns the source id and indexing task id. queued means accepted — not yet retrievable.

The body-addressed aliases remain: POST /v1/knowledge/files/upload-session (+ /finalize) with bucket_ids / bucket_slugs / bucket fields in the body. Same implementation, permanent alias.

Waiting for readiness

GET /v1/sources/{id}

Wait for ready: true before testing retrieval. For deeper debugging: status, task, bucket_sync_status, and the provider-truth check GET /v1/sources/{id}?verify=gemini — the gemini object shows the live document state in the search index (STATE_ACTIVE, STATE_PENDING, STATE_FAILED).

Limits

  • Max file size: 25 MB, on both paths.
  • Rate limit: 5 create requests per second per team.
  • Metadata max: 8 KB. Tags max: 20.

Best practices

  • Use stable Idempotency-Key values for automated retries.
  • Store your upstream source id in metadata.
  • Provision buckets explicitly with PUT /v1/buckets/{slug} (Manage → Buckets) rather than relying on implicit creation during uploads.

Next: