AgentFS

Uploads

Create and complete resumable multipart uploads.

Resumable uploads handle files up to 5,000,000,000,000 bytes (5 TB), and are required above 100 MiB. Files up to 5,000,000,000 bytes go up in one PUT unless you ask for parts. Larger files go up in at most 10,000 parts, each part_size bytes except the last.

The API keeps at most 64 active uploads for an organization. A session expires after 24 hours, or sooner when the file's expiration is sooner. An authenticated browser session can call these endpoints without an API key; an agent should send an API key.

Upload session shape

FieldTypeDescription
typestringAlways upload.
idstringUpload session ID.
file_idstringReserved file ID.
statusstringcreating, active, completing, completed, aborted, or failed.
transportstrings3: send the bytes to upload_url, or to the URLs from part URLs. worker: send parts to the API with upload a streamed part.
part_sizeintegerThe file size for a single-PUT session. Otherwise the required size of every non-final part; the final part can be smaller.
total_partsintegerNumber of parts calculated from expected_size_bytes and part_size.
expected_size_bytesintegerDeclared complete-file size.
uploaded_partsarrayRecorded parts, ordered by part_number.
uploaded_parts[].part_numberintegerPart number starting at 1.
uploaded_parts[].etagstringRecorded part entity tag.
uploaded_parts[].checksum_sha256string or nullRecorded direct-part SHA-256 checksum, when supplied.
uploaded_parts[].size_bytesintegerRecorded part size.
expires_atstringISO 8601 session expiration time.
upload_urlstringPresent on an active s3 session of at most 5,000,000,000 bytes: a signed URL that accepts one PUT of exactly expected_size_bytes bytes. Larger s3 sessions have no upload_url; fetch part URLs instead.
upload_url_expires_atstringISO 8601 time after which upload_url stops working. Fetch the session again for a fresh one.
fileobjectIncluded on a completed session; this is the file object.

upload_url is a capability: anyone holding it can write that one object until it expires. Do not log it.

Create an upload

POST /v1/uploads

Create a file record and a resumable upload session. Send an API key with write permission on the target path, or use an authenticated browser session.

Creating is safe to retry. If the response is lost, send the same request again: while the first session is still live, the same path, size_bytes and sha256 return that session with 200 instead of path_exists. A different size or hash for the same path is still a conflict.

Files up to 5,000,000,000 bytes get a session with upload_url: PUT the whole file there, then call complete. Larger files, and any file sent with multipart: true, go up in parts: follow the session's transport, then call complete. Every part is resumable on its own. If you get 503 upload_unavailable, retry shortly.

The url in the create response is where the file will live. An HTML, SVG, or XML file can move to the sandboxed host s.agentfsusercontent.com at completion, so share the url from the completed file object.

Request body

Send JSON.

FieldTypeRequiredDescription
pathstringYesproject/filename or a nested path. The path must include a project and filename.
size_bytesintegerYesPositive declared size, at most 5,000,000,000,000 bytes.
content_typestringNoTrimmed media type, 1–255 characters. If omitted, infer it from the filename. application/octet-stream is also replaced by filename inference.
sha256stringNoExpected SHA-256 digest of the whole file as 64 hexadecimal characters. Completion reads the stored bytes back to check it, so it is accepted only for uploads up to 1 GiB (1,073,741,824 bytes); a mismatch returns 422 checksum_mismatch.
visibilitystringNopublic, unlisted, or private.
expires_instring or nullNoDuration such as 24h or 7d using an s, m, h, d, or w suffix, or null. A string can be at most 52 weeks. When omitted, use the project's default expiration if one exists.
labelstring or nullNoOptional label, at most 200 characters.
content_dispositionstringNoinline or attachment. Defaults to inline.
multipartbooleanNoDefaults to false. true gives a multipart session at any size, with parts fetched through part URLs, so the upload can resume part by part. With false, files up to 5,000,000,000 bytes get one upload_url.

Paths use at most 16 segments and 2,048 encoded characters. Every segment may contain only letters, digits, ., _, and -.

Returns 201 Created.

Response fields

