API reference

Upload sessions

7 operations. Base URL https://api.scarleta.ai. Select an operation to see its parameters, samples and errors.

Jump to an operation
GET/v1/audio/uploads

List unfinished upload sessions

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Returns your upload sessions that are still open, newest first (up to 200), so an interrupted upload can be found and resumed. Finished and cancelled sessions are not listed. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.

Cost. Free of charge.

curl "https://api.scarleta.ai/v1/audio/uploads" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"

Parameters

NameTypeRequiredDescription
statusquery"uploading"OptionalOnly `uploading` is supported, and it is the default.
Response fields
FieldTypeDescription
sessionsarray<object>
sessions[].session_idstringIdentifier of the session.
sessions[].file_idstringIdentifier the file will have once completed.
sessions[].audio_idstring
sessions[].filenamestring | null
sessions[].content_typestring
sessions[].declared_bytesintegerSize declared when the session was created. Allowed: -9007199254740991 to 9007199254740991.
sessions[].part_size_bytesintegerAllowed: -9007199254740991 to 9007199254740991.
sessions[].part_countintegerAllowed: -9007199254740991 to 9007199254740991.
sessions[].tagsarray<string>
sessions[].version_ofstring | null`audio_id` this upload will be attached to, if any.
sessions[].created_atstringISO 8601 timestamp.
sessions[].expires_atstringISO 8601 timestamp.
Errors
StatusCodeDescription
400invalid_statusA `status` other than `uploading`.
401invalid_keyMissing, malformed, unknown or revoked API key.
429rate_limit_exceededOver the account request budget. Wait for the `Retry-After` header, then retry.
503upload_unavailableThe database is temporarily unavailable. Retry shortly.
Example responses
{
  "data": {
    "sessions": [
      {
        "session_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
        "audio_id": "audio_bbb14949dc19",
        "filename": "morning-session.wav",
        "content_type": "audio/wav",
        "declared_bytes": 1920044,
        "part_size_bytes": 16777216,
        "part_count": 1,
        "tags": [
          "morning"
        ],
        "version_of": null,
        "created_at": "2026-10-20T11:53:45.938Z",
        "expires_at": "2026-10-27T11:53:45.938Z"
      }
    ]
  }
}
  • 200 Open sessions. The body is `{ data }` without `meta`.
  • 400 A `status` other than `uploading`.
  • 401 Missing, malformed, unknown or revoked API key.
  • 429 Over the account request budget. Wait for the `Retry-After` header, then retry.
  • 503 The database is temporarily unavailable. Retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: auth_unavailable, invalid_auth_format, invalid_key_format, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.

POST/v1/audio/uploads

Start an upload session

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Starts a resumable upload for a file of any size up to 10 GiB (1 GiB for MP4 or MOV video). The file is sent in parts of part_size_bytes (16 MiB; the last part is smaller), at most 10000 parts. The flow is: create the session, ask for part URLs, PUT each part to its URL (parts can go in parallel and be retried), then complete the session. A session you do not finish can be resumed by reading its status, and is cleaned up 7 days after it started.

Creating a session reserves the declared size in your storage at once, so a file that would not fit is refused here with 413 storage_quota_exceeded. At most 50 sessions started in the last 60 minutes can be unfinished at the same time. If you send sha256, repeating the same request (same hash, filename, size and version_of) within 5 minutes returns the open session instead of starting a second one, which makes a lost response safe to retry. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.

Cost. Free of charge; the file counts toward your storage.

curl -X POST "https://api.scarleta.ai/v1/audio/uploads" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "morning-session.wav",
    "content_type": "audio/wav",
    "size_bytes": 1920044,
    "tags": [
      "morning"
    ],
    "client_duration_seconds": 60
  }'

Request body

