MaveraMavera Docs
Audiences
Checking…
Use or share this pageSend the page itself, print it, or open its complete context in your AI workspace.

Files & analysis

Upload files and mine them.

3 min readDocs build Updated Jul 26, 2026

Endpoints: POST /api/v1/files (upload), POST /api/v1/files/analyze, GET/DELETE /api/v1/files/{id}. Beta: files-api-2025-04-14.

Two different file paths — pick the right one.

  • Grounding a persona/audience (so they answer from your data): use import_file / import_folder. Those extract text and feed the grounding store — that's what shapes what a persona knows. This is the right path for "build an audience from these interviews."
  • Analyzing a file directly (summarize this PDF, run stats on this dataset, generate a chart): use the Files API on this page. This talks to Claude's beta Messages API with the file attached, optionally running Python over it.

The persona chat path grounds via extracted text, not raw file_ids — so "files in chat" means grounding (Connect), while "analyze this file and give me an output" means the Files API here.

The lifecycle

Upload

curl -X POST https://mavera-platform.vercel.app/api/v1/files \
  -H "x-api-key: $KEY" \
  -F "file=@quarterly-report.pdf"
# → { "ok": true, "data": { "file": {
#     "id": "file_011...", "filename": "quarterly-report.pdf",
#     "mimeType": "application/pdf", "sizeBytes": 1048576,
#     "downloadable": false, "createdAt": "2026-06-30T..." } } }

Multipart form-data, field name file. Max 500 MB per file; 500 GB per organization. Files are scoped to the API key's Anthropic workspace.

Stay attached & analyze

Reference one or more uploaded file_ids in an analysis turn. Claude reads them directly (PDF/text → document block, images → image block) and answers your prompt. Turn on withCodeExecution to let it compute over the files.

POST /api/v1/files/analyze
{
  "fileIds": [ { "id": "file_011...", "mimeType": "application/pdf" } ],
  "prompt": "Summarize the three biggest risks in this report and quote the supporting line for each.",
  "withCodeExecution": false
}
# → { "ok": true, "data": {
#     "text": "1. Customer concentration — \"our top 3 clients are 48% of revenue\"...",
#     "producedFiles": [],
#     "usage": { "inputTokens": 4210, "outputTokens": 380 } } }

The file stays attached for the whole turn — multi-part prompts, follow-up questions in the same request, and code execution all see the same uploaded bytes. No re-uploading per question.

Produce & download outputs

With withCodeExecution: true, Claude can run Python over your files and create new files (a chart, a cleaned CSV, a computed table). Those come back in producedFiles with downloadable: true — fetch them:

POST /api/v1/files/analyze
{ "fileIds": [ { "id": "file_data", "mimeType": "text/csv" } ],
  "prompt": "Plot monthly revenue as a line chart and save it as revenue.png.",
  "withCodeExecution": true }
# → data.producedFiles: [ { "id": "file_chart9", "filename": "revenue.png", "mimeType": "image/png", "downloadable": true } ]

# then download it:
curl "https://mavera-platform.vercel.app/api/v1/files/file_chart9?download=1" -H "x-api-key: $MAVERA_API_KEY" -o revenue.png

This also generates real Office documents. Ask for a .docx / .xlsx / .pptx and Claude builds it with python-docx / openpyxl / python-pptx in the container, then hands back a downloadable file — verified end-to-end (upload CSV → compute → Word doc → download a valid .docx):

POST /api/v1/files/analyze
{ "fileIds": [ { "id": "file_data", "mimeType": "text/csv" } ],
  "prompt": "Read the CSV and build a Word doc 'summary.docx' with a heading, the top region by revenue, and a table of all regions.",
  "withCodeExecution": true }
# → data.producedFiles: [ { "filename": "summary.docx", "mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "downloadable": true } ]

Edit existing documents (Word / PowerPoint / PDF / Excel)

Because every uploaded file is mounted into the code-execution container, Claude opens the actual file and edits it in place — preserving the parts you didn't touch — rather than regenerating it from scratch. Verified end-to-end: edit a real .pptx ("DRAFT"→"FINAL", add an "Approved" slide) and a real .pdf (flip the status line, append a sign-off), then download the revised file.

POST /api/v1/files/analyze
{ "fileIds": [ { "id": "file_deck", "mimeType": "application/vnd.openxmlformats-officedocument.presentationml.presentation" } ],
  "prompt": "Open this PowerPoint, change every 'DRAFT' to 'FINAL', add a closing slide titled 'Approved', and save as edited_deck.pptx.",
  "withCodeExecution": true }
# → data.producedFiles: [ { "filename": "edited_deck.pptx", "downloadable": true } ]   ← download with ?download=1

Tip: pass the right mimeType so the file lands in the container with a sensible extension — …presentationml.presentation for .pptx, …wordprocessingml.document for .docx, …spreadsheetml.sheet for .xlsx, application/pdf for .pdf.

Manage

GET    /api/v1/files            # list files in the workspace
GET    /api/v1/files/{id}       # metadata for one file
DELETE /api/v1/files/{id}       # delete a file

Critical behaviors (straight from Anthropic — no surprises)

RuleWhat it means for you
Uploaded files are NOT downloadableAn input you uploaded returns downloadable: false; ?download=1 on it returns 422 with a clear message. Only files Claude created via code execution can be downloaded.
500 MB / file, 500 GB / orgLarger uploads are rejected at the edge (422) before hitting Anthropic.
Workspace-scopedA file is visible to other API keys in the same Anthropic workspace. Keep that in mind for multi-tenant separation.
File-type → content blockPDF + plain text (text/plain, text/markdown) → document; images (jpeg/png/gif/webp) → image. CSV / XLSX / DOCX and other datasets are NOT native document blocks — note even text/csv is rejected as a document. With withCodeExecution: true the API mounts them into the container automatically via container_upload so Python can read them; otherwise use import_* to extract them to text.
Not eligible for Zero-Data-RetentionFiles are retained per Anthropic's standard policy. Don't upload anything that must never be retained.

Why the architecture is split this way (honest note)

The persona chat engine runs on the Vercel AI SDK's generateText, which doesn't carry Anthropic file_id references. So direct file analysis runs on Anthropic's beta Messages API (this page's endpoints) — separate from the chat path on purpose. That's the correct seam: a synthetic persona "knows" your data through grounding (extracted evidence), while file analysis (summarize, compute, chart) is an analyst capability that belongs on the beta client with code execution. We didn't bolt raw uploads onto the persona turn because that would conflate "what this person knows" with "what the analyst computed" — and blur the bright line.

Recipe: dataset → chart → download

# 1. upload a CSV
curl -X POST .../api/v1/files -H "x-api-key: $KEY" -F "file=@sales.csv"      # → file_data
# 2. analyze + plot (code execution on)
POST /api/v1/files/analyze
{ "fileIds":[{"id":"file_data","mimeType":"text/csv"}],
  "prompt":"Compute YoY growth per region and save a bar chart as growth.png.",
  "withCodeExecution":true }                                                  # → producedFiles:[growth.png]
# 3. download the chart
curl ".../api/v1/files/file_chart?download=1" -H "x-api-key: $KEY" -o growth.png

On this page