Returns an upload session. A new session has no uploaded_parts. A direct session may include direct; a streamed session does not.

Request

Request
curl -X POST https://agentfs.cloud/v1/uploads \
  -H "Authorization: Bearer $AGENTFS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "media/video.mp4",
    "size_bytes": 150000000,
    "content_type": "video/mp4",
    "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
    "visibility": "private",
    "expires_in": "7d",
    "label": "Demo video",
    "content_disposition": "attachment",
    "multipart": true
  }'

Response

201 Created
{
  "type": "upload",
  "id": "up_7c31",
  "file_id": "f_8f2c",
  "status": "active",
  "transport": "s3",
  "part_size": 16777216,
  "total_parts": 9,
  "expected_size_bytes": 150000000,
  "uploaded_parts": [],
  "expires_at": "2026-03-03T12:00:00.000Z"
}

Errors

unauthorized (401), invalid_agent_label (400), csrf_rejected (403), no_active_organization (403), invalid_upload (400), forbidden (403), path_exists (409), upload_rate_limited (429), storage_limit_exceeded (413), billing_unavailable (503), invalid_metadata (400), region_unavailable (422), project_create_failed (500), folder_create_failed (500), upload_unavailable (503), upload_create_failed (500 or 502), upload_not_found (404), upload_not_active (409), invalid_token (400), unknown_bucket (400), upload_failed (502), internal_error (500).

Get an upload

GET /v1/uploads/:id

Return the current session and its recorded parts. The API key must have write permission on the upload's file path.

Path parameters

ParameterTypeRequiredDescription
idstringYesUpload session ID.

An unfinished session that has expired is reported as not found. A completed session remains readable.

Response fields

Returns an upload session. Completed sessions also include file.

Returns 200 OK.

Request

Request
curl https://agentfs.cloud/v1/uploads/up_7c31 \
  -H "Authorization: Bearer $AGENTFS_KEY"

Response

200 OK
{
  "type": "upload",
  "id": "up_7c31",
  "file_id": "f_8f2c",
  "status": "active",
  "transport": "s3",
  "part_size": 16777216,
  "total_parts": 9,
  "expected_size_bytes": 150000000,
  "uploaded_parts": [
    {
      "part_number": 1,
      "etag": "etag-part-1",
      "checksum_sha256": null,
      "size_bytes": 16777216
    }
  ],
  "expires_at": "2026-03-03T12:00:00.000Z"
}

Errors

unauthorized (401), no_active_organization (403), invalid_agent_label (400), upload_not_found (404), forbidden (403), internal_error (500).

Get part URLs

GET /v1/uploads/:id/part-urls?from=1&to=100

Signed PUT URLs for the parts of a multipart s3 session, at most 100 per call. Each URL accepts exactly size_bytes bytes for its part and expires at expires_at; an expired URL answers 403, so fetch again for fresh ones. Parts can be sent in parallel. Storage answers each part with an ETag; you do not need to send it back, completion reads the parts from storage.

200 OK
{
  "upload_id": "up_7c31",
  "part_size": 16777216,
  "total_parts": 9,
  "parts": [
    { "part_number": 1, "size_bytes": 16777216, "url": "https://<part_url>", "expires_at": "2026-03-02T17:55:00.000Z" }
  ]
}

Errors: upload_not_found (404), upload_not_active (409) for a session without part URLs, invalid_part (400), upload_expired (410), upload_unavailable (503).

Upload a streamed part

PUT /v1/uploads/:id/parts/:part

Send one binary part to a worker session. The API key must have write permission on the file path. An s3 session refuses parts with 409 upload_not_active; send its bytes to upload_url instead.

Non-final parts must be exactly part_size bytes. The final part must be exactly the remaining bytes of expected_size_bytes. Send the exact byte count in Content-Length; any other size is a 400 invalid_part. Sending the same part number again replaces its recorded part.

Path parameters

ParameterTypeRequiredDescription
idstringYesUpload session ID.
partintegerYesPositive part number, starting at 1 and no greater than total_parts.

Request body

Send the raw binary bytes. Content-Length is required.

Response fields

