Files
A file is one of your inputs: a recording you uploaded, or one we imported for you. Projects are made of files.
You can make a file on its own (POST /v1/files) and use it in a project later, or make it inline when you create
the project (files: [{"fileName": "host.wav"}]): it’s the same thing either way.
Uploading
Section titled “Uploading”curl https://api.podsworth.com/v1/files \ -H "Authorization: Bearer $PODSWORTH_KEY" -H "Content-Type: application/json" \ -d '{"fileName": "host.wav"}'{ "id": "file_8c1d4f0e2b7a49d1a3f0", "fileName": "host.wav", "status": "awaiting_upload", "uploadUrl": "https://…s3.us-east-2.amazonaws.com/uploads/…?X-Amz-Signature=…", "uploadExpiresAt": "2026-10-07T18:02:11Z"}PUT the file’s bytes to uploadUrl, as the whole request body:
curl -T host.wav "<uploadUrl>"with open("host.wav", "rb") as f: requests.put(file["uploadUrl"], data=f).raise_for_status()await fetch(file.uploadUrl, { method: "PUT", body: await readFile("host.wav") });- Why a separate URL: the bytes go straight to our storage instead of through the API, so files up to 5 GB
upload as fast as your connection allows. The URL is signed: it needs no
Authorizationheader (or any other header), and works for three hours. Read the file again for a new one. - From a browser: the upload URL accepts a
PUTfrom any origin, so your own web app can upload directly (fetchorXMLHttpRequest, which reports progress). - Its answers come from storage, not from our API:
200when it’s in, and an XML error otherwise. A403withRequest has expiredmeans the URL is too old: read the file for a fresh one and PUT again. - Limits: 5 GB per file (500 MB in test mode); at most 100 files waiting for their upload per account. Accepted: WAV, MP3, M4A, MP4, AVI, FLAC, OGG, AAC and a few more; we read the file itself, not its name.
Checking
Section titled “Checking”As soon as a file lands we check it: we measure it, and it has to be audio or video we can read. Then it’s ready,
with its length, or failed, with why.
status | |
|---|---|
awaiting_upload | Made; PUT it to uploadUrl. |
importing | We’re fetching it from its link. |
checking | It’s in; we’re measuring it (a few seconds). |
ready | durationSeconds, channels, sampleRate and sizeBytes are filled in, and for a stereo file twoSpeakers (a different speaker on each side: two tracks in a project, see Projects). Usable in projects. |
failed | error.code (unreadable_file, file_too_large in test mode, import_failed) and error.message. |
expired | Deleted 30 days after it was checked. |
deleted | You deleted it. |
We notice an upload when you next read the file or a project that has it, or straight away if a submitted project is waiting for it, so you never need to tell us you’re done. A file that’s in can’t change: PUTting to its old URL afterwards changes nothing we read or process. To use a different recording, make a new file.
A project of ready files shows its price (creditsSeconds) before you submit it. file.ready and file.failed
webhooks tell you when a file is checked.
Imports
Section titled “Imports”We fetch the file for you. Imports start as soon as the file is made (status: "importing", no uploadUrl), and
it’s checked like an upload once it’s in. A project can be submitted before its imports finish: it waits for them.
source | |
|---|---|
{"type": "url", "url": "https://…"} | Any public https file, e.g. a signed link from your own storage. |
{"type": "dropbox", "url": "https://www.dropbox.com/…"} | A Dropbox share link. |
{"type": "googleDrive", "fileId": "…", "accessToken": "…"} | A Google Drive file, with an OAuth access token that can read it (the drive.file scope covers files the user picked). We use the token once and don’t keep it. |
{ "fileName": "host.wav", "source": { "type": "url", "url": "https://files.example.com/ep12/host.wav?sig=…" } }Rules for imports:
- https only, and the host must resolve to a public address. We follow up to five redirects, checking each one.
- Dropbox imports stay on Dropbox’s hosts and Drive imports on Google’s.
- Up to 5 GB per file (500 MB in test mode), and an hour per download.
- At most 24 files importing at once per account (
429import_limit).
When an import fails because of its link (a 4xx answer, too large, a private address), the file is failed with
import_failed and the reason in error.message. Put a new file with a working link in the project
(changing a project).
Using a file again
Section titled “Using a file again”A file isn’t tied to one project: put its id in any project of the same account and mode, including a copy made to
process a project again, with no new upload. Files belong to the key’s mode
(live and test never see each other’s), and a show’s key sees only the files it made.
{ "name": "Episode 12 (merged)", "files": ["file_8c1d4f0e2b7a49d1a3f0", "file_93ab07c2d4e14f5a8b61"] }Listing and deleting
Section titled “Listing and deleting”GET /v1/files?status=ready&limit=50&cursor=…GET /v1/files/{id}DELETE /v1/files/{id}Lists are newest first, at most 100 per page; pass nextCursor as cursor for the next page.
Files are deleted 30 days after they’re checked (expiresAt), unless a kept project uses them:
then they’re kept too, and expiresAt is null. DELETE /v1/files/{id} deletes one now, kept copy included. It’s
refused with 409 file_in_use while a submitted project that hasn’t finished uses it.