Skip to main content

Upload a File

Upload an audio or video file from your machine to start a transcription job. Use it when the file has no public URL. The upload host, upload.speechischeap.com, stores the file and forwards it to the Jobs API as a job from a URL. It returns the same job, so webhooks, streaming, polling, and cancellation work as they do for any other job.

Endpoint​

POST https://upload.speechischeap.com/v2/jobs/

Send the request to upload.speechischeap.com, not to api.speechischeap.com. The API host reads a JSON body and doesn't accept files.

Authentication​

Send your API key as a Bearer token. Upload checks the key with the Jobs API before it reads the file.

Authorization: Bearer YOUR_API_KEY

Request​

Send a multipart/form-data body. Name the file part input_file, and send every other parameter as a form field.

ParameterTypeDefaultDescription
input_filefileRequiredThe audio or video file to transcribe. The file can be up to 2 GiB. See Uploads for the other rules.
can_label_audio, can_parse_speakers, can_parse_wordsbooleanfalseThe add-ons. Send true to turn one on. See Output and Add-ons for their output and pricing for their price.
can_stream_outputbooleanfalseWhen enabled, streams the transcription after the upload finishes. See Stream Progress.
webhook_urlstring""The URL that receives the job's result in a single POST request. See Webhooks.
Other parametersEvery other parameter of Create a Job from a URL works as a form field, except input_url.

Example Requests​

Upload and Receive a Webhook​

curl --request POST \
--url https://upload.speechischeap.com/v2/jobs/ \
--header 'Authorization: Bearer YOUR_API_KEY' \
--form 'input_file=@/path/to/audio-file.mp3' \
--form 'webhook_url=https://your-domain.com/webhook' \
--no-buffer

The --no-buffer option prints each event as it arrives.

Upload and Stream the Result​

curl --request POST \
--url https://upload.speechischeap.com/v2/jobs/ \
--header 'Authorization: Bearer YOUR_API_KEY' \
--form 'input_file=@/path/to/audio-file.mp3' \
--form 'can_stream_output=true' \
--no-buffer

Response​

Upload answers every valid request with 200 OK and Content-Type: text/event-stream, even when the job doesn't stream. A request that fails validation gets one of the other statuses and a JSON body with an error or message field.

Status CodeDescription
200 OKUpload accepted the file and started the event stream.
400 Bad RequestThe input_file part is missing or misnamed, the file's type isn't supported, or the upload ended before the whole file arrived.
401 UnauthorizedThe Authorization header is missing or malformed, or the API key is unknown, revoked, or its billing isn't active.
406 Not AcceptableThe body is JSON, plain text, or empty instead of multipart/form-data.
415 Unsupported Media TypeThe body has another Content-Type, such as application/x-www-form-urlencoded, or none. Upload answers before it checks the API key.
500 Internal Server ErrorUpload failed before it started the stream.

Each event is a line that starts with data: and holds one JSON object, followed by a blank line.

Upload Events​

The stream starts with upload events. bytes_uploaded is the number of bytes stored so far.

data: {"type":"upload","message":"Uploading...","bytes_uploaded":0}

data: {"type":"upload","message":"Uploading...","bytes_uploaded":16384}

Job Event​

When the file is stored, Upload creates the job. Without can_stream_output, the last event is the job, the same one that creating a job from a URL returns, and the stream closes:

data: {"status":"PENDING","id":"00000000-1111-7222-b333-444444444444-sic","output":{}}

With can_stream_output, the stream continues with the job's initial, progress, segment, and final events. See Stream Progress.

Error Events​

A failure after the stream starts can't change the HTTP status, so it arrives as an event, and the stream closes:

data: {"status":"error","error":"Upload connection closed"}

Errors​

Errors before the stream starts are JSON, and the most likely are Unsupported file type detected: <type>. and Missing required "input_file" parameter. Errors after it starts arrive as error events, such as API call failed: 400 - Input URL is not reachable, and Upload errors explains each one.

Notes​

  • Upload accepts a file by its content, but it keeps the extension from the file name. Name the file with a supported extension. A file named audio.m4b or audio passes the content check and then fails. See Uploads for the size limit, the accepted types, the naming rule, and how long Upload keeps the file.
  • You pay only when a job completes. See Billing.
  • The upload host accepts browser requests (CORS), but browser code exposes your API key to anyone who loads the page. Send uploads from a server, or use a key you can revoke.
  • To pay with a crypto wallet instead of an API key, see x402 Upload a File.