Files
List, upload, download and delete files in a phone's shared storage, and the rules for their paths.
Files live in the phone's shared storage under /sdcard and stay there while the phone is parked. Every file request needs a ready phone. Files covers the same requests from the CLI and the SDK.
Paths
Each request names its file or directory in the path query parameter:
- A path is
/sdcard, or a path inside it./storage/emulated/0is another name for the same place and works the same way. - It has at most 1024 characters, and it can't contain
.or..segments. - URL-encode it when it has spaces or other special characters.
A path that breaks these rules fails with 400 validation_failed, whose details.issues names path.
List files
GET /v1/phones/{id}/files needs the phones:read scope.
Lists one directory.
| Parameter | Type | Default | Rules |
|---|---|---|---|
path | string | /sdcard | The directory to list. |
curl "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/files?path=/sdcard/Download" \
-H "Authorization: Bearer $PHONEBOX_API_KEY"{
"path": "/sdcard/Download",
"data": [
{ "name": "report.pdf", "type": "file", "size": 482133, "modified_at": "2026-09-29T10:09:14.000Z" },
{ "name": "receipts", "type": "directory", "size": 4096, "modified_at": "2026-09-29T10:04:52.000Z" }
]
}| Field | Type | Meaning |
|---|---|---|
path | string | The directory listed. |
data[].name | string | The entry's name. |
data[].type | string | file, directory or other. |
data[].size | number | Its size in bytes. |
data[].modified_at | timestamp or null | When it last changed, or null when that isn't known. |
| Error | When |
|---|---|
400 validation_failed | The path breaks the rules, or it names a file. For a file, next gives the request that downloads it. |
404 file_not_found | No directory exists at the path. details.path repeats it. |
The readiness and phone-service errors in Common errors apply too.
Upload a file
PUT /v1/phones/{id}/files needs the phones:control scope.
Writes the request body, as raw bytes, to the file that path names. The body can be at most 4 MB, which is 4,000,000 bytes.
| Parameter | Type | Default | Rules |
|---|---|---|---|
path | string | None | The file's full path, ending with its name. It is required. |
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.pdfDirectories on the way that don't exist yet are created. It answers 201 Created:
{
"path": "/sdcard/Download/report.pdf",
"size": 482133
}| Error | When |
|---|---|
400 validation_failed | The path breaks the rules, or it doesn't end with a file name. |
413 payload_too_large | The body is larger than 4 MB. |
502 action_outcome_unknown | The phone service didn't confirm the upload. List the directory to see whether the file arrived. |
The readiness and phone-service errors in Common errors apply too.
Download a file
GET /v1/phones/{id}/files/content needs the phones:read scope.
Returns the file's bytes as application/octet-stream, with its name in the Content-Disposition header.
| Parameter | Type | Default | Rules |
|---|---|---|---|
path | string | None | The file to download. It is required. |
curl -o report.pdf "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/files/content?path=/sdcard/Download/report.pdf" \
-H "Authorization: Bearer $PHONEBOX_API_KEY"A file can be downloaded when it is at most 4 MB. When its size isn't known in advance, a download that passes 4 MB is cut off, so check that you received the whole file.
| Error | When |
|---|---|
400 validation_failed | The path breaks the rules, or it names a directory. For a directory, next gives the request that lists it. |
404 file_not_found | No file exists at the path. details.path repeats it. |
413 payload_too_large | The file is larger than 4 MB. |
The readiness and phone-service errors in Common errors apply too.
Delete a file
DELETE /v1/phones/{id}/files needs the phones:control scope.
Deletes a file. Directories return 400 validation_failed without deleting any contents. Delete folders in the Files app on the phone instead; the console’s Files tab has an Open Files button.
| Parameter | Type | Default | Rules |
|---|---|---|---|
path | string | None | The file to delete. It is required; directories and the storage root cannot be deleted through this endpoint. |
curl -X DELETE "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/files?path=/sdcard/Download/report.pdf" \
-H "Authorization: Bearer $PHONEBOX_API_KEY"{
"path": "/sdcard/Download/report.pdf",
"deleted": true
}| Error | When |
|---|---|
400 validation_failed | The path breaks the rules, or it names a directory or the storage root. For directories, next explains how to use the phone’s Files app; no contents are deleted. |
404 file_not_found | Nothing exists at the path. details.path repeats it. |
502 action_outcome_unknown | The phone service didn't confirm the delete, and a follow-up read couldn't confirm that the path is absent. Follow next to list the parent directory before deciding whether to retry. |
After an unconfirmed deletion, Phonebox reads the parent directory once to check the result, without repeating the delete. If the path is confirmed absent, it returns deleted: true. A path already absent before the initial delete still returns 404 file_not_found; a cleanup task can treat this as its desired state already reached.
The readiness and phone-service errors in Common errors apply too.