The Files API — upload, attach, manage

Availability: All plans. Uploads up to 50 MB per file.

The Files API is how you give your agent something to read: upload a document or image, get back a file_id, and pass that ID in a streaming call. Every response also tells you whether the file is LLM-compatible — readable by the agent's current model — so you can catch a mismatch at upload time instead of mid-conversation.

All endpoints live under https://api.agentman.ai/v3/files and use the standard agent-token auth:

Authorization: Bearer <AGENT_TOKEN>

Upload a file

POST /v3/files/upload?conversation_id=<id>&expires_in_hours=24

Multipart form with a single file field:

curl -X POST "https://api.agentman.ai/v3/files/upload?conversation_id=$CONV_ID" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -F "file=@quarterly-report.pdf"
Query param Default Description
conversation_id — Optional; links the file to a conversation.
expires_in_hours 24 How long the file is retained.

Rules enforced at upload:

  • Max size: 50 MB.
  • Allowed extensions: .pdf .png .jpg .jpeg .gif .txt .md .docx .xlsx .csv .json .xml .html. Anything else is rejected with a 400.

Response:

{
  "file_id": "f_8c2e…",
  "url": "https://storage.googleapis.com/…(presigned)",
  "metadata": {
    "filename": "quarterly-report.pdf",
    "mime_type": "application/pdf",
    "size_bytes": 482113,
    "uploaded_at": "2026-07-13T10:22:41",
    "expires_at": "2026-07-14T10:22:41",
    "agent_id": "1042",
    "conversation_id": "3f6f9f0a-…"
  },
  "validation": {
    "llm_compatible": true,
    "model_name": "gpt-4o",
    "accessible": true,
    "notes": ["Compatible with gpt-4o"]
  }
}

If validation.llm_compatible is false, the upload still succeeded — but the agent's current model can't read this MIME type, and notes lists what it does support. Check /v3/agent/capabilities up front to avoid this.

Attach it to a conversation

Pass the ID in your next streaming call — that's the whole integration:

{
  "user_input": "Summarize the attached report.",
  "conversation_id": "3f6f9f0a-…",
  "attachment_file_ids": ["f_8c2e…"]
}

(attachment_urls works too, for files hosted elsewhere — the URL must be fetchable by the platform.)

Get metadata

GET /v3/files/{file_id}

Returns the same shape as the upload metadata plus a current validation block — including whether the file has expired (validation.notes will say so, and llm_compatible flips to false once it has).

Download the bytes

GET /v3/files/{file_id}/download

Streams the raw file content back. Use this server-side; for handing a link to a browser, mint a presigned URL instead.

Mint a fresh presigned URL

POST /v3/files/{file_id}/url?expires_in_minutes=60
{
  "file_id": "f_8c2e…",
  "url": "https://storage.googleapis.com/…",
  "expires_at": "2026-07-13T11:22:41",
  "expires_in_minutes": 60
}

Presigned URLs expire independently of the file itself (default 60 minutes). The url returned by upload/metadata responses is also presigned — if one has gone stale, mint a new one here rather than re-uploading.

Validate end-to-end

GET /v3/files/validate/{file_id}

The debugging endpoint: it checks metadata, mints a short-lived URL, and actually tests that the URL is fetchable, returning accessible, llm_compatible, per-check details, and recommendations. If an attachment "isn't working" in a conversation, call this first — it pinpoints whether the problem is expiry, accessibility, or model compatibility.

List your files

GET /v3/files?limit=50&offset=0
{
  "files": [
    {
      "file_id": "f_8c2e…",
      "filename": "quarterly-report.pdf",
      "mime_type": "application/pdf",
      "size_bytes": 482113,
      "uploaded_at": "2026-07-13T10:22:41",
      "expires_at": "2026-07-14T10:22:41",
      "url": "https://…",
      "llm_compatible": true,
      "status": "ready"
    }
  ],
  "pagination": { "limit": 50, "offset": 0, "total": 3, "has_more": false },
  "agent_info": { "agent_id": "1042", "model_name": "gpt-4o" }
}

Files are scoped to the agent behind your token — one agent's token never sees another agent's files.

Lifecycle in one picture

  1. Upload → get file_id (+ compatibility verdict).
  2. Attach file_id in /v3/agent/stream calls until the file expires (expires_in_hours, default 24).
  3. Re-mint URLs as needed for direct access; validate when something looks wrong.
  4. After expiry, upload again — expired files stop being accessible to the agent.

Availability

All plans. Uploads up to 50 MB per file.

Build an agent, then call it from your code

Create an agent in a free workspace and reach it over the Runtime API with an agent token.