NameTypeRequiredDescription
filenamebodystringRequiredName to show for the file, at most 255 characters. Required. Allowed: 1 to 255 characters.
content_typebodystringRequiredContent type of the file. Required. One of: `audio/wav`, `audio/wave`, `audio/x-wav`, `audio/mpeg`, `audio/mp3`, `audio/ogg`, `audio/flac`, `audio/aac`, `audio/m4a`, `audio/mp4`, `audio/x-m4a`, `audio/aiff`, `audio/x-aiff`, `audio/webm`, `audio/opus`, `audio/x-opus+ogg`, `video/mp4`, `video/quicktime`.
size_bytesbodyintegerRequiredSize of the whole file in bytes. Required. At most 10 GiB for audio and 1 GiB for video. Allowed: at most 10737418240.
sha256bodystringOptionalSHA-256 of the file bytes as 64 hexadecimal characters. Optional; enables safe retry of this call.
tagsbodyarray<string>OptionalTags to put on the file, at most 50 of at most 64 characters each. Blank tags are dropped and duplicates merged.
version_ofbodystringOptional`audio_id` of one of your ready files to attach this upload to as a new version, once it completes. Allowed: at most 200 characters.
client_duration_secondsbodynumberOptionalLength of the audio in seconds, if you know it. Display only; never used for billing. Allowed: at least 0.
Response fields
FieldTypeDescription
session_idstringIdentifier of the session.
file_idstringIdentifier the file will have once completed.
audio_idstringLibrary identifier of the file.
part_size_bytesintegerSize of every part except the last. Allowed: -9007199254740991 to 9007199254740991.
part_countintegerNumber of parts to send. Allowed: -9007199254740991 to 9007199254740991.
parts_donearray<integer>Part numbers already uploaded (empty for a new session).
expires_atstringWhen an unfinished session is cleaned up, as an ISO 8601 timestamp.
Errors
StatusCodeDescription
400missing_filenameA required field is missing or malformed, `tags`, `sha256` or the duration is invalid, or `version_of` is not one of your ready files.
401invalid_keyMissing, malformed, unknown or revoked API key.
413file_too_largeThe declared size is over the per-file limit, or the file does not fit in your storage (`storage_quota_exceeded`).
429too_many_active_uploadsToo many unfinished sessions, or over the per-minute cap of these routes.
503upload_unavailableThe session could not be registered; nothing was reserved. Retry shortly.
Example responses
{
  "data": {
    "session_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
    "audio_id": "audio_bbb14949dc19",
    "part_size_bytes": 16777216,
    "part_count": 1,
    "parts_done": [],
    "expires_at": "2026-10-27T11:53:45.938Z"
  }
}
  • 201 Session created. The body is `{ data }` without `meta`.
  • 400 A required field is missing or malformed, `tags`, `sha256` or the duration is invalid, or `version_of` is not one of your ready files.
  • 401 Missing, malformed, unknown or revoked API key.
  • 413 The declared size is over the per-file limit, or the file does not fit in your storage (`storage_quota_exceeded`).
  • 429 Too many unfinished sessions, or over the per-minute cap of these routes.
  • 503 The session could not be registered; nothing was reserved. Retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: auth_unavailable, invalid_auth_format, invalid_content_type, invalid_duration, invalid_json, invalid_key_format, invalid_sha256, invalid_tags, invalid_version_of, missing_api_key, missing_auth, missing_size, rate_limit_exceeded, rate_limit_unavailable, storage_quota_exceeded, tag_too_long, too_many_tags, unauthorized.

GET/v1/audio/uploads/{sessionId}

Get an upload session

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Returns the state of one session, with the parts storage has actually received, so an interrupted upload resumes by sending only the missing parts. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.

Cost. Free of charge.

SESSIONID="YOUR_SESSIONID"
curl "https://api.scarleta.ai/v1/audio/uploads/$SESSIONID" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"

Parameters

