Upload API (SDK)
Create a job, upload bytes to a presigned URL, then complete. This is what the official SDKs call.
Create job
curl -X POST "https://api.speechrevolutions.com/api/v1/upload" \
-H "X-API-Key: $SPEECHREVOLUTIONS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file_size": 1048576,
"output_type": "json",
"word_timestamps": true,
"speaker_labels": true,
"nltk": true,
"tier": "standard",
"custom_vocabulary": ["AcmeCorp"]
}'Request body
| Field | Type | Default |
|---|---|---|
file_size | int | required (unless audio_url) |
audio_url | string (uri) | alternative to file_size |
output_type | string | json |
word_timestamps | bool | true |
speaker_labels | bool | true |
nltk | bool | true |
tier | string | standard — the only tier currently available |
custom_vocabulary | string[] | optional |
callback_url | string (uri) | optional |
Provide exactly one of file_size or audio_url. With audio_url (an http(s) URL) the platform fetches the audio itself: the response has no upload_url, the job is enqueued immediately, and you skip the upload and /upload/complete steps entirely — go straight to waiting on the job stream. The URL must resolve to a public host.
callback_url is an optional http(s) webhook. On completion or permanent failure the platform POSTs a JSON notification there, shaped like {job_id, status: "completed"|"failed", download_url?, step?, reason?}, with these headers:
| Header | Value |
|---|---|
X-SR-Signature | sha256=<hex>, an HMAC-SHA256 of the raw request body. Verify it against the exact bytes you received, with a constant-time comparison. |
X-SR-Event | completed or failed, the same value as status in the body, so you can route a delivery before parsing it. |
X-SR-Delivery | A unique id for this delivery. Retries of the same delivery reuse it, so use it to ignore duplicates. |
User-Agent | SpeechRevolutions-Webhook/1 |
Respond with any 2xx to acknowledge. A 5xx, a timeout (10 seconds per attempt) or a connection error is retried with backoff, up to 4 attempts in all; a 4xx is treated as final and not retried. See any SDK page for a signature-verification snippet.
Response
{
"job_id": "…",
"upload_url": "https://…", // null for audio_url jobs (nothing to upload)
"download_url": "https://…",
"content_type": "application/octet-stream",
"expires_in": 3600
}Progress heartbeat
Ping while the PUT is in flight (TTL ~15s). Body: {"job_id":"…"}
Complete
Enqueues the job. Body: {"job_id":"…"}
Then wait on GET /api/v1/jobs/{job_id}/stream.
Multipart upload (large files)
An alternative to the single presigned PUT: upload the file in parts, which is more resilient for large files. The official SDKs use this by default and fall back to the single-shot PUT above if it's unavailable. The single-shot flow is always supported.
Create
Same body as /upload (needs file_size), plus an optional part_size. Returns presigned URLs for each part:
{
"job_id": "…",
"upload_id": "…",
"download_url": "https://…",
"part_size": 16777216,
"num_parts": 3,
"parts": [
{ "part_number": 1, "url": "https://…" },
{ "part_number": 2, "url": "https://…" },
{ "part_number": 3, "url": "https://…" }
],
"expires_in": 3600
}PUT each part's bytes to its url and keep the ETag from each response header.
Complete
Finalizes the upload and enqueues the job. Body: {"job_id": "…", "parts": [{"part_number": 1, "etag": "…"}, …]}
Abort
Discards an in-progress multipart upload. Body: {"job_id": "…"}