Use DittoDub with an AI coding agent
Copy these Markdown instructions into Codex, Claude, or another coding agent. They cover authentication, project creation, polling, errors, and spending rules. Your API key is not included.
# DittoDub API setup
Human documentation: https://dittodub.com/docs/api
Base URL: https://api.dittodub.com
## Authentication
- Read the key from the DITTODUB_API_KEY environment variable.
- Send it as: x-api-key: $DITTODUB_API_KEY
- Never print, paste into source code, commit, or return the key in a response.
## Dubbing workflow
1. GET /v1/dubbing/locales and use the exact locale identifiers returned.
2. GET /v1/dubbing/projects or GET /v1/dubbing/youtube/videos to find existing work before creating a duplicate.
3. GET /v1/usage before billable work.
4. POST /v1/dubbing/projects with a unique Idempotency-Key.
5. For YouTube, set source to { "type": "youtube", "url": "https://..." }.
6. For a local video, create an upload source. PUT each part to its presigned URL, then POST the collected part numbers and ETags to the complete URL.
7. Poll GET /v1/dubbing/projects/{project_id}. Do not create another project while the first one is processing.
8. When a language is completed, use the download_url returned with each deliverable.
9. To add languages, POST /v1/dubbing/projects/{project_id}/languages with preview_only true. Show the exact quote to the user. After confirmation, repeat with preview_only false and an Idempotency-Key.
10. To request human review, POST /v1/dubbing/projects/{project_id}/transcript-review with preview_only true. This reviews only the English source transcript. Show the exact quote, then repeat with preview_only false and an Idempotency-Key after confirmation.
## Rules
- max_billable_seconds is a hard safety ceiling, not an estimate. If validated media exceeds it, the project fails before processing or charging.
- The language-add ceiling applies to the entire operation. Previewing never charges or changes a project.
- Source transcript review is available only while an English transcript is awaiting validation. It never requests review for target-language transcripts.
- Create requests are idempotent. Reuse the same Idempotency-Key only for the same request body.
- List endpoints use cursor pagination. Pass page.next_cursor as cursor until page.has_more is false.
- Errors use application/problem+json and include type, title, status, code, and request_id.
- Overall status can be awaiting_upload, validating, queued, processing, completed, partial, or failed.
- Each language has its own queued, processing, completed, or failed status.
## Endpoints
- GET /v1/dubbing/locales: exact supported locales; no authentication required
- GET /v1/dubbing/youtube/videos: search connected channels and identify matching projects
- GET /v1/usage: total, reserved, and available workspace credits
- POST /v1/dubbing/projects: create a YouTube or upload project
- GET /v1/dubbing/projects: list and filter projects
- GET /v1/dubbing/projects/{project_id}: status, usage, transfer, and completed files
- POST /v1/dubbing/projects/{project_id}/languages: preview or add target languages
- POST /v1/dubbing/projects/{project_id}/transcript-review: preview or submit the English source transcript to Ditto Verified
- GET /v1/dubbing/projects/{project_id}/download: stable authenticated file download
- POST /v1/dubbing/projects/{project_id}/upload/complete: finalize multipart upload
## Minimal YouTube request
curl "https://api.dittodub.com/v1/dubbing/projects" \
--request POST \
--header "x-api-key: $DITTODUB_API_KEY" \
--header "Idempotency-Key: YOUR_UNIQUE_OPERATION_ID" \
--header "Content-Type: application/json" \
--data '{
"name": "Launch video",
"external_id": "YOUR_INTERNAL_ID",
"source_locale": "en_us",
"target_locales": ["es_mx"],
"max_billable_seconds": 1800,
"source": { "type": "youtube", "url": "YOUTUBE_URL" }
}'
Before a POST that can spend credits, confirm the source, target locales, exact quote when available, and max_billable_seconds.Authentication
A backend uses a service key. An integration acting for a signed-in person uses an OAuth access token.
Service key
x-api-key: $DITTODUB_API_KEYOAuth access token
Authorization: Bearer $DITTODUB_ACCESS_TOKENDo not expose a service key in browser code, logs, prompts, or source control. Production requests should come from your server.
Project lifecycle
Create a project once, then poll it for status. Each target language progresses independently, so completed languages can be published while others continue processing.
Follow each language through the same four stages.
Each target language moves independently. The project response keeps usage, status, and completed files together.
1
Create
Start from YouTube or an uploaded source.
2
Validate
Measure the media and confirm usage.
3
Process
Track each target locale independently.
4
Publish
Download completed files as they are ready.
Errors
Error responses use
application/problem+json. Read the stable code in your application. Save the request_id with your logs so support can find the request.Example problem
{
"type": "https://api.dittodub.com/problems/unsupported-locale",
"title": "Invalid request",
"status": 400,
"detail": "target_locales contains unsupported locale 'es-us'.",
"code": "unsupported_locale",
"request_id": "req_01K2..."
}Pagination
List projects returns up to 50 items. When
page.has_more is true, pass page.next_cursor as the next request's cursor. Do not modify or reuse a cursor with different filters.