API

Transfers.

A ticket lets farwing cp move bytes on the data port. HTTPS upload and download are for callers that cannot open that port. The transfer list is the record of both.

See the API reference for the key, errors, and paging.

HTTPS upload and download

GET /api/v1/files/download

Download one file over HTTPS, as an attachment. Honors a single Range: bytes=A- or bytes=A-B, so an interrupted download can carry on. Counts as a transfer against the license's limits.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
rootquerystringoptionalThe location, for a caller that still names storage directly.
pathquerystringrequiredThe file, relative to the storage location.
spacequerystringoptionalThe space, when path is relative to one.

Encode the query value. A slash in a path may stay as / or be written %2F; the server reads the decoded value. Do not put a leading slash on the path.

Success. 200.

JSON object.

A Range request that the server can satisfy answers 206 with that part of the file.

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestthe path is a folder
404not_foundno such file, or this caller may not see it
416the range starts past the end of the file
503unavailablebusy: every transfer the license allows at once is running; ask again after Retry-After
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "the path is a folder"
  }
}

POST /api/v1/uploads

Begin an upload over HTTPS.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Send {root, path, size, fingerprint}; the reply has the upload's id, how many bytes have received, and chunkBytes, the most one piece may carry. Starting again with the same destination, size and fingerprint carries on from received.

Request body. JSON.

A field the server does not know is refused with 400.

FieldTypeMeaning
rootstringoptionalThe location, for a caller that still names storage directly.
spacestringoptionalThe space, when path is relative to one.
pathstringrequiredWhere the file will land, relative to the location or the space.
sizeintegerrequiredSize in bytes.
fingerprintstringoptionalAnything the client can work out again for the same file; its name, size and modification time will do. Starting again with the same one carries on rather than colliding with the upload already open.
{
  "space": "k7Qm2sLp9vX4aB1c",
  "path": "projects/rush",
  "size": 1048576,
  "fingerprint": "example"
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
rootstringrequired
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
sizeintegerrequiredSize in bytes.
receivedintegerrequiredBytes safely written. The next piece starts here.
chunkBytesintegerrequiredThe most one piece may carry.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "root": "k7Qm2sLp9vX4aB1c",
  "path": "projects/rush",
  "size": 1048576,
  "received": 1,
  "chunkBytes": 1
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestthe path is not valid
404not_foundno such storage location, or this caller may not write there
409conflictsomething is already there, or another upload to that name is under way
503unavailablebusy: every transfer the license allows at once is running; ask again after Retry-After
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "the path is not valid"
  }
}
Send the same root or space, path, size and fingerprint to continue an upload that already started. offset on each piece must equal received.

GET /api/v1/uploads/{id}

Where an upload has got to.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
rootstringrequired
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
sizeintegerrequiredSize in bytes.
receivedintegerrequiredBytes safely written. The next piece starts here.
chunkBytesintegerrequiredThe most one piece may carry.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "root": "k7Qm2sLp9vX4aB1c",
  "path": "projects/rush",
  "size": 1048576,
  "received": 1,
  "chunkBytes": 1
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

DELETE /api/v1/uploads/{id}

Cancel it. Nothing is published.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

The reply has no body.

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

PUT /api/v1/uploads/{id}/data

The next piece of an upload, as the raw request body. offset must equal the bytes received so far.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe upload's id.
offsetqueryintegerrequiredWhere this piece starts.

Request body. The raw bytes of the piece. Not JSON.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
rootstringrequired
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
sizeintegerrequiredSize in bytes.
receivedintegerrequiredBytes safely written. The next piece starts here.
chunkBytesintegerrequiredThe most one piece may carry.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "root": "k7Qm2sLp9vX4aB1c",
  "path": "projects/rush",
  "size": 1048576,
  "received": 1,
  "chunkBytes": 1
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestthe piece is empty, too large, or runs past the size given at the start
404not_foundno such upload for this caller
409conflictthe offset is not where the upload has got to, or it was paused or canceled from the Transfers page
503unavailablebusy: every transfer the license allows at once is running; ask again after Retry-After
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "the piece is empty, too large, or runs past the size given at the start"
  }
}