NameTypeRequiredDescription
sessionIdpathstringRequiredThe `session_id` returned when the session was created.
Response fields
FieldTypeDescription
session_idstringIdentifier of the session.
file_idstringIdentifier the file has once completed.
audio_idstring | null
status"uploading" | "completed" | "aborted" | "expired"`uploading` until completed or cancelled.
parts_donearray<integer>Part numbers storage has received.
bytes_doneintegerTotal size of those parts in bytes. Allowed: -9007199254740991 to 9007199254740991.
declared_bytesintegerAllowed: -9007199254740991 to 9007199254740991.
part_size_bytesintegerAllowed: -9007199254740991 to 9007199254740991.
part_countintegerAllowed: -9007199254740991 to 9007199254740991.
filenamestring | null
expires_atstringISO 8601 timestamp.
Errors
StatusCodeDescription
401invalid_keyMissing, malformed, unknown or revoked API key.
404upload_session_not_foundNo upload session with this id in your account. A session that belongs to another account is reported the same way.
429rate_limit_exceededOver the account request budget. Wait for the `Retry-After` header, then retry.
503upload_unavailableStorage or the database is temporarily unavailable. Retry shortly.
Example responses
{
  "data": {
    "session_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
    "audio_id": "audio_bbb14949dc19",
    "status": "uploading",
    "parts_done": [
      1
    ],
    "bytes_done": 1920044,
    "declared_bytes": 1920044,
    "part_size_bytes": 16777216,
    "part_count": 1,
    "filename": "morning-session.wav",
    "expires_at": "2026-10-27T11:53:45.938Z"
  }
}
  • 200 Session state. The body is `{ data }` without `meta`.
  • 401 Missing, malformed, unknown or revoked API key.
  • 404 No upload session with this id in your account. A session that belongs to another account is reported the same way.
  • 429 Over the account request budget. Wait for the `Retry-After` header, then retry.
  • 503 Storage or the database is temporarily unavailable. Retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: auth_unavailable, invalid_auth_format, invalid_key_format, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.

POST/v1/audio/uploads/{sessionId}/abort

Cancel an upload session

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Cancels an unfinished session: the parts are discarded and the storage reserved for the file is released. Cancelling a session that is already cancelled succeeds again; one that already completed returns 409 session_not_uploading (delete the file instead). Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.

Cost. Free of charge.

SESSIONID="YOUR_SESSIONID"
curl -X POST "https://api.scarleta.ai/v1/audio/uploads/$SESSIONID/abort" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"

Parameters

NameTypeRequiredDescription
sessionIdpathstringRequiredThe `session_id` returned when the session was created.
Response fields
FieldTypeDescription
status"aborted"
Errors
StatusCodeDescription
401invalid_keyMissing, malformed, unknown or revoked API key.
404upload_session_not_foundNo upload session with this id in your account. A session that belongs to another account is reported the same way.
409session_not_uploadingThe session already completed.
429rate_limit_exceededOver the account request budget. Wait for the `Retry-After` header, then retry.
503upload_unavailableStorage or the database is temporarily unavailable. Retry shortly.
Example responses
{
  "data": {
    "status": "aborted"
  }
}
  • 200 The session is cancelled. The body is `{ data }` without `meta`.
  • 401 Missing, malformed, unknown or revoked API key.
  • 404 No upload session with this id in your account. A session that belongs to another account is reported the same way.
  • 409 The session already completed.
  • 429 Over the account request budget. Wait for the `Retry-After` header, then retry.
  • 503 Storage or the database is temporarily unavailable. Retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: auth_unavailable, invalid_auth_format, invalid_key_format, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.

POST/v1/audio/uploads/{sessionId}/complete

Complete an upload session

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Assembles the uploaded parts into the file. Every part must be uploaded with the right size and the total must match the size you declared. The bytes are then checked: a file that is not audio is removed and refused with 415 not_audio. On success the file is ready in your library. Completing a session that already completed returns the same result, so the call is safe to retry.

Optionally add tags (merged with the ones from the start), change version_of, or give client_duration_seconds. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.

Cost. Free of charge.

