# Upload a file

`POST https://api.mailmasker.org/api/v1/drive/files`

Send a whole file in one request, as a form upload.

- Who can use it: Any signed-in account
- Area: Drive
- Answers 201 Created when it works
- Page: https://developer.mailmasker.org/drive-upload-file

The body is a multipart form, the kind a browser sends, with the file in a field named `file`; the name it has there becomes its name in Drive. Drive works out the real type from the contents, whatever the upload claims. Fine for everyday files; for a big one, or over a shaky connection, use Start a big upload instead. homelab-cli switches to that for files over 8 MiB.

## Parameters

| Name | In | Required | What it is | Example |
|---|---|---|---|---|
| `file` | body | yes | The file itself, as a multipart form field (with cURL, `-F file=@notes.txt`). |  |
| `folder_id` | body | no | A form field naming the folder to put it in. Leave it out for the top level. |  |
| `client_mtime` | body | no | A form field with the file's own date, in seconds since 1970, so a search by date finds it (or client_mtime_ms, in milliseconds). A date before 1990, or more than a day ahead, is ignored.  |  |

## Good to know

- With no file field the answer is 400, and a folder that isn't yours answers 404.
- An upload that would take you past your storage limit is refused with 413.

## Examples

cURL:

```bash
curl -s -X POST 'https://api.mailmasker.org/api/v1/drive/files' \
  -H "Authorization: Bearer $TOKEN" \
  -F file=@notes.txt
```

Perl:

```perl
use Mojo::Base -strict;
use Mojo::UserAgent;

my $ua  = Mojo::UserAgent->new;
my $res = $ua->post('https://api.mailmasker.org/api/v1/drive/files',
    { Authorization => "Bearer $ENV{TOKEN}" },
    form => { file => { file => 'notes.txt' } })->result;
die $res->code, ' ', ($res->json('/error') // $res->message), "\n" unless $res->is_success;
print $res->body, "\n";
```

homelab-cli:

```bash
homelab-cli drive upload ./notes.txt
```

## Response

201 Created:

```json
{
  "id": 42,
  "filename": "notes.txt",
  "size_bytes": 1532,
  "mime_type": "text/plain",
  "uploaded_at": "2026-11-03 21:42:10.123456-06",
  "content_created_at": "2026-10-30 08:12:03-06",
  "folder_id": null
}
```
