curl --request POST 'https://api.voicecheap.ai/v1/actions/transcription_result_download' \
--header "x-api-key: $VOICECHEAP_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"resultId":"b3caf96f-5f2a-4619-832c-a12c0d57f78b"}'
const input = {
resultId: 'b3caf96f-5f2a-4619-832c-a12c0d57f78b',
};
const response = await fetch('https://api.voicecheap.ai/v1/actions/transcription_result_download', {
method: 'POST',
headers: {
'x-api-key': process.env.VOICECHEAP_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
});
const body = await response.json();
if (!response.ok) throw new Error(body.code + ': ' + body.message);
console.log(body);
import os
import requests
response = requests.post(
"https://api.voicecheap.ai/v1/actions/transcription_result_download",
headers={"x-api-key": os.environ["VOICECHEAP_API_KEY"]},
json={"resultId": "b3caf96f-5f2a-4619-832c-a12c0d57f78b"},
timeout=120,
)
body = response.json()
if not response.ok:
raise RuntimeError(f"{body.get('code')}: {body.get('message')}")
print(body)
{
"data": {
"resultId": "b3caf96f-5f2a-4619-832c-a12c0d57f78b",
"operation": "transcription_create",
"createdAt": 1792152000000,
"fileName": "voicecheap-transcription_create-b3caf96f-5f2a-4619-832c-a12c0d57f78b.json",
"byteLength": 116,
"contentType": "application/json; charset=utf-8",
"status": "completed",
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"getAction": "transcription_result_get",
"downloadAction": "transcription_result_download",
"listAction": "transcription_result_list",
"content": "{\"transcript\":{\"raw\":\"Hello world.\",\"paragraphs\":\"Hello world.\",\"sentences\":\"Hello world.\",\"detectedLanguage\":\"en\"}}"
}
}
Transcription
Export a saved transcription action result
Export the complete owned result as JSON text with a filename and content type. Access remains authenticated; no public media URL exposes the transcript.
POST
/
v1
/
actions
/
transcription_result_download
curl --request POST 'https://api.voicecheap.ai/v1/actions/transcription_result_download' \
--header "x-api-key: $VOICECHEAP_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"resultId":"b3caf96f-5f2a-4619-832c-a12c0d57f78b"}'
const input = {
resultId: 'b3caf96f-5f2a-4619-832c-a12c0d57f78b',
};
const response = await fetch('https://api.voicecheap.ai/v1/actions/transcription_result_download', {
method: 'POST',
headers: {
'x-api-key': process.env.VOICECHEAP_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
});
const body = await response.json();
if (!response.ok) throw new Error(body.code + ': ' + body.message);
console.log(body);
import os
import requests
response = requests.post(
"https://api.voicecheap.ai/v1/actions/transcription_result_download",
headers={"x-api-key": os.environ["VOICECHEAP_API_KEY"]},
json={"resultId": "b3caf96f-5f2a-4619-832c-a12c0d57f78b"},
timeout=120,
)
body = response.json()
if not response.ok:
raise RuntimeError(f"{body.get('code')}: {body.get('message')}")
print(body)
{
"data": {
"resultId": "b3caf96f-5f2a-4619-832c-a12c0d57f78b",
"operation": "transcription_create",
"createdAt": 1792152000000,
"fileName": "voicecheap-transcription_create-b3caf96f-5f2a-4619-832c-a12c0d57f78b.json",
"byteLength": 116,
"contentType": "application/json; charset=utf-8",
"status": "completed",
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"getAction": "transcription_result_get",
"downloadAction": "transcription_result_download",
"listAction": "transcription_result_list",
"content": "{\"transcript\":{\"raw\":\"Hello world.\",\"paragraphs\":\"Hello world.\",\"sentences\":\"Hello world.\",\"detectedLanguage\":\"en\"}}"
}
}
Export the complete owned result as JSON text with a filename and content type. Access remains authenticated; no public media URL exposes the transcript.
Required permissions:
POST https://api.voicecheap.ai/v1/actions/transcription_result_download
Authentication and permissions
string
required
Send a VoiceCheap API key in this header. Authorization: Bearer with the same API key is also supported. OAuth access tokens are accepted only by
MCP, not by this REST endpoint.
transcription:read.
An active paid subscription is required. Permissions do not change team roles, resource ownership, media credits, or plan limits.
Parameters
string
required
Text value.Format: “uuid”. Pattern:
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$.Complete input schema
Complete input schema
The JSON Schema below preserves the exact field names, nested types, defaults, bounds, and accepted values exposed by discovery. Additional cross-field rules are listed in the operation notes.
{
"type": "object",
"properties": {
"resultId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"required": ["resultId"],
"additionalProperties": false
}
Request examples
Replace example resource identifiers and media keys with values returned for your account. Keep the request identifier stable when retrying the same mutation.curl --request POST 'https://api.voicecheap.ai/v1/actions/transcription_result_download' \
--header "x-api-key: $VOICECHEAP_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"resultId":"b3caf96f-5f2a-4619-832c-a12c0d57f78b"}'
const input = {
resultId: 'b3caf96f-5f2a-4619-832c-a12c0d57f78b',
};
const response = await fetch('https://api.voicecheap.ai/v1/actions/transcription_result_download', {
method: 'POST',
headers: {
'x-api-key': process.env.VOICECHEAP_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
});
const body = await response.json();
if (!response.ok) throw new Error(body.code + ': ' + body.message);
console.log(body);
import os
import requests
response = requests.post(
"https://api.voicecheap.ai/v1/actions/transcription_result_download",
headers={"x-api-key": os.environ["VOICECHEAP_API_KEY"]},
json={"resultId": "b3caf96f-5f2a-4619-832c-a12c0d57f78b"},
timeout=120,
)
body = response.json()
if not response.ok:
raise RuntimeError(f"{body.get('code')}: {body.get('message')}")
print(body)
Response
A successful first execution returns HTTP 200 with the operation result under data. A replay may return saved request state instead. The example shows one supported response, not every optional field. Saved output metadata with complete generated JSON serialized as a content string for an authenticated local export.{
"data": {
"resultId": "b3caf96f-5f2a-4619-832c-a12c0d57f78b",
"operation": "transcription_create",
"createdAt": 1792152000000,
"fileName": "voicecheap-transcription_create-b3caf96f-5f2a-4619-832c-a12c0d57f78b.json",
"byteLength": 116,
"contentType": "application/json; charset=utf-8",
"status": "completed",
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"getAction": "transcription_result_get",
"downloadAction": "transcription_result_download",
"listAction": "transcription_result_list",
"content": "{\"transcript\":{\"raw\":\"Hello world.\",\"paragraphs\":\"Hello world.\",\"sentences\":\"Hello world.\",\"detectedLanguage\":\"en\"}}"
}
}
Result fields
| Field | Description |
|---|---|
data.resultId | Owned saved-output UUID. Use it with getAction or downloadAction; it is distinct from requestId and any historyId. |
data.operation | Generation action that produced this saved JSON. |
data.createdAt | Unix timestamp in milliseconds when the saved output was prepared. |
data.fileName | Suggested filename for a JSON export. |
data.byteLength | UTF-8 bytes of the complete serialized output, not the compact metadata. |
data.contentType | application/json; charset=utf-8. |
data.status | completed on successful generation. Result history can also expose pending recovery entries. |
data.requestId | Original action request UUID when recorded. |
data.getAction | Owned retrieval action; includeContent defaults to false and must be true for complete structured output. |
data.downloadAction | Authenticated export action returning full JSON as a content string. |
data.listAction | Owned saved-output listing action for this permission domain. |
data.content | Complete original public generation result encoded as JSON text, ready to save to fileName. |
Operation notes
- Requires a paid subscription and the action permission. The actor’s personal tool plan is rechecked at execution; saved tools and upload references belong to that actor, including when the credential is associated with a team.
- A successful action uses one shared monthly API/MCP call. Beginner allows 500, Starter 5,000 and Creator 25,000 calls/month; Pro, Scale and Enterprise have no monthly ceiling. Per-minute limits still apply: 30, 60, 120, 180, 300 and 600 respectively. Tool generation allowances are separate.
- resultId is a UUID from a completed generation reference or this domain’s result_list. It is different from the action requestId and web-tool historyId.
- Results are owned by the authenticated actor and permission domain. A subtitles result cannot be read through transcription actions, or the reverse.
- Complete saved JSON is encrypted at rest and retained independently of the bounded action polling cache. Retrieval remains authenticated; no public transcript or caption JSON URL is issued.
- These actions retrieve existing output and do not generate media or use a daily allowance. Each successful retrieval still uses one monthly integration call.
- Pending metadata means output persistence needs recovery. Reading content or downloading attempts recovery of an already saved encrypted object; check it before starting another generation.
- Write content to fileName using UTF-8, or JSON.parse(content) to recover the structured output. The outer response does not contain a result property or a media download URL.
- byteLength describes the UTF-8 JSON inside content; contentType is application/json; charset=utf-8. Download also attempts recovery of pending encrypted output.
Usage
Each successful invocation consumes one monthly API/MCP call. Media credits and the operation’s own generation allowances also apply.Errors
| HTTP status | Code | Meaning or recovery |
|---|---|---|
| 400 | CREDENTIAL_IN_QUERY | Credentials were supplied in an access_token or api_key query parameter. Send credentials in headers. |
| 400 | VALIDATION_ERROR | Arguments do not satisfy the action schema, or an unknown argument was supplied. |
| 401 | API_KEY_EXPIRED | The API key has expired. |
| 401 | INVALID_API_KEY | Provide a valid, unexpired API key. |
| 401 | INVALID_CREDENTIAL | The Authorization header is malformed or conflicts with x-api-key. |
| 401 | MISSING_CREDENTIAL | No usable header credential was supplied, or it exceeded 4096 characters. |
| 401 | USER_NOT_FOUND | The credential’s account no longer exists. |
| 403 | AMBIGUOUS_TEAM_API_KEY | The credential’s user belongs to more than one team, so the billing context is ambiguous. |
| 403 | INSUFFICIENT_SCOPE | The API key or MCP connection lacks the required action permission. |
| 403 | INTEGRATION_PLAN_UNSUPPORTED | The account’s integration limits could not be verified. |
| 403 | PAID_SUBSCRIPTION_REQUIRED | The authenticated actor no longer has a paid subscription when this tool action executes. |
| 403 | SUBSCRIPTION_REQUIRED | Use an active paid subscription. |
| 403 | TEAM_OWNER_NOT_FOUND | The effective team owner account could not be found. |
| 404 | TOOL_RESULT_NOT_FOUND | The result is absent, belongs to another actor or belongs to the other permission domain. |
| 410 | TOOL_RESULT_ACCOUNT_UNAVAILABLE | The actor account is being deleted or no longer exists during recovery. |
| 429 | INTEGRATION_MONTHLY_LIMIT_REACHED | Used and pending calls have reached the shared monthly API/MCP allowance. |
| 429 | INTEGRATION_RATE_LIMIT_REACHED | The account has reached its per-minute integration limit; inspect retryAfterSeconds. |
| 500 | INTERNAL_ERROR | The saved completed JSON could not be read or validated. |
| 503 | INTERNAL_ERROR | A pending saved result cannot yet be recovered; inspect the same result before regenerating. |
| 503 | SERVER_RESTARTING | The server is restarting. Retry shortly and keep the same request identifier for a mutation. |
{
"code": "INSUFFICIENT_SCOPE",
"message": "This credential does not permit the requested action.",
"status": 403,
"details": {
"requiredScopes": ["transcription:read"]
}
}
Was this page helpful?