SESSIONID="YOUR_SESSIONID"
curl -X POST "https://api.scarleta.ai/v1/audio/uploads/$SESSIONID/complete" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": [
      "morning"
    ]
  }'

Parameters

NameTypeRequiredDescription
sessionIdpathstringRequiredThe `session_id` returned when the session was created.

Request body

NameTypeRequiredDescription
tagsbodyarray<string>OptionalTags to put on the file, at most 50 of at most 64 characters each. Blank tags are dropped and duplicates merged.
version_ofbodystringOptional`audio_id` of one of your ready files to attach this upload to. A value that is not one of yours is ignored. Allowed: at most 200 characters.
client_duration_secondsbodynumberOptionalLength of the audio in seconds. Display only. Allowed: at least 0.
Response fields
FieldTypeDescription
audio_idstringLibrary identifier of the file.
file_idstringIdentifier of the file.
size_bytesintegerFinal size in bytes. Allowed: -9007199254740991 to 9007199254740991.
formatstringDetected audio format.
status"ready"
version_link"linked" | "failed" | null`linked` or `failed` when `version_of` was requested, otherwise `null`.
Errors
StatusCodeDescription
400invalid_tags`tags` or `client_duration_seconds` is invalid.
401invalid_keyMissing, malformed, unknown or revoked API key.
404upload_session_not_foundNo upload session with this id in your account. A session that belongs to another account is reported the same way.
409parts_missingA part is missing or has the wrong size, the parts add up to more than the declared size, or the session was cancelled or already ended another way.
413file_too_largeThe uploaded bytes exceed the per-file limit; the upload is cancelled.
415not_audioThe assembled file is not a supported audio or video file; it is removed.
429rate_limit_exceededOver the account request budget. Wait for the `Retry-After` header, then retry.
503upload_unavailableStorage is temporarily unavailable. Retry shortly.
Example responses
{
  "data": {
    "audio_id": "audio_bbb14949dc19",
    "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
    "size_bytes": 1920044,
    "format": "wav",
    "status": "ready",
    "version_link": null
  }
}
  • 200 The file is ready. The body is `{ data }` without `meta`.
  • 400 `tags` or `client_duration_seconds` is invalid.
  • 401 Missing, malformed, unknown or revoked API key.
  • 404 No upload session with this id in your account. A session that belongs to another account is reported the same way.
  • 409 A part is missing or has the wrong size, the parts add up to more than the declared size, or the session was cancelled or already ended another way.
  • 413 The uploaded bytes exceed the per-file limit; the upload is cancelled.
  • 415 The assembled file is not a supported audio or video file; it is removed.
  • 429 Over the account request budget. Wait for the `Retry-After` header, then retry.
  • 503 Storage is temporarily unavailable. Retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: auth_unavailable, invalid_auth_format, invalid_duration, invalid_json, invalid_key_format, missing_api_key, missing_auth, part_size_mismatch, rate_limit_unavailable, session_not_uploading, size_mismatch, tag_too_long, too_many_tags, unauthorized, upload_reservation_missing.

POST/v1/audio/uploads/{sessionId}/part-urls

Get upload URLs for parts

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Returns one upload URL per requested part, at most 20 per call. Send each part's bytes with a PUT to its url, exactly as returned and with no API key (the URL is the credential), within 60 minutes. A part is exactly part_size_bytes long except the last one. A part can be sent again; the last copy wins. Ask again for fresh URLs if they expire. URLs are opaque: do not parse them. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.

Cost. Free of charge.

SESSIONID="YOUR_SESSIONID"
curl -X POST "https://api.scarleta.ai/v1/audio/uploads/$SESSIONID/part-urls" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "part_numbers": [
      1
    ]
  }'

Parameters

NameTypeRequiredDescription
sessionIdpathstringRequiredThe `session_id` returned when the session was created.

Request body