POST /api/v1/uploads/{id}/finish

Publish the file under its name, once every byte has arrived.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

FieldTypeMeaning
namestringrequiredThe name.
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
kindstringrequired
sizeintegerrequiredSize in bytes.
modifiedstringoptional, left out when empty
{
  "name": "Rush delivery",
  "path": "projects/rush",
  "kind": "file",
  "size": 1048576,
  "modified": "example"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestbytes are still missing
409conflictsomething else arrived at that name meanwhile; nothing was replaced
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "bytes are still missing"
  }
}

Parallel uploads

POST /api/v1/uploads/parallel

Begin an upload whose parts may travel at the same time and arrive in any order.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

partBytes is a preference: it is clamped to 16 to 128 MiB, rounded to a whole mebibyte, and raised if the file would need more than 10,000 parts. Starting again with the same destination, size and fingerprint carries on with the parts already there, after a restart too. The upload takes one of the places the license allows at once, however many parts it has in flight.

Send {root, path, size, partBytes, fingerprint}; the reply has the upload's id, the partBytes it will use, which parts have landed, the bytes received, and maxInFlight, how many parts may be sent at once.

Request body. JSON.

A field the server does not know is refused with 400.

FieldTypeMeaning
rootstringrequired
pathstringrequiredWhere the file will land, relative to the storage location.
sizeintegerrequiredSize in bytes.
partBytesintegeroptionalThe part size the client would like. Clamped, never trusted.
fingerprintstringoptionalAnything the client can work out again for the same file. Starting again with the same one carries on rather than colliding with the upload already open.
{
  "root": "k7Qm2sLp9vX4aB1c",
  "path": "projects/rush",
  "size": 1048576,
  "partBytes": 1,
  "fingerprint": "example"
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
partBytesintegerrequired
partsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
indexintegerrequired
bytesintegerrequiredSize in bytes.
receivedbooleanrequired
checksumstringoptionalThe checksum the server verified, once the part has landed.
receivedintegerrequiredBytes safely on disk, over all the parts that have landed.
maxInFlightintegerrequiredThe most parts to have on their way at once.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "partBytes": 1,
  "parts": [
    {
      "index": 1,
      "bytes": 1048576,
      "received": true,
      "checksum": "example"
    }
  ],
  "received": 1,
  "maxInFlight": 1
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestthe path is not valid, or the file is too large even for the largest part
404not_foundno such storage location, or this caller may not write there
409conflictanother upload to that name is already open
503unavailablebusy: every transfer the license allows at once is running; ask again after Retry-After
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "the path is not valid, or the file is too large even for the largest part"
  }
}
Parts may arrive in any order. partBytes is clamped to between 16 and 128 MiB. Sending a part again replaces it. The whole file's BLAKE3 hash is checked when you finish.

GET /api/v1/uploads/parallel/{id}

Which parts of a parallel upload have landed, and how many bytes that is.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
partBytesintegerrequired
partsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
indexintegerrequired
bytesintegerrequiredSize in bytes.
receivedbooleanrequired
checksumstringoptionalThe checksum the server verified, once the part has landed.
receivedintegerrequiredBytes safely on disk, over all the parts that have landed.
maxInFlightintegerrequiredThe most parts to have on their way at once.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "partBytes": 1,
  "parts": [
    {
      "index": 1,
      "bytes": 1048576,
      "received": true,
      "checksum": "example"
    }
  ],
  "received": 1,
  "maxInFlight": 1
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

DELETE /api/v1/uploads/parallel/{id}

Cancel it. The parts are thrown away and nothing is published.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

The reply has no body.

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

PUT /api/v1/uploads/parallel/{id}/part/{index}

One part, as the raw request body, with its BLAKE3 hash in checksum (or the x-farwing-checksum header).

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Every part is exactly partBytes long except the last. The server hashes the bytes as they arrive and throws a part away if they do not match, so a damaged part is found at that part. Sending a part again replaces it.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe upload's id.
indexpathstringrequiredWhich part, counting from 0.
checksumquerystringoptionalThe part's BLAKE3 hash, as 64 hex digits. The x-farwing-checksum header says the same and wins if both are sent.

