Skip to content

Copy a file or folder

copyItem

POST /api/v1/shares/{share_id}/copy

Scope: files.writeRate cost: 2

Copy a file or a folder, within its share or into another of the person’s shares

to_path is the copy’s full path; the folder it goes in must exist. Something already called that is never replaced (on_conflict “fail” answers 409, “rename” picks the first free name); a folder copy is a new folder, never merged into one already there. Both shares must be ones your app may change. The original is not touched. A copy into another share is refused when a label on the file stops it being downloaded. A small file is copied in the request and answered 201 with the copy. A folder, a file whose source or destination is in Microsoft 365, a file over 64 MiB going between storages or over 1 GiB within one, or any copy sent with Prefer: respond-async, is copied by Foldr afterwards: answered 202 with an operation, its Location the address to poll (getOperation) until it answers 200 with the copy or the problem the copy ended with. A folder copy takes at most 10,000 files and folders, nested at most 64 deep (413 copy-too-large); a person may have at most 20 copies waiting through one app (429), and 2 run at once. Send an Idempotency-Key: the same request sent again with it answers the first answer (the same operation) and copies nothing more; after 24 hours, an operation still under way is answered 202 again, and one that has finished its final answer: 201 with the copy, or the problem it ended with, carrying the operation.

Terminal window
curl -X POST "$FOLDR/api/v1/shares/$SHARE_ID/copy" \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"path":"string","to_share":"0191f2c4-8a1e-7b52-9d3a-5c1e0b7a4d21","to_path":"string"}'

$FOLDR is your site’s address (for example https://files.example.com) and $TOKEN is an access token. See Getting access.

NameInTypeRequiredDescription
share_idpathstringYesThe id of the share the file or folder is in.
Idempotency-KeyheaderstringYesA value of your own, 1 to 255 visible ASCII characters, new for each new request. The same key with the same request within 24 hours answers the first answer again (for a copy made afterwards, the same operation) and copies nothing more; later, the operation as it stands (202 while under way, its final answer once finished); with a different request it is refused (422).
PreferheaderstringNorespond-async: copy afterwards and answer 202 with an operation, whatever the size (Preference-Applied says it was). Without it, small files are copied in the request.

application/json, required: CopyBody

FieldTypeDescription
pathstringRequired. The path of the file to copy (files only).
to_sharestring (uuid)Required. The id of the share the copy goes in: this share or another of the person’s.
to_pathstringRequired. The copy’s full path in that share, its name last. The folder it goes in must exist.
on_conflictstring, one of fail, renameWhat to do when something is already called that: “fail” (the default) answers 409 conflict; “rename” gives the copy the first free name (“Q3 copy.xlsx”). Nothing is ever replaced.

Example:

{
"path": "string",
"to_share": "0191f2c4-8a1e-7b52-9d3a-5c1e0b7a4d21",
"to_path": "string"
}
StatusMeaningBody
201The copy, at its canonical path.application/json: Item
202The copy will be made by Foldr: the operation. Poll its Location after Retry-After seconds.application/json: Operation
HeaderDescription
ETagThe 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.
LocationWhere to read what was made.

Item:

FieldTypeDescription
share_idstring (uuid)Required. The id of the share the item is in.
pathstringRequired. 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.
namestringRequired. The item’s name (the last segment of its path; the share’s name for the top).
kindstring, one of file, folderRequired. file or folder.
sizeinteger or nullRequired. 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).
modifiedstring or null (date-time)Required. Last modified (RFC 3339, UTC), where the storage reports it.
mime_typestring or nullRequired. 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.
exportExport or nullRequired. 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).
etagstring or nullRequired. 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_onlybooleanRequired. True when the person cannot change things in this share.
checked_outCheckout or nullRequired. 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"
}
}
HeaderDescription
LocationWhere to poll the operation: GET it until it answers anything but 202.
Preference-Appliedrespond-async: sent when the request’s Prefer: respond-async is why this is an operation rather than an answer in the request (RFC 7240). Absent when Foldr chose the operation itself (a folder, a large file, Microsoft 365).
Retry-AfterSeconds to wait before polling again.

Operation:

