Upload a file
uploadFile
PUT /api/v1/shares/{share_id}/files
files.writeRate cost: 5Upload a new file: the request body is the file
The bytes stream to the share as they arrive, at any size; Content-Length is required, so a share without room refuses before the first byte. New files only, said as HTTP says it: send If-None-Match: * (required, 428 without it). Something already called that is never replaced: the default answers 412 precondition-failed; on_conflict=rename picks the first free name instead, so read the answer’s path (and Location). If-Match names a file to replace, which this operation never does: sending it is refused (400); replace a file with overwriteFile. A person may have only a few uploads in flight through your app at once (429 with Retry-After beyond that). On a share that offers it, an upload session (createUploadSession) sends the bytes straight to the storage instead. Send an Idempotency-Key: the same upload sent again with it (the same path, query and bytes) answers the first answer and writes nothing; other bytes under the same key are refused (422).
Request
Section titled “Request”curl -X PUT "$FOLDR/api/v1/shares/$SHARE_ID/files?path=%2FReports%2Fq3.pdf" \ -H "Authorization: Bearer $TOKEN" \ -H "If-None-Match: *" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/octet-stream" \ --data-binary @./file$FOLDR is your site’s address (for example https://files.example.com) and $TOKEN is an access token. See Getting access.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
share_id | path | string | Yes | The share’s id. |
path | query | string | Yes | The new file’s full path in the share, its name last. The folder it goes in must exist. |
on_conflict | query | string, one of fail, rename | No | What to do when something is already called that: “fail” (the default) or “rename”. Nothing is ever replaced. |
If-None-Match | header | string | Yes | ”*”: create only, never replace (RFC 9110). Required; no other value is taken. |
Idempotency-Key | header | string | Yes | A value of your own, 1 to 255 visible ASCII characters, new for each new upload. Sending the same upload again (the same path, query and bytes) with the same key within 24 hours answers the first answer and writes nothing (the body is read again, to be sure it is the same); with a different request, other bytes included, it is refused (422). |
Request body
Section titled “Request body”The file’s bytes, exactly Content-Length of them.
application/octet-stream, required: string (binary)
Responses
Section titled “Responses”| Status | Meaning | Body |
|---|---|---|
| 201 | The file, at its canonical path. | application/json: Item |
201 response
Section titled “201 response”| Header | Description |
|---|---|
ETag | The entity tag of what was answered. Send it back as If-None-Match for a 304 while it is unchanged, or as If-Match to change it only while it is unchanged. |
Location | Where to read what was made. |
Item:
| Field | Type | Description |
|---|---|---|
share_id | string (uuid) | Required. The id of the share the item is in. |
path | string | Required. The canonical path: as the storage holds it (its case), Unicode NFC, always starting with ”/”. ”/” is the top of the share. Send this form back in later calls. |
name | string | Required. The item’s name (the last segment of its path; the share’s name for the top). |
kind | string, one of file, folder | Required. file or folder. |
size | integer or null | Required. Size in bytes; null for a folder, and null when the item has no fixed byte size (a native Google document, exported on download: see export). |
modified | string or null (date-time) | Required. Last modified (RFC 3339, UTC), where the storage reports it. |
mime_type | string or null | Required. The item’s own media type, as the storage reports it or guessed from the name; null for a folder. A native Google document has Google’s own type here (application/vnd.google-apps.document for a Doc); export says what it downloads as. |
export | Export or null | Required. For a native Google document that can be downloaded, what content delivers: its media type and the extension the download is named with. Null for everything else, including a native Google type that cannot be downloaded (a Form: content answers 409 not-downloadable). |
etag | string or null | Required. The item’s entity tag: the storage’s own where it has one, else a weak tag over size and modified time (over modified time alone for a native Google document, whose export is made afresh each time). Null on a search hit, which comes from the index; GET …/item for the live one. |
read_only | boolean | Required. True when the person cannot change things in this share. |
checked_out | Checkout or null | Required. Who has the item checked out, or null. Null on a search hit. |
Example:
{ "share_id": "0191f2c4-8a1e-7b52-9d3a-5c1e0b7a4d21", "path": "string", "name": "string", "kind": "file", "size": 1, "modified": "2026-11-04T09:30:00Z", "mime_type": "string", "export": { "mime_type": "string", "extension": "string" }, "etag": "string", "read_only": false, "checked_out": { "by": {}, "since": "2026-11-04T09:30:00Z" }}Errors
Section titled “Errors”Every error is an application/problem+json document (ProblemDetails); branch on its type or code. See Errors.
| Status | Problem types | When |
|---|---|---|
| 400 | invalid-pathinvalid-request | One of: Invalid path (invalid-path); Invalid request (invalid-request). |
| 401 | invalid-token | Invalid token (invalid-token). |
| 403 | insufficient-scopewrite-not-allowed | One of: Insufficient scope (insufficient-scope); Not allowed for this app (write-not-allowed). |
| 404 | not-found | Not found (not-found). |
| 409 | ambiguous-pathconflictnot-a-folderstorage-account-not-connected | One of: Ambiguous path (ambiguous-path); Conflict (conflict); Not a folder (not-a-folder); Storage account not connected (storage-account-not-connected). |
| 412 | precondition-failed | Precondition failed (precondition-failed). |
| 413 | too-large | Too large (too-large). |
| 422 | idempotency-key-reused | Idempotency key reused (idempotency-key-reused). |
| 428 | precondition-required | Precondition required (precondition-required). |
| 429 | daily-write-limitrate-limited | One of: Daily write limit reached (daily-write-limit); Too many requests (rate-limited). |
| 500 | internal-error | Internal error (internal-error). |
| 503 | share-unavailableshare-unreachablewrite-failed | One of: Share unavailable (share-unavailable); Share unreachable (share-unreachable); Write failed (write-failed). |