Files
Every app has one volume, mounted as its working directory. The file API reads and writes it; paths are relative to the volume root and always start with/.
Reading text
/files/text returns the content inside the usual JSON envelope, up to 512 KB per call. A longer file comes back with truncated: true — page through it with offset. A file that is not text is reported with binary: true and no content; download it from /files/content instead.
Writing
Writes replace the whole file — there is no partial write. Send text as-is, and anything else base64-encoded:Database templates do not allow file access — their files are a live on-disk format that hand edits would corrupt. The file API answers
403 FILE_ACCESS_NOT_ALLOWED for them; use backups to get the data out.SFTP
For moving many files, or using an editor or FTP client you already have, turn on SFTP:GET /apps/{id}/sftp afterwards — gives the host, port, username and password. Disabling SFTP revokes the password; enabling it again issues a new one, so update your client. POST /apps/{id}/sftp/regenerate issues a new password without turning SFTP off.
Output and logs
tail lines from the end (up to 5000), or everything after an ISO timestamp with since. It works on a stopped or crashed app too — which is usually when you need it most. To follow output live, see Consoles and live streams.
Run a command
POST /apps/{id}/exec runs a command inside the running container and returns its output and exit code. The command is a list of arguments, not a shell line — ask for a shell to use pipes or &&:
truncated: true beyond that), and a command still running at timeoutMs (up to 2 minutes) comes back with timedOut: true. This runs alongside your app; it does not change how the app starts.