# Files

Source: https://phonebox.dev/docs/using-phones/files

> Upload, download, list and delete files in a phone's shared storage.



Files live in the phone's shared storage under `/sdcard`, the storage that apps such as the file manager, the camera and the browser's downloads use. `/storage/emulated/0` is another name for the same place. Files stay on the phone when it parks, and every file request needs the phone to be `ready`.

Each request names its file or directory in the `path` query parameter:

* A path is `/sdcard` or a path inside it, or the same under `/storage/emulated/0`, with at most 1024 characters.
* A path can't contain `.` or `..` segments.
* URL-encode the path when it has spaces or other special characters.

A file can be at most 4 MB (4,000,000 bytes), whether you upload it or download it.

## Upload a file [#upload-a-file]

Send the file's bytes as the request body, not as JSON or a form:

```bash
curl -X PUT "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/files?path=/sdcard/Download/report.pdf" \
  -H "Authorization: Bearer $PHONEBOX_API_KEY" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @report.pdf
```

The path must end with the file's name. Directories on the way that don't exist yet are created. The response is `201 Created` with the `path` and the `size` in bytes. A body over 4 MB fails with `413 payload_too_large`.

## Download a file [#download-a-file]

```bash
curl -o report.pdf "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/files/content?path=/sdcard/Download/report.pdf" \
  -H "Authorization: Bearer $PHONEBOX_API_KEY"
```

The response is the file itself, as `application/octet-stream`, with its name in the `Content-Disposition` header. A path with no file fails with `404 file_not_found`, and a path to a directory fails with `400 validation_failed`, whose `next` tells you how to list it instead. A file over 4 MB fails with `413 payload_too_large`. When the file's size isn't known in advance, a download that passes 4 MB is cut off instead.

## List a directory [#list-a-directory]

```bash
curl "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/files?path=/sdcard/Download" \
  -H "Authorization: Bearer $PHONEBOX_API_KEY"
```

Without `path`, the request lists `/sdcard`. The response has the `path` and a `data` list with one entry for each file or directory:

| Field         | Meaning                                                |
| ------------- | ------------------------------------------------------ |
| `name`        | The entry's name.                                      |
| `type`        | `file`, `directory` or `other`.                        |
| `size`        | Its size in bytes.                                     |
| `modified_at` | When it last changed, or `null` when that isn't known. |

A directory that doesn't exist fails with `404 file_not_found`. A path to a file fails with `400 validation_failed`, whose `next` points to the download request for it.

## Delete a file [#delete-a-file]

```bash
curl -X DELETE "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/files?path=/sdcard/Download/report.pdf" \
  -H "Authorization: Bearer $PHONEBOX_API_KEY"
```

The response has the `path` and `"deleted": true`. A path with nothing at it fails with `404 file_not_found`, and the storage root itself can't be deleted.

Directories are not supported by this endpoint: they return `400 validation_failed` without deleting any contents. To delete a folder, open the Files app on the phone. In the console, choose **Open Files** in the Files tab, then delete the folder on the phone screen.

## From the CLI and the SDK [#from-the-cli-and-the-sdk]

| CLI                                                          | SDK                                                        |
| ------------------------------------------------------------ | ---------------------------------------------------------- |
| `phonebox files ls /sdcard/Download`                         | `phone.files.list("/sdcard/Download")`                     |
| `phonebox files push report.pdf /sdcard/Download/`           | `phone.files.upload("/sdcard/Download/report.pdf", bytes)` |
| `phonebox files pull /sdcard/Download/report.pdf report.pdf` | `phone.files.download("/sdcard/Download/report.pdf")`      |
| `phonebox files rm /sdcard/Download/report.pdf`              | `phone.files.remove("/sdcard/Download/report.pdf")`        |

When the CLI's `push` target ends with `/`, the local file keeps its name in that directory.