NameTypeRequiredDescription
part_numbersbodyarray<integer>RequiredParts to get URLs for, each between 1 and the session's `part_count`, at most 20 numbers.
Response fields
FieldTypeDescription
urlsarray<object>
urls[].part_numberintegerAllowed: -9007199254740991 to 9007199254740991.
urls[].urlstringWhere to `PUT` this part. Opaque; use it as returned.
urls[].expires_atstringISO 8601 timestamp.
Errors
StatusCodeDescription
400invalid_part_numbers`part_numbers` is empty, too long or has a number outside the session.
401invalid_keyMissing, malformed, unknown or revoked API key.
404upload_session_not_foundNo upload session with this id in your account. A session that belongs to another account is reported the same way.
409session_not_uploadingThe session is already completed or cancelled.
429rate_limit_exceededOver the account request budget. Wait for the `Retry-After` header, then retry.
503upload_unavailablePart URLs could not be created. Retry shortly.
Example responses
{
  "data": {
    "urls": [
      {
        "part_number": 1,
        "url": "https://storage.example.com/uploads/part-1?signature=…",
        "expires_at": "2026-10-21T04:40:00.000Z"
      }
    ]
  }
}
  • 200 One URL per requested part. The body is `{ data }` without `meta`.
  • 400 `part_numbers` is empty, too long or has a number outside the session.
  • 401 Missing, malformed, unknown or revoked API key.
  • 404 No upload session with this id in your account. A session that belongs to another account is reported the same way.
  • 409 The session is already completed or cancelled.
  • 429 Over the account request budget. Wait for the `Retry-After` header, then retry.
  • 503 Part URLs could not be created. Retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: auth_unavailable, invalid_auth_format, invalid_json, invalid_key_format, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.

PUT/v1/audio/uploads/{sessionId}/parts/{n}

Upload a part through the API

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Fallback target of a part URL. When a URL from the part-urls route points at this API instead of at storage, send the part bytes to it exactly as returned: it already carries the one-time t token, which is the credential, so there is no API key. The request needs a Content-Length header (without one it is refused with HTTP 411 missing_content_length) and a body no larger than part_size_bytes. Most accounts receive storage URLs and never call this route.

Cost. Free of charge.

SESSIONID="YOUR_SESSIONID"
N="YOUR_N"
curl -X PUT "https://api.scarleta.ai/v1/audio/uploads/$SESSIONID/parts/$N" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: audio/wav" \
  --data-binary @./recording.wav

Parameters

NameTypeRequiredDescription
sessionIdpathstringRequiredThe `session_id` of the session.
npathstringRequiredPart number, from 1 to the session's `part_count`.
tquerystringOptionalOne-time token. Already part of the URL that points here; leave it as returned.
Response fields
FieldTypeDescription
part_numberintegerAllowed: -9007199254740991 to 9007199254740991.
etagstringOpaque checksum of the stored part.
Errors
StatusCodeDescription
400invalid_part_numberThe part number is not within the session, or the body is missing.
403invalid_upload_tokenThe URL has expired, or the token is missing or wrong.
409session_not_uploadingThe session already completed or was cancelled.
413part_too_largeThe body is larger than `part_size_bytes`.
429rate_limit_exceededOver the account request budget. Wait for the `Retry-After` header, then retry.
503upload_unavailableStorage or the database is temporarily unavailable. Retry shortly.
Example responses
{
  "data": {
    "part_number": 1,
    "etag": "a54357aff0632cce46d942af68356b38"
  }
}
  • 200 The part is stored. The body is `{ data }` without `meta`.
  • 400 The part number is not within the session, or the body is missing.
  • 403 The URL has expired, or the token is missing or wrong.
  • 409 The session already completed or was cancelled.
  • 413 The body is larger than `part_size_bytes`.
  • 429 Over the account request budget. Wait for the `Retry-After` header, then retry.
  • 503 Storage or the database is temporarily unavailable. Retry shortly.

Try it

This operation uploads a file or binary body, which a browser form cannot build. Use the cURL sample.

Other error codes this operation can return: missing_body, missing_content_length, rate_limit_unavailable.