FieldTypeDescription
part_numberintegerStored part number.
etagstringEntity tag returned for the part.
size_bytesintegerStored part size.

Returns 200 OK.

Request

Request
curl -X PUT https://agentfs.cloud/v1/uploads/up_7c31/parts/1 \
  -H "Authorization: Bearer $AGENTFS_KEY" \
  -H "Content-Length: $PART_SIZE" \
  --data-binary @part-001.bin

Response

200 OK
{
  "part_number": 1,
  "etag": "etag-part-1",
  "size_bytes": 16777216
}

Errors

unauthorized (401), csrf_rejected (403), no_active_organization (403), invalid_agent_label (400), invalid_part (400), upload_not_found (404), upload_not_active (409), upload_expired (410), forbidden (403), length_required (411), upload_unavailable (503), invalid_token (400), unknown_bucket (400), part_upload_failed (502), upload_failed (502), internal_error (500).

Complete an upload

POST /v1/uploads/:id/complete

Verify every part and mark the file ready. The API key must have write permission on the file path. A single-PUT s3 session without sha256 completes on its own a few seconds after its bytes arrive; calling this endpoint just finishes it sooner.

For a worker or multipart s3 session the server requires contiguous part numbers from 1 through total_parts and an exact sum of part sizes. For a single-PUT s3 session it checks that the object at upload_url has arrived with exactly expected_size_bytes bytes, and verifies sha256 when one was declared; 409 object_not_ready means the bytes are not there yet. A retry after completion returns the file object again. 502 upload_complete_failed means storage could not assemble the parts; it is safe to retry, and if storage already finished, the retry succeeds.

Path parameters

ParameterTypeRequiredDescription
idstringYesUpload session ID.

Response fields

On success, return a file object with 200 OK. During a concurrent completion, return the upload session with 202 Accepted while the session remains completing.

Request

Request
curl -X POST https://agentfs.cloud/v1/uploads/up_7c31/complete \
  -H "Authorization: Bearer $AGENTFS_KEY"

Response

200 OK
{
  "type": "file",
  "id": "f_8f2c",
  "name": "video.mp4",
  "path": "media/video.mp4",
  "label": "Demo video",
  "content_type": "video/mp4",
  "content_disposition": "attachment",
  "size_bytes": 150000000,
  "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  "etag": "etag-video",
  "revision": 1,
  "visibility": "private",
  "expires_at": "2026-03-09T12:00:00.000Z",
  "tags": [],
  "metadata": {},
  "agent_id": null,
  "run_id": null,
  "url": null,
  "markdown": null,
  "created_at": "2026-03-02T12:00:00.000Z",
  "updated_at": "2026-03-02T12:03:00.000Z"
}

Errors

unauthorized (401), csrf_rejected (403), no_active_organization (403), invalid_agent_label (400), upload_not_found (404), forbidden (403), upload_not_active (409), upload_expired (410), missing_parts (409), size_mismatch (409 or 422), checksum_missing (409), checksum_mismatch (422), upload_not_pending (409), object_not_ready (409), upload_unavailable (503), invalid_token (400), unknown_bucket (400), upload_complete_failed (502), upload_finalize_failed (502), upload_failed (502), internal_error (500).

Abort an upload

DELETE /v1/uploads/:id

Abort an unfinished session and remove its reserved file. The API key must have delete permission on the file path.

An unknown session is treated as already aborted and returns 204. A completed session cannot be aborted.

Path parameters

ParameterTypeRequiredDescription
idstringYesUpload session ID.

Response

Returns 204 No Content with an empty body.

204 No Content
HTTP/1.1 204 No Content

Request

Request
curl -X DELETE https://agentfs.cloud/v1/uploads/up_7c31 \
  -H "Authorization: Bearer $AGENTFS_KEY"

Errors

unauthorized (401), csrf_rejected (403), no_active_organization (403), invalid_agent_label (400), forbidden (403), upload_completed (409), upload_abort_unavailable (503), upload_abort_failed (502), upload_unavailable (503), invalid_token (400), upload_failed (502), internal_error (500).

On this page