Request body. The raw bytes of the piece. Not JSON.

Success. 200.

FieldTypeMeaning
indexintegerrequired
bytesintegerrequiredSize in bytes.
checksumstringrequired
receivedintegerrequiredBytes safely on disk over the whole upload.
{
  "index": 1,
  "bytes": 1048576,
  "checksum": "example",
  "received": 1
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestthe checksum is missing or wrong, or the part is the wrong length
404not_foundno such upload for this caller
409conflicttoo many parts in flight, or it was paused or canceled from the Transfers page
503unavailablebusy: every transfer the license allows at once is running; ask again after Retry-After
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "the checksum is missing or wrong, or the part is the wrong length"
  }
}

POST /api/v1/uploads/parallel/{id}/finish

Join the parts in order, check the whole file's BLAKE3 hash, and publish it under its name. Body: {"checksum": "<64 hex digits>"}.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

FieldTypeMeaning
namestringrequiredThe name.
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
kindstringrequired
sizeintegerrequiredSize in bytes.
modifiedstringoptional, left out when empty
{
  "name": "Rush delivery",
  "path": "projects/rush",
  "kind": "file",
  "size": 1048576,
  "modified": "example"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestparts are missing, or the whole file's hash does not match
409conflictsomething else arrived at that name meanwhile; nothing was replaced
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "parts are missing, or the whole file's hash does not match"
  }
}

Tickets

POST /api/v1/transfers/ticket

Ask for permission to move files over the data port.

Who. Any user with a key that has the transfer scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Body: {rootId, space, path, direction, lanes?, maxRate?}. Send a storage location in rootId, or a space in space. A download names one file. An upload names an existing folder (empty for the top) to send any number of files and folders into it, or a new file's path for that one file.

Request body. JSON.

FieldTypeMeaning
rootIdstringoptionalThe location, for a caller that still names storage directly.
spacestringoptionalThe space, when the path is relative to one.
pathstringoptionalRelative to the storage location. For a download, the file. For an upload, a folder that exists (empty for the top of the location) to let the client send any number of files and folders into it, or a new file's path for a ticket that carries that one file.
directionstringrequiredupload or download.
lanesintegeroptionalParallel lanes. The server grants the smaller of this and its own ceiling; leaving it out takes the engine's default.
maxRateintegeroptionalBytes per second. Only ever lowers what the license already allows.
{
  "space": "k7Qm2sLp9vX4aB1c",
  "path": "projects/rush",
  "direction": "download",
  "lanes": 4,
  "maxRate": 12500000
}

Success. 200.

FieldTypeMeaning
ticketIdstringrequiredThe id.
secretstringrequiredShown once. Not stored anywhere it could be read back.
hoststringrequiredThe name this server is reached by, from the configuration. Never from a request header: a Host: a stranger chose would send the client's data, and its secret, to a host the stranger chose.
portintegerrequired
tcpPortintegeroptional, left out when empty
connIdsarray of integerrequired
directionstringrequired
kindstringrequiredfile; folder for an upload into path; files for a download of a set, which arrives as one tree with its folders and path names.
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
bytesintegerrequiredSize in bytes.
fileCountintegeroptional, left out when emptyFiles in a files ticket.
expiresAtstringrequiredThe transfer has to start by then. Once started it runs to the end, and a broken one can be continued with the same ticket for resumeHours after it first started.
resumeHoursintegerrequired
ticketstringrequiredEverything above, packed into one string for farwing cp --ticket.
linkstringoptional, left out when emptyThe same string as a link, for a desktop client that registers the scheme. Omitted when the server has no hostname set, because a link to nowhere is worse than no link.
{
  "ticketId": "k7Qm2sLp9vX4aB1c",
  "secret": "a-secret-shown-once",
  "host": "files.example.com",
  "port": 443,
  "connIds": [
    1
  ],
  "direction": "download",
  "kind": "file",
  "path": "projects/rush",
  "bytes": 1048576,
  "expiresAt": "2026-10-05T18:00:00Z",
  "resumeHours": 24,
  "ticket": "packed-ticket-string"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requesta download names a folder, or the direction is not upload or download
404not_foundno such file, or this caller may not see it
409conflictthere is already a file where an upload would land
503unavailablethe data service is not running, or every transfer slot the license allows is in use
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "a download names a folder, or the direction is not upload or download"
  }
}
Send space or rootId, not both. The HTTP call only issues permission. The bytes move on the data port. Pass ticket to farwing cp --ticket. lanes is 1 to 16. maxRate is bytes per second and can only lower what the license already allows. Zero is refused. The secret is shown once.