FieldTypeDescription
idstring (uuid)Required. The operation’s id.
kindstringRequired. What it does: copy, move (to another share, or held for approval within one), delete or restore (a version restore). delete and restore are only ever operations held for approval. Known values: copy, move, delete, restore. Clients must accept values not listed here.
statestring, one of pending_approval, queued, running, cancelling, succeeded, failed, cancelled, declined, expiredRequired. Where it has got to. pending_approval: held for an approver, nothing changed yet (approval says until when); queued: waiting to start; running: under way; cancelling: asked to stop, stopping at its next item; succeeded: done, result is what was made; failed: ended with the problem getOperation answers; cancelled: stopped, and what it had made removed (or, held for approval, withdrawn, nothing changed); declined: an approver said no, nothing changed; expired: nobody approved it in time, nothing changed.
phasestring or nullRequired. A move’s phase: copying (every item is copied first; nothing has been removed from where it was, and a cancel removes the partial copy), then deleting (the copy is whole and proven, and the originals are being removed: too late to cancel). Null for a copy. Known values: copying, deleting. Clients must accept values not listed here.
created_atstring (date-time)Required. When it was asked for (RFC 3339, UTC).
started_atstring or null (date-time)Required. When a worker first started it; null while queued.
finished_atstring or null (date-time)Required. When it finished; null until then.
sourceOperationSourceRequired. What is being copied, moved, deleted or restored.
targetOperationTarget or nullRequired. Where it was asked to go: the path asked for. result.path is where it landed (on_conflict “rename” may have given it another name). Null for a delete or a restore.
version_idstring or nullRequired. For a restore: the version asked for (one of listVersions’ ids). Null otherwise.
progressOperationProgressRequired. How far it has got.
resultItem or nullRequired. Once it has succeeded, what it made (the copy, the moved item at its new place, the restored file), at its canonical path; null until then, and for a delete (see deletion). A move that ended source-remains also has it: the whole copy it made.
deletionDeletion or nullRequired. A delete held for approval, once it has succeeded: what was deleted and where its storage keeps it now, as deleteItem answers. Null otherwise.
approvalOperationApproval or nullRequired. For an operation held for an approver: how its approval stands. Null for one that never waited for approval.
failuresarray of OperationFailureRequired. At most 100 items (failures_truncated says when there were more): for a copy that ended copy-incomplete, those it could not copy; for a move that ended source-remains, those still at the source. Empty otherwise.
failures_truncatedbooleanRequired. True when more items failed than failures lists.

Example:

{
"id": "0191f2c4-8a1e-7b52-9d3a-5c1e0b7a4d21",
"kind": "string",
"state": "pending_approval",
"phase": "string",
"created_at": "2026-11-04T09:30:00Z",
"started_at": "2026-11-04T09:30:00Z",
"finished_at": "2026-11-04T09:30:00Z",
"source": {
"share_id": "0191f2c4-8a1e-7b52-9d3a-5c1e0b7a4d21",
"path": "string",
"kind": "file"
},
"target": {
"share_id": "0191f2c4-8a1e-7b52-9d3a-5c1e0b7a4d21",
"path": "string"
},
"version_id": "string",
"progress": {
"items_done": 1,
"items_total": 1,
"bytes_done": 1,
"bytes_total": 1
},
"result": {
"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"
}
},
"deletion": {
"deleted": {},
"items": 1,
"recoverable": "bin",
"destination": "string",
"where": "string"
},
"approval": {
"status": "string",
"expires_at": "2026-11-04T09:30:00Z",
"decided_at": "2026-11-04T09:30:00Z"
},
"failures": [
{
"path": "string",
"code": "string"
}
],
"failures_truncated": false
}

Every error is an application/problem+json document (ProblemDetails); branch on its type or code. See Errors.

StatusProblem typesWhen
400copy-into-itself
invalid-path
invalid-request
One of: Copy into itself (copy-into-itself); Invalid path (invalid-path); Invalid request (invalid-request).
401invalid-tokenInvalid token (invalid-token).
403download-blocked
insufficient-scope
write-not-allowed
One of: Download blocked (download-blocked); Insufficient scope (insufficient-scope); Not allowed for this app (write-not-allowed).
404not-foundNot found (not-found).
409ambiguous-path
approved-version-unavailable
conflict
copy-incomplete
not-a-file
not-a-folder
operation-cancelled
storage-account-not-connected
One of: Ambiguous path (ambiguous-path); Approved version unavailable (approved-version-unavailable); Conflict (conflict); Copy incomplete (copy-incomplete); Not a file (not-a-file); Not a folder (not-a-folder); Operation cancelled (operation-cancelled); Storage account not connected (storage-account-not-connected).
413copy-too-large
too-large
One of: Copy too large (copy-too-large); Too large (too-large).
422idempotency-key-reusedIdempotency key reused (idempotency-key-reused).
429daily-write-limit
rate-limited
One of: Daily write limit reached (daily-write-limit); Too many requests (rate-limited).
500internal-errorInternal error (internal-error).
503copy-interrupted
share-unavailable
share-unreachable
write-failed
One of: Copy interrupted (copy-interrupted); Share unavailable (share-unavailable); Share unreachable (share-unreachable); Write failed (write-failed).