Help Center Agents Developer Help Developer API

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.