Transfer records

GET /api/v1/transfers

The transfers this caller may see, a page at a time, newest first.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Answers {items: [Transfer], total, page, page_size, summary: {transfers, bytes, avg_bytes_per_sec, failed, running}}; the summary covers every row the filters match, not just this page. An administrator sees every transfer. Anyone else sees a transfer when they started it, when it used a ticket or package link they made, when it collected a package they sent, or when it went into or out of a folder they may read through a grant to them or to a group they belong to (a grant on projects covers projects/... and nothing else). Only the person who started a transfer, or an administrator, may pause, resume or cancel it.

Parameters.

NameInTypeMeaning
pagequeryintegeroptional1-based.
pageSizequeryintegeroptional25, 50 or 100. Default 25.
sortquerystringoptionalstarted, size, duration or speed.
dirquerystringoptionalasc or desc.
scopequerystringoptionalmine, or all for an administrator.
fromquerystringoptionalRFC 3339, inclusive.
toquerystringoptionalRFC 3339, exclusive.
statusquerystringoptionalComma-separated: running, paused, completed, failed, canceled.
directionquerystringoptionalupload or download.
methodquerystringoptionalComma-separated: browser, desktop, cli, automation, package.
storagequerystringoptionalA storage location id.
userquerystringoptionalThe account the transfer ran under.
linkCreatorquerystringoptionalWho made the ticket or the package link.
uploaderquerystringoptionalAn account id, or an email address for someone without an account.
downloaderquerystringoptionalAn account id, or the email address of someone who collected a package.
packagequerystringoptionalA package id.
groupquerystringoptionalAdministrators only.
qquerystringoptionalMatched against file names and paths, email addresses, names and package subjects.

Success. 200.

FieldTypeMeaning
itemsarray of objectsrequiredThe records in this reply.

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
directionstringrequired
statestringrequiredWhere this record is in its life.
methodstringrequiredbrowser, desktop, cli, automation, or package for a package link.
clientstringoptional
root_idstringoptional
storage_namestringoptional
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
bytes_totalintegerrequired
bytes_doneintegerrequired
files_totalintegerrequired
files_doneintegerrequired
errorstringoptional
started_atstringrequired
finished_atstringoptional
duration_secsnumberrequiredSeconds from start to finish, or to now while it is still going.
bytes_per_secnumberrequiredAverage over the duration.
peerstringoptionalThe address at the other end. Only for an administrator, the person who started it and the person who made the link.
user_idstringoptional
userPersonoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
link_creatorPersonoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
recipient_emailstringoptional
packagePackageRefoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
subjectstringrequired
api_keyKeyRefoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
can_controlbooleanrequiredWhether this caller may pause, resume or cancel it.
totalintegerrequiredHow many matched, including ones not on this page.
pageintegerrequired
page_sizeintegerrequired
summaryobjectrequired

It is an object:

