Do you have an AI agent? Downoad the SKILL.md file or copy and paste the prompt below to your agent to get started:
Integrate the DaDaScribe transcription API into this project.
Docs: https://api.dadascribe.com/
Base URL: https://api.dadascribe.com/v1
Auth: Authorization: Bearer <API_KEY> on all JSON requests (create a key manually at https://dadascribe.com/account/api.php).
Workflow:
1. POST /v1/transcribe — JSON body: source (YouTube URL/ID or direct audio URL; string or array of up to 10), source-language (required code), optional destination-language (comma-separated codes, max 5), optional diarization (comma-separated speaker names, min 2). Or multipart/form-data: file (single audio) plus a data form part with the same JSON object (omit source). Save the returned id.
2. Poll POST /v1/status with {"id":"..."} every few seconds until status is "complete" (or "error"). Rate limits: 60/min transcribe, 120/min status.
3. GET each URL in urls — no Authorization header. Downloads are .txt transcripts and .srt subtitles.
Errors use {"status":"error","message":"..."} with HTTP 401, 402, 403, 429, etc.
Build a small reusable client for our stack with config for the API key, polling with backoff, and file download. Ask me for our language/framework and where outputs should be stored.
You can also use the official DaDaScribe API wrapper in Python or CLI. Or use the OpenAPI JSON file for Postman and other tools.
The API is available on every plan, including the free plan. All you need is an API key — create one in your account settings to get started. Transcription time is deducted from your account balance.
The DaDaScribe API is versioned under /v1. JSON endpoints use POST with Content-Type: application/json.
POST /v1/transcribe also accepts multipart/form-data for direct audio/video file upload (one file per request).
File delivery uses GET on secure output URLs returned when a batch is complete.
Base URL:
https://api.dadascribe.com/v1
Each submission creates a batch with one public 16-character id and up to 10 transcription jobs (one per source URL).
Account time is deducted from your balance based on the combined duration of all sources in the batch.
Create an API key in your account settings. The full key is shown only once when created or replaced. Store it securely and make sure to use it on every JSON request.
Authorization: Bearer dds_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Note: Output file URLs do not require the Bearer header, they are capability URLs scoped to the batch id and filename.
Limits apply per API key (per minute), except output downloads which are limited per client IP.
| Endpoint | Limit |
|---|---|
POST /v1/transcribe | 60 requests / minute |
POST /v1/status | 120 requests / minute |
GET /v1/output/... | 600 requests / minute (per IP) |
When exceeded, the API returns HTTP 429 with
{ "status": "error", "message": "rate limit exceeded" }.
Response headers include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.
POST https://api.dadascribe.com/v1/transcribe
Submit one or more sources for transcription. Duplicate URLs in a batch are removed automatically (including equivalent YouTube URL forms). Alternatively, upload a single local audio/video file via multipart/form-data.
curl -sS -X POST 'https://api.dadascribe.com/v1/transcribe' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F 'file=@/path/to/recording.mp3' \
-F 'data={
"source-language": "en",
"destination-language": "en,fr",
"diarization": "Alice,Bob"
};type=application/json'
import json
import requests
params = {
'source-language': 'en',
'destination-language': 'en,fr',
'diarization': 'Alice,Bob',
}
with open('/path/to/recording.mp3', 'rb') as f:
response = requests.post(
'https://api.dadascribe.com/v1/transcribe',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
files={
'file': ('recording.mp3', f),
'data': (None, json.dumps(params), 'application/json'),
},
)
print(response.json())
const params = {
'source-language': 'en',
'destination-language': 'en,fr',
diarization: 'Alice,Bob',
};
const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('data', new Blob([JSON.stringify(params)], { type: 'application/json' }));
const response = await fetch('https://api.dadascribe.com/v1/transcribe', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: form,
});
const data = await response.json();
console.log(data);
One single audio/video file is allowed in the file field. Optionally, you may send source-language, destination-language, and diarization as separate form fields.
curl -sS -X POST 'https://api.dadascribe.com/v1/transcribe' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"source": "https://www.youtube.com/watch?v=VIDEO_ID",
"source-language": "en",
"destination-language": "it,fr",
"diarization": "Alice,Bob"
}'
import requests
response = requests.post(
'https://api.dadascribe.com/v1/transcribe',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'source': 'https://www.youtube.com/watch?v=VIDEO_ID',
'source-language': 'en',
'destination-language': 'it,fr',
'diarization': 'Alice,Bob',
},
)
print(response.json())
const response = await fetch('https://api.dadascribe.com/v1/transcribe', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: 'https://www.youtube.com/watch?v=VIDEO_ID',
'source-language': 'en',
'destination-language': 'it,fr',
diarization: 'Alice,Bob',
}),
});
const data = await response.json();
console.log(data);
curl -sS -X POST 'https://api.dadascribe.com/v1/transcribe' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"source": [
"https://www.youtube.com/watch?v=VIDEO_ID",
"https://example.com/podcast.mp3"
],
"source-language": "en",
"destination-language": "it"
}'
import requests
response = requests.post(
'https://api.dadascribe.com/v1/transcribe',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'source': [
'https://www.youtube.com/watch?v=VIDEO_ID',
'https://example.com/podcast.mp3',
],
'source-language': 'en',
'destination-language': 'it',
},
)
print(response.json())
const response = await fetch('https://api.dadascribe.com/v1/transcribe', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: [
'https://www.youtube.com/watch?v=VIDEO_ID',
'https://example.com/podcast.mp3',
],
'source-language': 'en',
'destination-language': 'it',
}),
});
const data = await response.json();
console.log(data);
| Parameter | Required | Description |
|---|---|---|
source |
yes* | YouTube URL or video ID, or a direct HTTP(S) link to an audio or video file. String for one source, or array for up to 10. Omit when uploading a file or when using s3_token. |
file |
yes* | Single audio/video file upload (multipart/form-data only). Supported extensions match direct file URLs below. Omit when using source. |
data |
yes† | Multipart only (for file upload): JSON string with the same fields as a JSON request (omit source). Use type=application/json on this part. |
source-language |
yes | Short code for the spoken language (see Languages). |
destination-language |
no | Comma-separated target language codes for translation (max 5). Omit for transcription only — defaults to the source language code. |
diarization |
no | Comma-separated speaker names for multiple-speaker diarization (minimum two names). Omit or send an empty string for none. |
* Provide source (JSON) or file (multipart), not both.
† With file upload, provide data (JSON part) or individual form fields for source-language, destination-language, and diarization.
mp3, wav, m4a, mp4, mov, mkv, webm, …). Max 10 GB.multipart/form-data file (PHP size cap ~480M). For larger files use /v1/upload/init → PUT to S3 → /v1/upload/complete → /v1/transcribe with s3_token.{
"status": "ok",
"id": "a1B2c3D4e5F6g7H8",
"count": 2
}
Save id — it is the public batch identifier used for status polling and output URLs.
{ "status": "error", "message": "no time left" }
HTTP 402 when the combined duration of all sources exceeds your account time balance.
POST https://api.dadascribe.com/v1/status
curl -sS -X POST 'https://api.dadascribe.com/v1/status' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{ "id": "a1B2c3D4e5F6g7H8" }'
import requests
response = requests.post(
'https://api.dadascribe.com/v1/status',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={'id': 'a1B2c3D4e5F6g7H8'},
)
print(response.json())
const response = await fetch('https://api.dadascribe.com/v1/status', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: 'a1B2c3D4e5F6g7H8' }),
});
const data = await response.json();
console.log(data);
status | Meaning |
|---|---|
queue | All jobs are waiting in the queue. |
processing | At least one job is being processed. |
complete | All jobs finished (urls array is returned). |
error | Batch not found, or one or more jobs failed. |
{
"status": "processing",
"count": 3,
"complete": 1,
"queue": 1,
"processing": 1
}
{
"status": "complete",
"count": 2,
"urls": [
"https://api.dadascribe.com/v1/output/a1B2c3D4e5F6g7H8/{file_unique_id}.txt",
"https://api.dadascribe.com/v1/output/a1B2c3D4e5F6g7H8/{file_unique_id}.srt",
"https://api.dadascribe.com/v1/output/a1B2c3D4e5F6g7H8/{file_unique_id}_it.srt"
]
}
Each job produces a plain-text transcript (.txt) and subtitles (.srt).
Translation requests add additional _{lang}.srt files per target language.
GET https://api.dadascribe.com/v1/output/{id}/{filename}
Download a completed file with a plain GET request. No Authorization header is required.
The job must be complete; otherwise the API returns HTTP 403 with { "status": "error", "message": "not ready" }.
Only .txt and .srt files associated with your batch id can be downloaded.
curl -sS -O 'https://api.dadascribe.com/v1/output/a1B2c3D4e5F6g7H8/{file_unique_id}.txt'
import requests
url = 'https://api.dadascribe.com/v1/output/a1B2c3D4e5F6g7H8/{file_unique_id}.txt'
response = requests.get(url)
response.raise_for_status()
with open('{file_unique_id}.txt', 'wb') as f:
f.write(response.content)
const url = 'https://api.dadascribe.com/v1/output/a1B2c3D4e5F6g7H8/{file_unique_id}.txt';
const response = await fetch(url);
const buffer = await response.arrayBuffer();
// save buffer to disk with your runtime's file API
POST /v1/transcribe — save the returned id.POST /v1/status with { "id": "..." } every few seconds (stay within rate limits).status is complete, GET each URL in urls.Use the Code value for source-language:
| Language | Code |
|---|---|
| Afrikaans | af |
| Albanian | sq |
| Arabic | ar |
| Armenian | hy |
| Assamese | as |
| Azerbaijani | az |
| Bashkir | ba |
| Basque | eu |
| Belarusian | be |
| Bengali | bn |
| Bosnian | bs |
| Breton | br |
| Bulgarian | bg |
| Catalan | ca |
| Chinese | zh |
| Croatian | hr |
| Czech | cs |
| Danish | da |
| Dutch | nl |
| English | en |
| Estonian | et |
| Faroese | fo |
| Finnish | fi |
| French | fr |
| Galician | gl |
| Georgian | ka |
| German | de |
| Greek | el |
| Gujarati | gu |
| Haitian Creole | ht |
| Hausa | ha |
| Hawaiian | haw |
| Hebrew | he |
| Hindi | hi |
| Hungarian | hu |
| Icelandic | is |
| Indonesian | id |
| Italian | it |
| Japanese | ja |
| Javanese | jw |
| Kannada | kn |
| Kazakh | kk |
| Khmer | km |
| Korean | ko |
| Lao | lo |
| Latin | la |
| Latvian | lv |
| Lingala | ln |
| Lithuanian | lt |
| Luxembourgish | lb |
| Macedonian | mk |
| Malagasy | mg |
| Malay | ms |
| Malayalam | ml |
| Maltese | mt |
| Maori | mi |
| Marathi | mr |
| Mongolian | mn |
| Myanmar | my |
| Nepali | ne |
| Norwegian | no |
| Nynorsk | nn |
| Occitan | oc |
| Pashto | ps |
| Persian | fa |
| Polish | pl |
| Portuguese | pt |
| Punjabi | pa |
| Romanian | ro |
| Russian | ru |
| Sanskrit | sa |
| Serbian | sr |
| Shona | sn |
| Sindhi | sd |
| Sinhala | si |
| Slovak | sk |
| Slovenian | sl |
| Somali | so |
| Spanish | es |
| Sundanese | su |
| Swahili | sw |
| Swedish | sv |
| Tagalog | tl |
| Tajik | tg |
| Tamil | ta |
| Tatar | tt |
| Telugu | te |
| Thai | th |
| Tibetan | bo |
| Turkish | tr |
| Turkmen | tk |
| Ukrainian | uk |
| Urdu | ur |
| Uzbek | uz |
| Vietnamese | vi |
| Welsh | cy |
| Yiddish | yi |
| Yoruba | yo |
Use comma-separated Code values for destination-language (max 5).
Destination codes must not include the source language. Source language will always be included in the destination languages.
| Language | Code |
|---|---|
| Afrikaans | af |
| Albanian | sq |
| Arabic | ar |
| Armenian | hy |
| Assamese | as |
| Azerbaijani | az |
| Bashkir | bh |
| Basque | eu |
| Belarusian | be |
| Bengali | bn |
| Bosnian | bs |
| Breton | br |
| Bulgarian | bg |
| Cantonese | yue |
| Catalan | ca |
| Cebuano | ceb |
| Cherokee | chr |
| Chichewa | ny |
| Chinese (Simplified) | zh-CN |
| Chinese (Traditional) | zh-TW |
| Corsican | co |
| Croatian | hr |
| Czech | cs |
| Danish | da |
| Dutch | nl |
| Dzongkha | dz |
| English | en |
| Esperanto | eo |
| Estonian | et |
| Faroese | fo |
| Filipino | fil |
| Finnish | fi |
| French | fr |
| Frisian | fy |
| Galician | gl |
| Georgian | ka |
| German | de |
| Greek | el |
| Guarani | gn |
| Gujarati | gu |
| Haitian Creole | ht |
| Hausa | ha |
| Hawaiian | haw |
| Hebrew | iw |
| Hindi | hi |
| Hmong | hmn |
| Hungarian | hu |
| Icelandic | is |
| Igbo | ig |
| Indonesian | id |
| Irish | ga |
| Italian | it |
| Japanese | ja |
| Javanese | jv |
| Kannada | kn |
| Kazakh | kk |
| Khmer | km |
| Kinyarwanda | rw |
| Korean | ko |
| Kurdish (Kurmanji) | ku |
| Kurdish (Sorani) | ckb |
| Kyrgyz | ky |
| Lao | lo |
| Latin | la |
| Latvian | lv |
| Lingala | li |
| Lithuanian | lt |
| Luxembourgish | lb |
| Macedonian | mk |
| Malagasy | mg |
| Malay | ms |
| Malayalam | ml |
| Maltese | mt |
| Maori | mi |
| Marathi | mr |
| Mongolian | mn |
| Myanmar (Burmese) | my |
| Nepali | ne |
| Norwegian | no |
| Nynorsk | nn |
| Occitan | oc |
| Odia (Oriya) | or |
| Pashto | ps |
| Persian | fa |
| Polish | pl |
| Portuguese | pt |
| Punjabi | pa |
| Romanian | ro |
| Romansh | rm |
| Russian | ru |
| Samoan | sm |
| Sanskrit | ss |
| Scots Gaelic | gd |
| Serbian | sr |
| Serrano | ser |
| Sesotho | st |
| Shona | sn |
| Sicilian | scn |
| Sindhi | sd |
| Sinhala | si |
| Slovak | sk |
| Slovenian | sl |
| Somali | so |
| Spanish | es |
| Sundanese | su |
| Swahili | sw |
| Swedish | sv |
| Tagalog | tl |
| Tajik | tg |
| Tamazight | ber |
| Tamil | ta |
| Tatar | tt |
| Telugu | te |
| Thai | th |
| Tibetan | bo |
| Turkish | tr |
| Turkmen | tk |
| Ukrainian | uk |
| Urdu | ur |
| Uyghur | ug |
| Uzbek | uz |
| Vietnamese | vi |
| Welsh | cy |
| Wolof | wo |
| Xhosa | xh |
| Yiddish | yi |
| Yoruba | yo |
| Zulu | zu |
All JSON errors use the shape { "status": "error", "message": "..." }.
| HTTP | Typical message | When |
|---|---|---|
400 | missing source, missing file, use either source or file upload, invalid source-language, invalid YouTube URL, etc. | Invalid or missing request parameters. |
401 | unauthorized | Missing or invalid API key. |
402 | no time left | Batch duration exceeds account balance. |
403 | not ready | Output requested before job completion. |
404 | job_not_found, not found | Unknown batch id or file. |
405 | method not allowed | Wrong HTTP method on a JSON endpoint. |
429 | rate limit exceeded | Too many requests in the current window. |
500 | internal error, etc. | Unexpected server error. |
Request and response shapes for each endpoint.
{
"source": "string | string[]", // required unless uploading a file — 1 URL/ID, or array of 1–10 URLs/IDs
"source-language": "string", // required — source language short code
"destination-language": "string", // optional — comma-separated codes, max 5; omit for transcription only
"diarization": "string" // optional — comma-separated speaker names (min 2), or ""
}
Content-Type: multipart/form-data
file: // required — single audio/video file
data: // recommended — same JSON as above, omit source; Content-Type: application/json
// alternative: individual form fields source-language, destination-language, diarization
{
"status": "ok", // literal
"id": "string", // 16-char alphanumeric public batch id
"count": "integer" // number of jobs queued (1–10)
}
{
"id": "string" // required — batch id from /v1/transcribe
}
queue){
"status": "queue",
"count": "integer", // total jobs in batch
"complete": "integer", // jobs finished
"queue": "integer", // jobs still waiting
"processing": "integer" // jobs currently running
}
processing){
"status": "processing",
"count": "integer",
"complete": "integer",
"queue": "integer",
"processing": "integer"
}
complete){
"status": "complete",
"count": "integer",
"urls": [ // flat list of download URLs for the whole batch
"string" // GET /v1/output/{id}/{filename}
]
}
error){
"status": "error",
"message": "string", // e.g. "job_not_found", "one or more transcriptions failed"
"count": "integer", // present when batch exists but jobs failed
"complete": "integer", // optional progress fields
"queue": "integer",
"processing": "integer"
}
Success returns the raw file stream (text/plain or application/x-subrip). Errors are JSON:
{
"status": "error",
"message": "string" // "invalid request" | "not found" | "not ready" | "invalid file"
}
All JSON endpoints use this shape on failure (including /v1/transcribe):
{
"status": "error",
"message": "string"
}