-
Notifications
You must be signed in to change notification settings - Fork 11
docs: pipeline-generated pages (?, Languages, Voice) #423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| --- | ||
| title: "Query language support for a specific resource" | ||
| description: "Use the v3/languages endpoint to look up which languages and features are available for a specific DeepL API resource before you make translation requests." | ||
| covers: [Languages] | ||
| --- | ||
|
|
||
| The `/v3/languages` endpoint tells you which languages a given DeepL API resource supports and which optional features (formality, glossaries, tag handling, and more) are available per language. Calling it before you build language selectors or validate user input lets you stay current as DeepL adds languages, without maintaining a hardcoded list. | ||
|
|
||
| This guide shows you how to query language support for a resource, read the response, and check whether a specific feature is available for a language pair. | ||
|
|
||
| <Info> | ||
| The `resource` parameter is required. If you're migrating from `/v2/languages`, see the [migration guide](/docs/languages/migrating-from-v2-languages) — the v3 response structure is different. | ||
| </Info> | ||
|
|
||
| ## Before you start | ||
|
|
||
| You need a DeepL API key. Find yours on the [API Keys & Limits page](https://www.deepl.com/your-account/keys). If you're on the Free plan, use `https://api-free.deepl.com` instead of `https://api.deepl.com` in all requests below. | ||
|
|
||
| ## Step 1: Choose your resource | ||
|
|
||
| The `resource` parameter identifies which DeepL API product you're querying language support for. Choose the value that matches what you're building: | ||
|
|
||
| | **`resource` value** | **What it covers** | | ||
| |---|---| | ||
| | `translate_text` | Text translation via `/v2/translate` | | ||
| | `translate_document` | Document translation via `/v2/document` | | ||
| | `glossary` | Glossary management via `/v2/` and `/v3/glossaries` | | ||
| | `voice` | Speech transcription and translation via `/v3/voice` | | ||
| | `write` | Text improvement via `/v2/write` | | ||
| | `style_rules` | Style rules via the style rules endpoints | | ||
| | `translation_memory` | Translation memory features | | ||
|
|
||
| ## Step 2: Fetch supported languages | ||
|
|
||
| Call `GET /v3/languages` with your chosen `resource` value. This example queries languages for text translation: | ||
|
|
||
| ```sh | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Table left-alignment not specified for status/symbol columns The resource table uses default alignment (no explicit column alignment syntax). Per CLAUDE.md, text columns should be left-aligned. The table currently has no alignment row specified, which may render inconsistently depending on Mintlify defaults. Suggested fix: Add explicit column alignment to the table: |
||
| curl -X GET 'https://api.deepl.com/v3/languages?resource=translate_text' \ | ||
| --header 'Authorization: DeepL-Auth-Key [yourAuthKey]' | ||
| ``` | ||
|
|
||
| The response is an array where each object represents one language: | ||
|
|
||
| ```json | ||
| [ | ||
| { | ||
| "lang": "de", | ||
| "name": "German", | ||
| "status": "stable", | ||
| "usable_as_source": true, | ||
| "usable_as_target": true, | ||
| "features": { | ||
| "formality": { "status": "stable" }, | ||
| "glossary": { "status": "stable" }, | ||
| "tag_handling": { "status": "stable" } | ||
| } | ||
| }, | ||
| { | ||
| "lang": "en", | ||
| "name": "English", | ||
| "status": "stable", | ||
| "usable_as_source": true, | ||
| "usable_as_target": false, | ||
| "features": { | ||
| "glossary": { "status": "stable" }, | ||
| "tag_handling": { "status": "stable" } | ||
| } | ||
| }, | ||
| { | ||
| "lang": "en-US", | ||
| "name": "English (American)", | ||
| "status": "stable", | ||
| "usable_as_source": false, | ||
| "usable_as_target": true, | ||
| "features": { | ||
| "glossary": { "status": "stable" }, | ||
| "tag_handling": { "status": "stable" } | ||
| } | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BCP 47 link points to an internal docs path but uses a full URL pattern The BCP 47 link ( Suggested fix: Replace the absolute URL with a relative path: |
||
| A few things to notice in this response: | ||
|
|
||
| - `en` is source-only (`usable_as_source: true`, `usable_as_target: false`). For target languages, use a regional variant like `en-US` or `en-GB`. | ||
| - Language codes follow [BCP 47](https://developers.deepl.com/docs/resources/language-release-process). Don't assume codes are always two letters — treat them as opaque identifiers. | ||
| - The `features` object lists optional capabilities available for that language with this resource. A feature's absence means it isn't supported. | ||
|
|
||
| ## Step 3: Filter source and target languages | ||
|
|
||
| Use `usable_as_source` and `usable_as_target` to build your language selectors: | ||
|
|
||
| ```python | ||
| import requests | ||
|
|
||
| def get_languages(resource, auth_key): | ||
| response = requests.get( | ||
| "https://api.deepl.com/v3/languages", | ||
| params={"resource": resource}, | ||
| headers={"Authorization": f"DeepL-Auth-Key {auth_key}"}, | ||
| ) | ||
| response.raise_for_status() | ||
| return response.json() | ||
|
|
||
| languages = get_languages("translate_text", auth_key="[yourAuthKey]") | ||
|
|
||
| source_languages = [lang for lang in languages if lang["usable_as_source"]] | ||
| target_languages = [lang for lang in languages if lang["usable_as_target"]] | ||
|
|
||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Step 4 response block missing request context The JSON response block for GET /v3/languages/resources (lines ~115-129) is not preceded by a labeled 'Example response' heading or comment, making it easy to misread as a continuation of the curl request output. The two blocks (curl and JSON) are separated only by a blank line with no label. Suggested fix: Add a short label between the curl block and the JSON block, e.g. 'The response lists each resource and its feature requirements:' to mirror the pattern used in Step 2. |
||
| print("Source languages:", [lang["lang"] for lang in source_languages]) | ||
| print("Target languages:", [lang["lang"] for lang in target_languages]) | ||
| ``` | ||
|
|
||
| ## Step 4: Check feature availability for a language pair | ||
|
|
||
| Some features, like formality, depend on both the source and target language supporting it. To know which language must support a feature for it to be available, call `GET /v3/languages/resources`: | ||
|
|
||
| ```sh | ||
| curl -X GET 'https://api.deepl.com/v3/languages/resources' \ | ||
| --header 'Authorization: DeepL-Auth-Key [yourAuthKey]' | ||
| ``` | ||
|
|
||
| ```json | ||
| [ | ||
| { | ||
| "name": "translate_text", | ||
| "features": [ | ||
| { "name": "formality", "needs_target_support": true }, | ||
| { "name": "glossary", "needs_source_support": true, "needs_target_support": true }, | ||
| { "name": "tag_handling", "needs_source_support": true, "needs_target_support": true }, | ||
| { "name": "auto_detection", "needs_source_support": true } | ||
| ] | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| For `formality`, only `needs_target_support` is set. This means you only need to check whether the target language's `features` object contains `formality` — the source language doesn't matter. | ||
|
|
||
| For `glossary`, both `needs_source_support` and `needs_target_support` are set. Both languages in the pair must support `glossary` for you to use a glossary on that translation. | ||
|
|
||
| Here's a helper that combines both calls to check whether a feature is available for a given pair: | ||
|
|
||
| ```python | ||
| def is_feature_available(feature_name, source_lang, target_lang, resource_name, languages, resources): | ||
| # Find the feature's requirements from the resources list | ||
| resource_info = next(r for r in resources if r["name"] == resource_name) | ||
| feature_req = next( | ||
| (f for f in resource_info["features"] if f["name"] == feature_name), | ||
| None, | ||
| ) | ||
| if feature_req is None: | ||
| return False # Feature not defined for this resource | ||
|
|
||
| lang_map = {lang["lang"]: lang for lang in languages} | ||
|
|
||
| if feature_req.get("needs_source_support"): | ||
| source = lang_map.get(source_lang, {}) | ||
| if feature_name not in source.get("features", {}): | ||
| return False | ||
|
|
||
| if feature_req.get("needs_target_support"): | ||
| target = lang_map.get(target_lang, {}) | ||
| if feature_name not in target.get("features", {}): | ||
| return False | ||
|
|
||
| return True | ||
|
|
||
| # Example: can we use a glossary for EN → DE? | ||
| available = is_feature_available("glossary", "en", "de", "translate_text", languages, resources) | ||
| print(f"Glossary available for EN→DE: {available}") # True | ||
| ``` | ||
|
|
||
| ## Including beta languages | ||
|
|
||
| By default, the endpoint only returns stable languages. To include languages in beta, add `include=beta` to your request: | ||
|
|
||
| ```sh | ||
| curl -X GET 'https://api.deepl.com/v3/languages?resource=translate_text&include=beta' \ | ||
| --header 'Authorization: DeepL-Auth-Key [yourAuthKey]' | ||
| ``` | ||
|
|
||
| Beta languages appear in the response with `"status": "beta"`. Use the `status` field to decide whether to surface them to end users or restrict them to internal testing. | ||
|
|
||
| <Warning> | ||
| Don't hardcode the list of languages returned by this endpoint. New languages are added regularly — call the endpoint at startup (or on a schedule) and cache the result rather than maintaining a static list. See the [language release process](/docs/resources/language-release-process) for details on how DeepL introduces new languages. | ||
| </Warning> | ||
|
|
||
| ## Next steps | ||
|
|
||
| - See the full API reference: [Retrieve languages](/api-reference/languages/retrieve-languages-by-resource) and [Retrieve language resources](/api-reference/languages/retrieve-resources) | ||
| - Browse all languages the API currently supports: [Languages supported](/docs/getting-started/supported-languages) | ||
| - If you're coming from `/v2/languages`: [Migrating from v2/languages](/docs/languages/migrating-from-v2-languages) | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,161 @@ | ||||||||
| --- | ||||||||
| title: "Translate an Audio File with the Voice Translate Job API" | ||||||||
| description: "Submit a pre-recorded audio file for translation and download the results using the asynchronous Voice Translate Job API." | ||||||||
| covers: [Translate Audio Files] | ||||||||
| --- | ||||||||
|
|
||||||||
| The Voice Translate Job API translates pre-recorded audio files asynchronously. You submit a job, upload your audio file, poll for results, and download each output when it's ready. This guide walks through all four steps with a complete curl example. | ||||||||
|
|
||||||||
| Use this API for batch or offline workloads: podcasts, meeting recordings, video files, and similar pre-recorded content. For live audio, use the [real-time Voice API](/docs/voice/overview). | ||||||||
|
|
||||||||
| <Warning> | ||||||||
| This API is only available to select DeepL customers and may change without notice. See [alpha and beta features](/docs/resources/alpha-and-beta-features) for details, or contact your customer success manager to request access. | ||||||||
| </Warning> | ||||||||
|
|
||||||||
| ## Prerequisites | ||||||||
|
|
||||||||
| - A DeepL API account with Voice Translate Job API access | ||||||||
| - Your DeepL API key (set as `DEEPL_API_KEY` in the examples below) | ||||||||
| - A pre-recorded audio file in a [supported format](/api-reference/jobs-voice-translate/reference#supported-source-audio-formats) | ||||||||
|
|
||||||||
| For file size, duration, concurrency, and supported format constraints, see the [Translate Audio Files reference](/api-reference/jobs-voice-translate/reference#limits). | ||||||||
|
|
||||||||
| API Pro users call `https://api.deepl.com`. API Free users call `https://api-free.deepl.com` instead. | ||||||||
|
|
||||||||
| ## The four-step workflow | ||||||||
|
|
||||||||
| Every translation follows the same pattern: | ||||||||
|
|
||||||||
| 1. **Create a job** to declare your source file and desired outputs. The API returns an upload URL. | ||||||||
| 2. **Upload your audio file** directly to that URL. | ||||||||
| 3. **Poll for status** until all targets are complete (or failed). | ||||||||
| 4. **Download each result** from its download URL. | ||||||||
|
|
||||||||
| The sections below walk through each step. | ||||||||
|
|
||||||||
| ## Step 1: Create a job | ||||||||
|
|
||||||||
| Send a POST request to `/v1/jobs/voice/translate` with the source file metadata and your desired translation targets. | ||||||||
|
|
||||||||
| The `content_length` and `content_type` fields in `source_file` must match your actual file exactly. The API uses them to provision a pre-signed upload URL, so mismatches will cause the upload in step 2 to fail. | ||||||||
|
|
||||||||
| ```bash | ||||||||
| curl -X POST "https://api.deepl.com/v1/jobs/voice/translate" \ | ||||||||
| -H "Authorization: DeepL-Auth-Key $DEEPL_API_KEY" \ | ||||||||
| -H "Content-Type: application/json" \ | ||||||||
| -d '{ | ||||||||
| "source_file": { | ||||||||
| "name": "podcast-episode-42.mp3", | ||||||||
| "content_type": "audio/mpeg", | ||||||||
| "content_length": 15728640 | ||||||||
| }, | ||||||||
| "parameters": { | ||||||||
| "source_language": "en" | ||||||||
| }, | ||||||||
| "targets": [ | ||||||||
| { "language": "de", "type": "text/plain" }, | ||||||||
| { "language": "es", "type": "audio/pcm;encoding=s16le;rate=16000" } | ||||||||
| ] | ||||||||
| }' | ||||||||
| ``` | ||||||||
|
|
||||||||
| A successful response includes a `job_id`, an `upload_url`, and a `signature`: | ||||||||
|
|
||||||||
| ```json | ||||||||
| { | ||||||||
| "job_id": "a74d88fb-ed2a-4943-a664-a4512398b994", | ||||||||
| "signature": "eyJhbGciOiJIUzI1NiIs...", | ||||||||
| "upload_url": "https://assets.deepl.com/collections/a74d88fb-ed2a-4943-a664-a4512398b994/assets/b1c2d3e4-f5a6-7890-abcd-ef1234567890" | ||||||||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Upload expiry time limit inline in guide The sentence 'You have 5 minutes to complete the upload before the URL expires' is a numeric limit that belongs on the reference page, not in the how-to guide.
Suggested change
Save the |
||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| Save the `job_id` for polling and the `upload_url` for the next step. You have 5 minutes to complete the upload before the URL expires. | ||||||||
|
|
||||||||
| Each job can have multiple targets in different output types, so a single English recording can produce a German transcript, French subtitles, and Spanish audio in one request. See the [Translate Audio Files reference](/api-reference/jobs-voice-translate/reference) for the full list of output types and supported languages. | ||||||||
|
|
||||||||
| ## Step 2: Upload your audio file | ||||||||
|
|
||||||||
| PUT your audio file to the `upload_url` returned in step 1. Set `Content-Type` to the same value you declared in `source_file.content_type`. | ||||||||
|
|
||||||||
| Do not include your DeepL API key in the upload request. The URL is pre-signed and only requires the `Content-Type` header. Adding an `Authorization` header will cause the request to fail. | ||||||||
|
|
||||||||
| ```bash | ||||||||
| curl -X PUT "https://assets.deepl.com/collections/a74d88fb-ed2a-4943-a664-a4512398b994/assets/b1c2d3e4-f5a6-7890-abcd-ef1234567890" \ | ||||||||
| -H "Content-Type: audio/mpeg" \ | ||||||||
| --data-binary @podcast-episode-42.mp3 | ||||||||
| ``` | ||||||||
|
|
||||||||
| A `200 OK` response with no body means the upload succeeded. Processing starts automatically once the file is received. | ||||||||
|
|
||||||||
| ## Step 3: Poll for status | ||||||||
|
|
||||||||
| Check the job status by sending a GET request to `/v1/jobs/voice/translate/{job_id}`. Each target in the `results` array has its own `status` field that progresses independently. | ||||||||
|
|
||||||||
| ```bash | ||||||||
| curl "https://api.deepl.com/v1/jobs/voice/translate/a74d88fb-ed2a-4943-a664-a4512398b994" \ | ||||||||
| -H "Authorization: DeepL-Auth-Key $DEEPL_API_KEY" | ||||||||
| ``` | ||||||||
|
|
||||||||
| While targets are still processing, the response looks like this: | ||||||||
|
|
||||||||
| ```json | ||||||||
| { | ||||||||
| "job_id": "a74d88fb-ed2a-4943-a664-a4512398b994", | ||||||||
| "operation": "translate", | ||||||||
| "product": "voice", | ||||||||
| "parameters": { "source_language": "en" }, | ||||||||
| "source_file": { | ||||||||
| "name": "podcast-episode-42.mp3", | ||||||||
| "content_type": "audio/mpeg", | ||||||||
| "content_length": 15728640 | ||||||||
| }, | ||||||||
| "targets": [ | ||||||||
| { "language": "de", "type": "text/plain" }, | ||||||||
| { "language": "es", "type": "audio/pcm;encoding=s16le;rate=16000" } | ||||||||
| ], | ||||||||
| "results": [ | ||||||||
| { "status": "processing" }, | ||||||||
| { "status": "processing" } | ||||||||
| ], | ||||||||
| "created_at": "2026-10-01T01:03:03.444Z", | ||||||||
| "updated_at": "2026-10-01T04:03:03.333Z" | ||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| When a target completes, its result entry includes a `download_url` and `signature`: | ||||||||
|
|
||||||||
| ```json | ||||||||
| { | ||||||||
| "results": [ | ||||||||
| { | ||||||||
| "status": "complete", | ||||||||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Polling guidance mixes how-to and reference content The paragraph 'Poll every 10-30 seconds for files under 100 MB...' introduces numeric thresholds (100 MB, 10-30 seconds, several minutes) that are reference-level constraints. Per the API reference conventions in CLAUDE.md, numeric limits belong on the reference page, not in guides. The guide should give actionable polling advice without encoding specific limits inline. Suggested fix: Replace with: 'Poll every 10-30 seconds. For polling interval and file size guidance, see the Translate Audio Files reference. Keep polling until every result has reached a terminal status: |
||||||||
| "download_url": "https://assets.deepl.com/collections/a74d88fb/assets/c3d4e5f6", | ||||||||
| "signature": "eyJhbGciOiJIUzI1NiIs..." | ||||||||
| }, | ||||||||
| { | ||||||||
| "status": "failed", | ||||||||
| "error": { "message": "processing failed" } | ||||||||
| } | ||||||||
| ] | ||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| Results are returned in the same order as the `targets` array in your create request, so `results[0]` corresponds to `targets[0]`. | ||||||||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inline time limit for download window is a numeric constraint The sentence 'You have 1 hour from the time the upload completes to download all results' encodes a specific numeric limit inline in a how-to guide. Per CLAUDE.md conventions, numeric limits live on the reference/requirements page, not in guide prose.
Suggested change
|
||||||||
|
|
||||||||
| Poll every 10-30 seconds for files under 100 MB. Larger files or longer recordings may take several minutes. Keep polling until every result has reached a terminal status: `complete`, `failed`, or `downloaded`. | ||||||||
|
|
||||||||
| ## Step 4: Download results | ||||||||
|
|
||||||||
| For each target with `status: complete`, download the result from its `download_url`. No authentication header is needed — the URL is pre-signed. | ||||||||
|
|
||||||||
| ```bash | ||||||||
| # Download the German plain-text transcript | ||||||||
| curl -o translation_de.txt \ | ||||||||
| "https://assets.deepl.com/collections/a74d88fb/assets/c3d4e5f6" | ||||||||
| ``` | ||||||||
|
|
||||||||
| After you download a result, its status transitions to `downloaded` and the asset is queued for deletion. You have 1 hour from the time the upload completes to download all results. After that window, or once all results are downloaded, the job is deleted and returns `404`. | ||||||||
|
|
||||||||
| ## Handling partial failures | ||||||||
|
|
||||||||
| Individual targets can fail while others succeed. Check each result's `status` independently and handle `failed` results by reading the `error.message` field. You cannot retry a failed target within an existing job; you need to create a new job. | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Info box placement slightly delays key migration context
The Info callout about the required
resourceparameter and v2 migration appears after the opening two paragraphs. Developers who are migrating are likely to miss it since they may skim past the intro. The style guide recommends front-loading key information.Suggested fix: Move the Info box to immediately after the title/opening sentence, before the second paragraph that begins 'This guide shows you...' — or fold the migration note into the Before you start section as a brief sentence with the link.