FieldTypeMeaning
transfersintegerrequired
bytesintegerrequiredSize in bytes.
avg_bytes_per_secnumberoptionalOver finished transfers only; a half-done one would drag it down.
failedintegerrequired
runningintegerrequired
{
  "items": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "direction": "download",
      "state": "active",
      "method": "example",
      "path": "projects/rush",
      "bytes_total": 1,
      "bytes_done": 1,
      "files_total": 1,
      "files_done": 1,
      "started_at": "2026-10-05T18:00:00Z",
      "duration_secs": 1,
      "bytes_per_sec": 1,
      "can_control": true
    }
  ],
  "total": 1,
  "page": 1,
  "page_size": 50,
  "summary": {
    "transfers": 1,
    "bytes": 1048576,
    "avg_bytes_per_sec": 1,
    "failed": 1,
    "running": 1
  }
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requesta parameter is not one of its allowed values, or a time is not RFC 3339
403forbiddenscope=all or group from someone who is not an administrator
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "a parameter is not one of its allowed values, or a time is not RFC 3339"
  }
}

GET /api/v1/transfers/filters

What the Transfers page's filters can offer this caller: people, groups (administrators only), storage, packages and the addresses of people without an account. Built from what the caller may see.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
scopequerystringoptionalmine, or all for an administrator.

Success. 200.

FieldTypeMeaning
peoplearray of objectsrequired

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
groupsarray of objectsrequiredAdministrators only; empty for everyone else.

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
storagesarray of objectsrequired

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
packagesarray of objectsrequired

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
subjectstringrequired
emailsarray of stringrequiredAddresses of people without an account who collected something.
{
  "people": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "name": "Rush delivery",
      "email": "[email protected]"
    }
  ],
  "groups": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "name": "Rush delivery"
    }
  ],
  "storages": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "name": "Rush delivery"
    }
  ],
  "packages": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "subject": "Files for Monday"
    }
  ],
  "emails": [
    "[email protected]"
  ]
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

GET /api/v1/transfers/{id}

One transfer, with every file it carried.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

FieldTypeMeaning
transferobjectrequired

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
directionstringrequired
statestringrequiredWhere this record is in its life.
methodstringrequiredbrowser, desktop, cli, automation, or package for a package link.
clientstringoptional
root_idstringoptional
storage_namestringoptional
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
bytes_totalintegerrequired
bytes_doneintegerrequired
files_totalintegerrequired
files_doneintegerrequired
errorstringoptional
started_atstringrequired
finished_atstringoptional
duration_secsnumberrequiredSeconds from start to finish, or to now while it is still going.
bytes_per_secnumberrequiredAverage over the duration.
peerstringoptionalThe address at the other end. Only for an administrator, the person who started it and the person who made the link.
user_idstringoptional
userPersonoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
link_creatorPersonoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
recipient_emailstringoptional
packagePackageRefoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
subjectstringrequired
api_keyKeyRefoptional

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
can_controlbooleanrequiredWhether this caller may pause, resume or cancel it.
filesarray of objectsrequired

Each item is an object:

FieldTypeMeaning
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
sizeintegerrequiredSize in bytes.
{
  "transfer": {
    "id": "k7Qm2sLp9vX4aB1c",
    "direction": "download",
    "state": "active",
    "method": "example",
    "path": "projects/rush",
    "bytes_total": 1,
    "bytes_done": 1,
    "files_total": 1,
    "files_done": 1,
    "started_at": "2026-10-05T18:00:00Z",
    "duration_secs": 1,
    "bytes_per_sec": 1,
    "can_control": true
  },
  "files": [
    {
      "path": "projects/rush",
      "size": 1048576
    }
  ]
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

POST /api/v1/transfers/{id}/pause

Pause it. It resumes from here, not from the start.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
directionstringrequired
statestringrequiredWhere this record is in its life.
methodstringrequiredbrowser, desktop, cli, automation, or package for a package link.
clientstringoptional, left out when empty
root_idstringoptional, left out when empty
storage_namestringoptional, left out when empty
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
bytes_totalintegerrequired
bytes_doneintegerrequired
files_totalintegerrequired
files_doneintegerrequired
errorstringoptional, left out when empty
started_atstringrequired
finished_atstringoptional, left out when empty
duration_secsnumberrequiredSeconds from start to finish, or to now while it is still going.
bytes_per_secnumberrequiredAverage over the duration.
peerstringoptional, left out when emptyThe address at the other end. Only for an administrator, the person who started it and the person who made the link.
user_idstringoptional, left out when empty
userPersonoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
link_creatorPersonoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
recipient_emailstringoptional, left out when empty
packagePackageRefoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
subjectstringrequired
api_keyKeyRefoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
can_controlbooleanrequiredWhether this caller may pause, resume or cancel it.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "direction": "download",
  "state": "active",
  "method": "example",
  "path": "projects/rush",
  "bytes_total": 1,
  "bytes_done": 1,
  "files_total": 1,
  "files_done": 1,
  "started_at": "2026-10-05T18:00:00Z",
  "duration_secs": 1,
  "bytes_per_sec": 1,
  "can_control": true
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
403forbiddenthis caller may see it but did not start it
409conflictonly a running transfer can be paused
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "forbidden",
    "message": "you do not have access to this"
  }
}

