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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
root | query | string | optional | The location, for a caller that still names storage directly. |
path | query | string | required | The file, relative to the storage location. |
space | query | string | optional | The 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | the path is a folder |
| 404 | not_found | no such file, or this caller may not see it |
| 416 | | the range starts past the end of the file |
| 503 | unavailable | busy: every transfer the license allows at once is running; ask again after Retry-After |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Field | Type | Meaning | |
|---|---|---|---|
root | string | optional | The location, for a caller that still names storage directly. |
space | string | optional | The space, when path is relative to one. |
path | string | required | Where the file will land, relative to the location or the space. |
size | integer | required | Size in bytes. |
fingerprint | string | optional | Anything 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.
| Field | Type | Meaning | |
|---|---|---|---|
id | string | required | The id. |
root | string | required | |
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. |
size | integer | required | Size in bytes. |
received | integer | required | Bytes safely written. The next piece starts here. |
chunkBytes | integer | required | The 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | the path is not valid |
| 404 | not_found | no such storage location, or this caller may not write there |
| 409 | conflict | something is already there, or another upload to that name is under way |
| 503 | unavailable | busy: every transfer the license allows at once is running; ask again after Retry-After |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the license does not include the REST API |
{
"error": {
"code": "bad_request",
"message": "the path is not valid"
}
}
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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Success. 200.
| Field | Type | Meaning | |
|---|---|---|---|
id | string | required | The id. |
root | string | required | |
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. |
size | integer | required | Size in bytes. |
received | integer | required | Bytes safely written. The next piece starts here. |
chunkBytes | integer | required | The 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.
| Status | code | When |
|---|---|---|
| 404 | not_found | not there, or not visible to this caller |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Success. 200.
The reply has no body.
Errors. The body always has the shape in Errors. Match on code.
| Status | code | When |
|---|---|---|
| 404 | not_found | not there, or not visible to this caller |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The upload's id. |
offset | query | integer | required | Where this piece starts. |
Request body. The raw bytes of the piece. Not JSON.
Success. 200.
| Field | Type | Meaning | |
|---|---|---|---|
id | string | required | The id. |
root | string | required | |
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. |
size | integer | required | Size in bytes. |
received | integer | required | Bytes safely written. The next piece starts here. |
chunkBytes | integer | required | The 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | the piece is empty, too large, or runs past the size given at the start |
| 404 | not_found | no such upload for this caller |
| 409 | conflict | the offset is not where the upload has got to, or it was paused or canceled from the Transfers page |
| 503 | unavailable | busy: every transfer the license allows at once is running; ask again after Retry-After |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Request body. None.
Success. 200.
| Field | Type | Meaning | |
|---|---|---|---|
name | string | required | The name. |
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. |
kind | string | required | |
size | integer | required | Size in bytes. |
modified | string | optional, 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | bytes are still missing |
| 409 | conflict | something else arrived at that name meanwhile; nothing was replaced |
| 404 | not_found | not there, or not visible to this caller |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Field | Type | Meaning | |
|---|---|---|---|
root | string | required | |
path | string | required | Where the file will land, relative to the storage location. |
size | integer | required | Size in bytes. |
partBytes | integer | optional | The part size the client would like. Clamped, never trusted. |
fingerprint | string | optional | Anything 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.
| Field | Type | Meaning | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string | required | The id. | ||||||||||||||||||||
partBytes | integer | required | |||||||||||||||||||||
parts | array of objects | required | |||||||||||||||||||||
Each item is an object:
| |||||||||||||||||||||||
received | integer | required | Bytes safely on disk, over all the parts that have landed. | ||||||||||||||||||||
maxInFlight | integer | required | The 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | the path is not valid, or the file is too large even for the largest part |
| 404 | not_found | no such storage location, or this caller may not write there |
| 409 | conflict | another upload to that name is already open |
| 503 | unavailable | busy: every transfer the license allows at once is running; ask again after Retry-After |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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"
}
}
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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Success. 200.
| Field | Type | Meaning | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string | required | The id. | ||||||||||||||||||||
partBytes | integer | required | |||||||||||||||||||||
parts | array of objects | required | |||||||||||||||||||||
Each item is an object:
| |||||||||||||||||||||||
received | integer | required | Bytes safely on disk, over all the parts that have landed. | ||||||||||||||||||||
maxInFlight | integer | required | The 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.
| Status | code | When |
|---|---|---|
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Success. 200.
The reply has no body.
Errors. The body always has the shape in Errors. Match on code.
| Status | code | When |
|---|---|---|
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The upload's id. |
index | path | string | required | Which part, counting from 0. |
checksum | query | string | optional | The 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.
| Field | Type | Meaning | |
|---|---|---|---|
index | integer | required | |
bytes | integer | required | Size in bytes. |
checksum | string | required | |
received | integer | required | Bytes 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | the checksum is missing or wrong, or the part is the wrong length |
| 404 | not_found | no such upload for this caller |
| 409 | conflict | too many parts in flight, or it was paused or canceled from the Transfers page |
| 503 | unavailable | busy: every transfer the license allows at once is running; ask again after Retry-After |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Request body. None.
Success. 200.
| Field | Type | Meaning | |
|---|---|---|---|
name | string | required | The name. |
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. |
kind | string | required | |
size | integer | required | Size in bytes. |
modified | string | optional, 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | parts are missing, or the whole file's hash does not match |
| 409 | conflict | something else arrived at that name meanwhile; nothing was replaced |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Field | Type | Meaning | |
|---|---|---|---|
rootId | string | optional | The location, for a caller that still names storage directly. |
space | string | optional | The space, when the path is relative to one. |
path | string | optional | Relative 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. |
direction | string | required | upload or download. |
lanes | integer | optional | Parallel lanes. The server grants the smaller of this and its own ceiling; leaving it out takes the engine's default. |
maxRate | integer | optional | Bytes per second. Only ever lowers what the license already allows. |
{
"space": "k7Qm2sLp9vX4aB1c",
"path": "projects/rush",
"direction": "download",
"lanes": 4,
"maxRate": 12500000
}
Success. 200.
| Field | Type | Meaning | |
|---|---|---|---|
ticketId | string | required | The id. |
secret | string | required | Shown once. Not stored anywhere it could be read back. |
host | string | required | The 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. |
port | integer | required | |
tcpPort | integer | optional, left out when empty | |
connIds | array of integer | required | |
direction | string | required | |
kind | string | required | file; folder for an upload into path; files for a download of a set, which arrives as one tree with its folders and path names. |
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. |
bytes | integer | required | Size in bytes. |
fileCount | integer | optional, left out when empty | Files in a files ticket. |
expiresAt | string | required | The 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. |
resumeHours | integer | required | |
ticket | string | required | Everything above, packed into one string for farwing cp --ticket. |
link | string | optional, left out when empty | The 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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | a download names a folder, or the direction is not upload or download |
| 404 | not_found | no such file, or this caller may not see it |
| 409 | conflict | there is already a file where an upload would land |
| 503 | unavailable | the data service is not running, or every transfer slot the license allows is in use |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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"
}
}
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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
page | query | integer | optional | 1-based. |
pageSize | query | integer | optional | 25, 50 or 100. Default 25. |
sort | query | string | optional | started, size, duration or speed. |
dir | query | string | optional | asc or desc. |
scope | query | string | optional | mine, or all for an administrator. |
from | query | string | optional | RFC 3339, inclusive. |
to | query | string | optional | RFC 3339, exclusive. |
status | query | string | optional | Comma-separated: running, paused, completed, failed, canceled. |
direction | query | string | optional | upload or download. |
method | query | string | optional | Comma-separated: browser, desktop, cli, automation, package. |
storage | query | string | optional | A storage location id. |
user | query | string | optional | The account the transfer ran under. |
linkCreator | query | string | optional | Who made the ticket or the package link. |
uploader | query | string | optional | An account id, or an email address for someone without an account. |
downloader | query | string | optional | An account id, or the email address of someone who collected a package. |
package | query | string | optional | A package id. |
group | query | string | optional | Administrators only. |
q | query | string | optional | Matched against file names and paths, email addresses, names and package subjects. |
Success. 200.
| Field | Type | Meaning | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
items | array of objects | required | The records in this reply. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Each item is an object:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
total | integer | required | How many matched, including ones not on this page. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
page | integer | required | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
page_size | integer | required | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
summary | object | required | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
It is an object:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{
"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.
| Status | code | When |
|---|---|---|
| 400 | bad_request | a parameter is not one of its allowed values, or a time is not RFC 3339 |
| 403 | forbidden | scope=all or group from someone who is not an administrator |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
scope | query | string | optional | mine, or all for an administrator. |
Success. 200.
| Field | Type | Meaning | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
people | array of objects | required | |||||||||||||||||
Each item is an object:
| |||||||||||||||||||
groups | array of objects | required | Administrators only; empty for everyone else. | ||||||||||||||||
Each item is an object:
| |||||||||||||||||||
storages | array of objects | required | |||||||||||||||||
Each item is an object:
| |||||||||||||||||||
packages | array of objects | required | |||||||||||||||||
Each item is an object:
| |||||||||||||||||||
emails | array of string | required | Addresses 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.
| Status | code | When |
|---|---|---|
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Success. 200.
| Field | Type | Meaning | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
transfer | object | required | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
It is an object:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
files | array of objects | required | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Each item is an object:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{
"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.
| Status | code | When |
|---|---|---|
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 403 | forbidden | the key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Request body. None.
Success. 200.
| Field | Type | Meaning | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string | required | The id. | ||||||||||||||||
direction | string | required | |||||||||||||||||
state | string | required | Where this record is in its life. | ||||||||||||||||
method | string | required | browser, desktop, cli, automation, or package for a package link. | ||||||||||||||||
client | string | optional, left out when empty | |||||||||||||||||
root_id | string | optional, left out when empty | |||||||||||||||||
storage_name | string | optional, left out when empty | |||||||||||||||||
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. | ||||||||||||||||
bytes_total | integer | required | |||||||||||||||||
bytes_done | integer | required | |||||||||||||||||
files_total | integer | required | |||||||||||||||||
files_done | integer | required | |||||||||||||||||
error | string | optional, left out when empty | |||||||||||||||||
started_at | string | required | |||||||||||||||||
finished_at | string | optional, left out when empty | |||||||||||||||||
duration_secs | number | required | Seconds from start to finish, or to now while it is still going. | ||||||||||||||||
bytes_per_sec | number | required | Average over the duration. | ||||||||||||||||
peer | string | optional, left out when empty | The address at the other end. Only for an administrator, the person who started it and the person who made the link. | ||||||||||||||||
user_id | string | optional, left out when empty | |||||||||||||||||
user | Person | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
link_creator | Person | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
recipient_email | string | optional, left out when empty | |||||||||||||||||
package | PackageRef | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
api_key | KeyRef | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
can_control | boolean | required | Whether 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.
| Status | code | When |
|---|---|---|
| 403 | forbidden | this caller may see it but did not start it |
| 409 | conflict | only a running transfer can be paused |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Request body. None.
Success. 200.
| Field | Type | Meaning | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string | required | The id. | ||||||||||||||||
direction | string | required | |||||||||||||||||
state | string | required | Where this record is in its life. | ||||||||||||||||
method | string | required | browser, desktop, cli, automation, or package for a package link. | ||||||||||||||||
client | string | optional, left out when empty | |||||||||||||||||
root_id | string | optional, left out when empty | |||||||||||||||||
storage_name | string | optional, left out when empty | |||||||||||||||||
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. | ||||||||||||||||
bytes_total | integer | required | |||||||||||||||||
bytes_done | integer | required | |||||||||||||||||
files_total | integer | required | |||||||||||||||||
files_done | integer | required | |||||||||||||||||
error | string | optional, left out when empty | |||||||||||||||||
started_at | string | required | |||||||||||||||||
finished_at | string | optional, left out when empty | |||||||||||||||||
duration_secs | number | required | Seconds from start to finish, or to now while it is still going. | ||||||||||||||||
bytes_per_sec | number | required | Average over the duration. | ||||||||||||||||
peer | string | optional, left out when empty | The address at the other end. Only for an administrator, the person who started it and the person who made the link. | ||||||||||||||||
user_id | string | optional, left out when empty | |||||||||||||||||
user | Person | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
link_creator | Person | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
recipient_email | string | optional, left out when empty | |||||||||||||||||
package | PackageRef | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
api_key | KeyRef | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
can_control | boolean | required | Whether 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.
| Status | code | When |
|---|---|---|
| 403 | forbidden | this caller may see it but did not start it |
| 409 | conflict | only a paused or queued transfer can be resumed |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 402 | licence_required | the 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.
| Name | In | Type | Meaning | |
|---|---|---|---|---|
id | path | string | required | The resource's id. |
Request body. None.
Success. 200.
| Field | Type | Meaning | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | string | required | The id. | ||||||||||||||||
direction | string | required | |||||||||||||||||
state | string | required | Where this record is in its life. | ||||||||||||||||
method | string | required | browser, desktop, cli, automation, or package for a package link. | ||||||||||||||||
client | string | optional, left out when empty | |||||||||||||||||
root_id | string | optional, left out when empty | |||||||||||||||||
storage_name | string | optional, left out when empty | |||||||||||||||||
path | string | required | A path relative to the space or the storage location, with / between folders and no leading slash. | ||||||||||||||||
bytes_total | integer | required | |||||||||||||||||
bytes_done | integer | required | |||||||||||||||||
files_total | integer | required | |||||||||||||||||
files_done | integer | required | |||||||||||||||||
error | string | optional, left out when empty | |||||||||||||||||
started_at | string | required | |||||||||||||||||
finished_at | string | optional, left out when empty | |||||||||||||||||
duration_secs | number | required | Seconds from start to finish, or to now while it is still going. | ||||||||||||||||
bytes_per_sec | number | required | Average over the duration. | ||||||||||||||||
peer | string | optional, left out when empty | The address at the other end. Only for an administrator, the person who started it and the person who made the link. | ||||||||||||||||
user_id | string | optional, left out when empty | |||||||||||||||||
user | Person | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
link_creator | Person | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
recipient_email | string | optional, left out when empty | |||||||||||||||||
package | PackageRef | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
api_key | KeyRef | optional, left out when empty | |||||||||||||||||
It is an object:
| |||||||||||||||||||
can_control | boolean | required | Whether 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.
| Status | code | When |
|---|---|---|
| 403 | forbidden | this caller may see it but did not start it |
| 409 | conflict | this transfer has already finished |
| 401 | unauthenticated | no key, or a key that is unknown, expired, revoked, or owned by a disabled account |
| 402 | licence_required | the license does not include the REST API |
{
"error": {
"code": "forbidden",
"message": "you do not have access to this"
}
}