Transfers
List transfers
GET /api/transfers
Returns both directions in one response.
{
"data": {
"sent": [
{
"id": 12,
"token": "3f9a…",
"subject": "Proposal & draft contract",
"status": "sent",
"kind": "outgoing",
"expiresAt": "2026-09-01T10:00:00.000Z",
"downloadCount": 3,
"fileCount": 3,
"totalSize": 574464,
"recipients": "client@example.com, anna@example.com"
}
],
"received": []
}
}
sent matches on your user id. received matches on your e-mail address,
because a transfer can be addressed to someone before they have an account, or
by an outside sender who only ever knew the address.
status is draft until the transfer is sent. kind is guest when an outside
contact uploaded it to a team member.
Create a draft
POST /api/transfers
{
"recipients": ["client@example.com"],
"subject": "Proposal & draft contract",
"message": "As discussed — feedback by Friday would be great.",
"retentionDays": 7,
"password": "optional",
"layout": "list"
}
| Field | Notes |
|---|---|
recipients | Up to 25 addresses. Omit or pass [] for a link-only transfer |
subject | Up to 255 characters |
message | Up to 5000 characters |
retentionDays | One of 1, 3, 7, 14, 30, 60, 90, 0; 0 means no expiry |
password | At least 4 characters; not included in the e-mail |
layout | list or gallery |
useDefaultBackground | false leaves the sender's default background off this transfer; omitted, it is applied |
retentionDays is validated before it is coerced, so a missing or blank value
is a 400 rather than silently becoming "keep forever".
The response carries the id and the download token, so you can copy the link without a second request:
{
"data": {
"id": 12,
"token": "3f9a…",
"status": "draft",
"retentionDays": 7,
"expiresAt": "2026-09-01T10:00:00.000Z",
"layout": "list",
"hasPassword": false,
"hasBackground": true,
"recipients": [{ "email": "client@example.com", "name": null }]
}
}
The password itself is never echoed back — only whether one is set.
hasBackground says whether the sender's default background was put on the
draft; the transfer keeps its own copy of it.
Delete a transfer
DELETE /api/transfers/:id
The manual version of expiry. Files go from disk and the rows go with them, so any link already sitting in an inbox stops working. This cannot be undone.
Administrators can delete anyone's transfer through the interface; over the API a key can only delete its own account's.