POST /api/v1/transfers/{id}/resume

Carry on from where it stopped.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
directionstringrequired
statestringrequiredWhere this record is in its life.
methodstringrequiredbrowser, desktop, cli, automation, or package for a package link.
clientstringoptional, left out when empty
root_idstringoptional, left out when empty
storage_namestringoptional, left out when empty
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
bytes_totalintegerrequired
bytes_doneintegerrequired
files_totalintegerrequired
files_doneintegerrequired
errorstringoptional, left out when empty
started_atstringrequired
finished_atstringoptional, left out when empty
duration_secsnumberrequiredSeconds from start to finish, or to now while it is still going.
bytes_per_secnumberrequiredAverage over the duration.
peerstringoptional, left out when emptyThe address at the other end. Only for an administrator, the person who started it and the person who made the link.
user_idstringoptional, left out when empty
userPersonoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
link_creatorPersonoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
recipient_emailstringoptional, left out when empty
packagePackageRefoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
subjectstringrequired
api_keyKeyRefoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
can_controlbooleanrequiredWhether this caller may pause, resume or cancel it.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "direction": "download",
  "state": "active",
  "method": "example",
  "path": "projects/rush",
  "bytes_total": 1,
  "bytes_done": 1,
  "files_total": 1,
  "files_done": 1,
  "started_at": "2026-10-05T18:00:00Z",
  "duration_secs": 1,
  "bytes_per_sec": 1,
  "can_control": true
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
403forbiddenthis caller may see it but did not start it
409conflictonly a paused or queued transfer can be resumed
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "forbidden",
    "message": "you do not have access to this"
  }
}

POST /api/v1/transfers/{id}/cancel

Give up on it.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
directionstringrequired
statestringrequiredWhere this record is in its life.
methodstringrequiredbrowser, desktop, cli, automation, or package for a package link.
clientstringoptional, left out when empty
root_idstringoptional, left out when empty
storage_namestringoptional, left out when empty
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
bytes_totalintegerrequired
bytes_doneintegerrequired
files_totalintegerrequired
files_doneintegerrequired
errorstringoptional, left out when empty
started_atstringrequired
finished_atstringoptional, left out when empty
duration_secsnumberrequiredSeconds from start to finish, or to now while it is still going.
bytes_per_secnumberrequiredAverage over the duration.
peerstringoptional, left out when emptyThe address at the other end. Only for an administrator, the person who started it and the person who made the link.
user_idstringoptional, left out when empty
userPersonoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
link_creatorPersonoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
emailstringrequiredAn email address.
recipient_emailstringoptional, left out when empty
packagePackageRefoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
subjectstringrequired
api_keyKeyRefoptional, left out when empty

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
can_controlbooleanrequiredWhether this caller may pause, resume or cancel it.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "direction": "download",
  "state": "active",
  "method": "example",
  "path": "projects/rush",
  "bytes_total": 1,
  "bytes_done": 1,
  "files_total": 1,
  "files_done": 1,
  "started_at": "2026-10-05T18:00:00Z",
  "duration_secs": 1,
  "bytes_per_sec": 1,
  "can_control": true
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
403forbiddenthis caller may see it but did not start it
409conflictthis transfer has already finished
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "forbidden",
    "message": "you do not have access to this"
  }
}