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"
}
FieldNotes
recipientsUp to 25 addresses. Omit or pass [] for a link-only transfer
subjectUp to 255 characters
messageUp to 5000 characters
retentionDaysOne of 1, 3, 7, 14, 30, 60, 90, 0; 0 means no expiry
passwordAt least 4 characters; not included in the e-mail
layoutlist or gallery
useDefaultBackgroundfalse 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.