diff --git a/_assets/images/discord-logo-black.png b/_assets/images/discord-logo-black.png
new file mode 100644
index 00000000..03936731
Binary files /dev/null and b/_assets/images/discord-logo-black.png differ
diff --git a/_assets/images/discord-logo-white.png b/_assets/images/discord-logo-white.png
new file mode 100644
index 00000000..3518047c
Binary files /dev/null and b/_assets/images/discord-logo-white.png differ
diff --git a/api-reference/admin-api.mdx b/api-reference/admin-api.mdx
deleted file mode 100644
index 50c4c46d..00000000
--- a/api-reference/admin-api.mdx
+++ /dev/null
@@ -1,299 +0,0 @@
----
-title: "Admin API"
-public: true
-sidebarTitle: "Overview"
-description: "Explore DeepL API offering designed for admins"
----
-
-### Get started
-
-
- The Admin API is available to all API Growth and API Enterprise subscribers, and to a limited set of Pro API subscribers. To enable access, contact your DeepL customer success manager or DeepL support.
-
-
-Once the Admin API is enabled, follow the instructions in [Managing admin keys](/api-reference/admin-api/managing-admin-keys)
-to create an admin key. You will use the generated key for authentication in each request to the API.
-
-
- Note that managing admin keys themselves is currently available only in the self-admin area under the
- [“Admin Keys” tab](https://www.deepl.com/your-account/admin).
-
-
-With an admin key in hand, you are now ready to manage developer keys within your organization through the public API.
-
-### Managing developer keys
-
-The admin API keys allow admins to [manage developer API keys](/docs/getting-started/managing-api-keys) through DeepL API. These functionalities are equivalent to
-those available in the self-admin area under the ["API Keys & Limits" tab](https://www.deepl.com/your-account/keys).
-
-The Admin API currently consists of a single endpoint, `/v2/admin/developer-keys`, available under our API pro endpoint `https://api.deepl.com`.
-
-#### Create a developer key
-
-`POST /v2/admin/developer-keys`
-
-You can optionally give an API key a name of your choosing during the creation process. If you do not name the key, the
-name “DeepL API Key” will be given to the key automatically.
-
-Up to 25 simultaneously active API keys are allowed.
-
-
-
- ```sh Example request: Create a developer key as an admin
- curl -X POST 'https://api.deepl.com/v2/admin/developer-keys' \
- --header 'Authorization: DeepL-Auth-Key [yourAdminKey]' \
- --header 'Content-Type: application/json' \
- --data '{
- "label": "admin-key"
- }'
- ```
- ```json Example response
- {
- "key_id": "ca7d5694-96eb-4263-a9a4-7f7e4211529e:20c2abcf-4c3c-4cd6-8ae8-8bd2a7d4da38",
- "label": "developer key prod",
- "creation_time": "2025-07-08T08:15:29.362Z",
- "deactivated_time": "2025-07-09T08:15:29.362Z",
- "is_deactivated": true,
- "usage_limits": {
- "characters": 5000
- }
- }
- ```
-
-
- ```http
- POST /v2/admin/developer-keys HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAdminKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 123
- Content-Type: application/json
-
- {
- "label": "admin-key"
- }
- ```
-
-
-
-#### Get all developer keys
-
-`GET /v2/admin/developer-keys`
-
-This method will return both active and deactivated keys.
-
-
-
- ```sh Example request: Get all developer keys as an admin
- curl -X GET 'https://api.deepl.com/v2/admin/developer-keys' \
- --header 'Authorization: DeepL-Auth-Key [yourAdminKey]' \
- --header 'Content-Type: application/json'
- ```
- ```json Example response
- [
- {
- "key_id": "ca7d5694-96eb-4263-a9a4-7f7e4211529e:20c2abcf-4c3c-4cd6-8ae8-8bd2a7d4da38",
- "label": "developer key prod",
- "creation_time": "2025-07-08T08:15:29.362Z",
- "deactivated_time": "2025-07-09T08:15:29.362Z",
- "is_deactivated": true,
- "usage_limits": {
- "characters": 5000
- }
- }
- ]
- ```
-
-
- ```http
- GET /v2/admin/developer-keys HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAdminKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 123
- Content-Type: application/json
- ```
-
-
-
-#### Deactivate a developer key
-
-`PUT /v2/admin/developer-keys/deactivate`
-
-
- **IMPORTANT:** An API key will stop working immediately when deactivated. After a key is deactivated, it cannot be reactivated—deactivating a key is permanent!
-
-
-To deactivate a key, pass its ID in the request, as shown below. The key ID is composed of two GUIDs separated by the `:` symbol.
-
-
-
- ```sh Example request: Deactivate a developer key as an admin
- curl -X PUT 'https://api.deepl.com/v2/admin/developer-keys/deactivate' \
- --header 'Authorization: DeepL-Auth-Key [yourAdminKey]' \
- --header 'Content-Type: application/json' \
- --data '{
- "key_id": "GUID:GUID"
- }'
- ```
- ```json Example response
- {
- "key_id": "ca7d5694-96eb-4263-a9a4-7f7e4211529e:20c2abcf-4c3c-4cd6-8ae8-8bd2a7d4da38",
- "label": "developer key prod",
- "creation_time": "2025-07-08T08:15:29.362Z",
- "deactivated_time": "2025-07-09T08:15:29.362Z",
- "is_deactivated": true,
- "usage_limits": {
- "characters": 5000
- }
- }
- ```
-
-
- ```http
- PUT /v2/admin/developer-keys/deactivate HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAdminKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 123
- Content-Type: application/json
-
- {
- "key_id": "GUID:GUID"
- }
- ```
-
-
-
-#### Rename a developer key
-
-`PUT /v2/admin/developer-keys/label`
-
-To rename a key, pass its ID in the request and the new label, as shown below.
-The key ID is composed of two GUIDs separated by the `:` symbol.
-
-
-
- ```sh Example request: Rename a developer key as an admin
- curl -X PUT 'https://api.deepl.com/v2/admin/developer-keys/label' \
- --header 'Authorization: DeepL-Auth-Key [yourAdminKey]' \
- --header 'Content-Type: application/json' \
- --data '{
- "key_id": "GUID:GUID",
- "label": "admin-key-prod"
- }'
- ```
- ```json Example response
- {
- "key_id": "ca7d5694-96eb-4263-a9a4-7f7e4211529e:20c2abcf-4c3c-4cd6-8ae8-8bd2a7d4da38",
- "label": "developer key prod",
- "creation_time": "2025-07-08T08:15:29.362Z",
- "deactivated_time": "2025-07-09T08:15:29.362Z",
- "is_deactivated": true,
- "usage_limits": {
- "characters": 5000
- }
- }
- ```
-
-
- ```http
- PUT /v2/admin/developer-keys/label HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAdminKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 123
- Content-Type: application/json
-
- {
- "key_id": "GUID:GUID",
- "label": "admin-key-prod"
- }
- ```
-
-
-
-#### Set usage limits for a developer key
-
-`PUT /v2/admin/developer-keys/limits`
-
-Key-level limits restrict the number of total characters (across text translation, document translation, and text
-improvement) that can be consumed by an API key in a one-month usage period.
-
-For example, if you set a key-level usage limit of 1,000,000 characters, the API key will not consume more than 1,000,000 characters per usage period.
-
-The character count will "reset" at the start of the next usage period, at which point the key will again be able to consume characters.
-
-As with subscription-level cost control:
-
-* Developers will receive notification emails when 80% and 100% of a key-level limit has been reached
-* The API will respond with `456 Quota exceeded` errors when 100% of a key-level limit has been reached
-
-
- Setting the limit to `0` means the API key will not be able to consume characters.
-
-
-
- Setting the limit to `null` disables the limit, effectively allowing unlimited usage.
-
-
-
-
- ```sh Example request: Set usage limits for a developer key as an admin
- curl -X PUT 'https://api.deepl.com/v2/admin/developer-keys/limits' \
- --header 'Authorization: DeepL-Auth-Key [yourAdminKey]' \
- --header 'Content-Type: application/json' \
- --data '{
- "key_id": "GUID:GUID",
- "characters": 1000
- }'
- ```
-
- ```sh Example request: Prevent using a developer key as an admin
- curl -X PUT 'https://api.deepl.com/v2/admin/developer-keys/limits' \
- --header 'Authorization: DeepL-Auth-Key [yourAdminKey]' \
- --header 'Content-Type: application/json' \
- --data '{
- "key_id": "GUID:GUID",
- "characters": 0
- }'
- ```
-
- ```sh Example request: Allow unlimited usage of a developer key as an admin
- curl -X PUT 'https://api.deepl.com/v2/admin/developer-keys/limits' \
- --header 'Authorization: DeepL-Auth-Key [yourAdminKey]' \
- --header 'Content-Type: application/json' \
- --data '{
- "key_id": "GUID:GUID",
- "characters": null
- }'
- ```
- ```json Example response
- {
- "key_id": "ca7d5694-96eb-4263-a9a4-7f7e4211529e:20c2abcf-4c3c-4cd6-8ae8-8bd2a7d4da38",
- "label": "developer key prod",
- "creation_time": "2025-07-08T08:15:29.362Z",
- "deactivated_time": "2025-07-09T08:15:29.362Z",
- "is_deactivated": true,
- "usage_limits": {
- "characters": 5000
- }
- }
- ```
-
-
- ```http
- PUT /v2/admin/developer-keys/limits HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAdminKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 123
- Content-Type: application/json
-
- {
- "key_id": "GUID:GUID",
- "characters": 1000
- }
- ```
-
-
\ No newline at end of file
diff --git a/api-reference/admin-api/managing-admin-keys.mdx b/api-reference/admin-api/managing-admin-keys.mdx
deleted file mode 100644
index 6a820f04..00000000
--- a/api-reference/admin-api/managing-admin-keys.mdx
+++ /dev/null
@@ -1,88 +0,0 @@
----
-title: "Managing admin API keys"
-description: "Learn how admins can create and manage admin API keys."
-public: true
----
-
-### Get started
-
-Once the Admin API access has been enabled for your account, you can find and manage your admin API keys in the
-[“Admin Keys” tab](https://www.deepl.com/your-account/admin) when signed into your DeepL API account.
-It’s possible to have multiple, simultaneously active admin API keys in a single API subscription.
-
-
- 
-
-
-### Create new key
-
-Create a new admin API key by clicking on the "Create Key" button.
-You can optionally give an API key a custom name during the creation process.
-If you do not name the key, the name “DeepL Admin Key” will be given to the key automatically.
-
-You can create up to 25 simultaneously active admin API keys.
-
-
- 
-
-
-After creating a key, a popup with the newly created key will appear:
-
-
- 
-
-
-You can copy the key from this popup and use the key immediately.
-You can also copy the key from the table in the “Admin Keys” tab at any time.
-
-Note that the generated admin keys always have an *:adm* suffix, to distinguish them from the developer keys which do not have a suffix.
-
-Giving your API keys a name during the key creation process makes it possible for you to search for the key by name
-using the search bar on the “Admin Keys” tab:
-
-
- 
-
-
-### Deactivate key
-
-
- **IMPORTANT:** An API key will stop working immediately when deactivated. After a key is deactivated, it cannot be reactivated—deactivating a key is permanent!
-
-
-To deactivate an active admin API key:
-
-
- 
-
-
-
- 
-
-
-
- 
-
-
-### Rename key
-
-Allows you to edit the name of an API key. Note that it *is* possible for two keys to have the same name.
-
-Both active and deactivated keys can be renamed.
-
-
- 
-
-
- 
-
-
-### Copy key
-
-To copy an admin API key to your clipboard click the "Copy" icon next to the key.
-
-
- 
-
-
-For security reasons, we do not show the full key in the table in the “Admin Keys” tab. Both active and deactivated keys can be copied.
diff --git a/api-reference/admin-api/managing-developer-keys.mdx b/api-reference/admin-api/managing-developer-keys.mdx
deleted file mode 100644
index 2adfa1e0..00000000
--- a/api-reference/admin-api/managing-developer-keys.mdx
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "Managing developer API keys"
-description: "Learn how admins can create and manage developer API keys."
-public: true
----
-
-The admin keys allow admins to [manage developer API keys](/docs/getting-started/managing-api-keys) through DeepL API. These functionalities are equivalent to
-those available in the self-admin area under the ["API Keys & Limits" tab](https://www.deepl.com/your-account/keys):
-* Create a developer key
-* Get developer keys
-* Deactivate a developer key
-* Rename a developer key
-* Set developer key limits
diff --git a/api-reference/admin-api/organization-usage-analytics.mdx b/api-reference/admin-api/organization-usage-analytics.mdx
deleted file mode 100644
index 5752d435..00000000
--- a/api-reference/admin-api/organization-usage-analytics.mdx
+++ /dev/null
@@ -1,40 +0,0 @@
----
-title: "Accessing usage analytics"
-description: "Learn how admins can retrieve and analyze usage data across their organization."
-public: true
----
-
-The Admin API provides two endpoints for monitoring usage across your organization:
-
-- [Get usage analytics](/api-reference/admin-api/get-usage-analytics): retrieves total usage statistics, optionally grouped by API key or day
-- [Get custom tag usage analytics](/api-reference/admin-api/get-custom-tag-usage-analytics): retrieves usage statistics broken down by custom tags
-
-## Organization usage
-
-The [Get usage analytics](/api-reference/admin-api/get-usage-analytics) endpoint returns usage statistics for a specified date range with flexible grouping options. It covers all services: text translation, document translation, text improvement, and speech-to-text.
-
-## Custom tag usage
-
-Custom tags are an optional dimension for breaking down usage. If your organization wants to track consumption by team, project, or any other category, you can attach a single tag to individual API requests using the `X-DeepL-Reporting-Tag` header. Each request accepts one tag.
-
-The [Get custom tag usage analytics](/api-reference/admin-api/get-custom-tag-usage-analytics) endpoint only returns usage from tagged requests. Untagged requests are not included, so the results will reflect a subset of your organization's total usage unless all API requests are tagged.
-
-```bash
-curl --request POST \
- --url https://api.deepl.com/v2/translate \
- --header 'Authorization: DeepL-Auth-Key YOUR_AUTH_KEY' \
- --header 'X-DeepL-Reporting-Tag: your-custom-tag' \
- --header 'Content-Type: application/json' \
- --data '{
- "text": ["Hello, world!"],
- "target_lang": "DE"
- }'
-```
-
-
-Custom tag data is currently supported for text translation. Support for additional request types will be added in a future update.
-
-
-For a fuller walkthrough including naming guidance and current limitations, see [How to Use Custom Reporting Tags](/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags).
-
-Once tags are in place, query [Get custom tag usage analytics](/api-reference/admin-api/get-custom-tag-usage-analytics) to retrieve usage broken down by tag.
diff --git a/api-reference/document.mdx b/api-reference/document.mdx
deleted file mode 100644
index f0767ac7..00000000
--- a/api-reference/document.mdx
+++ /dev/null
@@ -1,348 +0,0 @@
----
-title: "Translate documents"
-sidebarTitle: "Overview"
-public: true
----
-
-The document translation API allows you to translate whole documents and supports the following file types and extensions:
-
-* `docx` / `doc` - Microsoft Word Document
-* `pptx` - Microsoft PowerPoint Document
-* `xlsx` - Microsoft Excel Document
-* `pdf` - Portable Document Format
-* `htm / html` - HTML Document
-* `txt` - Plain Text Document
-* `xlf / xliff` - XLIFF Document (versions 1.2, 2.0, and 2.1)
-* `srt` - SRT (SubRip Subtitle) Document
-* `idml` - Adobe InDesign Markup Language
-* `xml` - XML Document
-* `json` - JSON Document
-* `dita` - DITA topic (Darwin Information Typing Architecture)
-* `mif` - Adobe FrameMaker Interchange Format
-* `jpeg` / `jpg` / `png` - Image (currently in beta)
-
-Please note that with every submitted document of type .pptx, .docx, .doc, .xlsx, or .pdf, you are billed a minimum of 50,000 characters with the DeepL API plan, no matter how many characters are included in the document.
-
-The maximum upload limit for documents is [available here](/docs/resources/usage-limits#maximum-upload-limits-per-document-format) and may vary based on API plan and document type.
-
-We also provide specs that are auto-generated from DeepL's OpenAPI file. [You can find it here](/api-reference/document/upload-and-translate-a-document).
-
-
-When translating a `doc` file, you will receive a `docx` file as the output format.
-
-
-### Step 1: upload a document to the `/document` endpoint
-
-This call uploads a document and queues it for translation. The call returns once the upload is complete, returning a document ID and key which can be used to [query the translation status](/api-reference/document#step-2%3A-check-the-document-status-and-wait-for-translation-to-complete) and to [download the translated document](/api-reference/document#step-3%3A-download-the-translated-document) once translation is complete.
-
-Because the request includes a file upload, it must be an HTTP POST request with content type `multipart/form-data`.
-
-Please be aware that the uploaded document is automatically removed from the server once the translated document has been downloaded. You have to upload the document again in order to restart the translation.
-
-You may specify the glossary to use for the document translation using the `glossary_id` parameter. **Important:** This requires the `source_lang` parameter to be set and the language pair of the glossary has to match the language pair of the request.
-
-For more detail about request body parameters, see the [Request Body Descriptions](/api-reference/document#request-body-descriptions) section further down on the page.
-
-
-
-The examples below use our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```sh Example request: document upload (no glossary)
-curl -X POST 'https://api.deepl.com/v2/document' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---form 'target_lang=DE' \
---form 'file=@document.docx'
-```
-
-```sh Example request: document upload (with glossary)
-curl -X POST 'https://api.deepl.com/v2/document' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---form 'source_lang=EN' \
---form 'target_lang=DE' \
---form 'file=@document.docx' \
---form 'glossary_id=[yourGlossaryId]'
-```
-
-```json Example response
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "document_key": "0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"
-}
-```
-
-
-The examples below use our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```http Example request: document upload (no glossary)
-POST /v2/document HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: [length]
-Content-Type: multipart/form-data;boundary="boundary"
-
---boundary,Content-Disposition: form-data; name=target_lang
-
-DE
---boundary,Content-Disposition: form-data; name=file
-
-@document.docx
-```
-
-```http Example request: document upload (with glossary)
-POST /v2/document HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: [length]
-Content-Type: multipart/form-data;boundary="boundary"
-
---boundary,Content-Disposition: form-data; name=source_lang
-
-EN
---boundary,Content-Disposition: form-data; name=target_lang
-
-DE
---boundary,Content-Disposition: form-data; name=file
-
-@document.docx
---boundary,Content-Disposition: form-data; name=glossary_id
-
-[yourGlossaryId]
-```
-
-```json Example response
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "document_key": "0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"
-}
-```
-
-
-
-These examples are for demonstration purposes only. In production code, the authentication key should not be hard-coded but instead fetched from a configuration file or environment variable.
-
-#### Request Body Descriptions
-
-**Note:** the `model_type` parameter is not supported for API document translation and is only supported for [text translation](/api-reference/translate#about-the-model_type-parameter). It’s possible to submit a document translation request that includes the parameter, but the parameter will be ignored and will not have an effect on translation results.
-
-
- Language of the text to be translated. If omitted, the API will attempt to detect the language of the text and translate it. You can find supported languages here.
-
-
- The language into which the text should be translated. You can find supported languages here.
-
-
- The document file to be translated. The file name should be included in this part's content disposition. As an alternative, the filename parameter can be used.
- The following file types and extensions are supported:
-
- - `docx`: Microsoft Word Document
- - `pptx`: Microsoft PowerPoint Document
- - `xlsx`: Microsoft Excel Document
- - `pdf`: Portable Document Format
- - `htm / .html`: HTML Document
- - `txt`: Plain Text Document
- - `xlf / xliff`: XLIFF Document (versions 1.2, 2.0, and 2.1)
- - `srt` - SRT (SubRip Subtitle) Document
- - `idml`: Adobe InDesign Markup Language
- - `xml`: XML Document
- - `json`: JSON Document
- - `dita`: DITA topic (Darwin Information Typing Architecture)
- - `mif`: Adobe FrameMaker Interchange Format
- - `jpeg` / `jpg` / `png` - Image (currently in beta)
-
-
-
- The name of the uploaded file. Can be used as an alternative to including the file name in the file part's content disposition.
-
-
- Sets whether the translated text should lean towards formal or informal language. This feature currently only works for target languages `DE` (German), `FR` (French), `IT` (Italian), `ES` (Spanish), `NL` (Dutch), `PL` (Polish), `PT-BR` and `PT-PT` (Portuguese), `JA` (Japanese), and `RU` (Russian). Learn more about the plain/polite feature for Japanese here. Setting this parameter with a target language that does not support formality will fail, unless one of the `prefer_...` options are used. To check formality support dynamically, call GET /v3/languages?resource=translate_document and look for the formality feature key on the target language. Possible options are:
-
- - `default` (default)
- - `more` - for a more formal language
- - `less` - for a more informal language
- - `prefer_more` - for a more formal language if available, otherwise fallback to default formality
- - `prefer_less` - for a more informal language if available, otherwise fallback to default formality
-
-
-
- A unique ID assigned to a glossary. To check glossary support for a language pair, call GET /v3/languages?resource=translate_document and verify the glossary feature key is present on both the source and target language.
-
- Cannot be used together with glossary_ids.
-
-
-
- Specify up to 5 glossaries to use for the document translation, as an array of glossary IDs. Each glossary's matching terms are applied to the translated document.
-
- Important: This requires the source_lang parameter to be set, and every listed glossary must contain a dictionary for the requested language pair.
-
- Cannot be used together with glossary_id.
-
-
-
- Specify the style rule list to use for the translation which can be used to customize translations according to the selected formatting and style conventions.
-
- The target language has to match the language of the style rule list.
-
-
-
- The [translation memory](/api-reference/translation-memory/list-translation-memories) to use for the translation. The value should be the UUID of a translation memory associated with your account.
-
-
- The minimum matching percentage required for a translation memory segment to be applied (recommended to be 75% or higher). Accepts values from 0 to 100. Default: `75`.
-
-
- File extension of desired format of translated file, for example: `pdf`. If unspecified, by default the translated file will be in the same format as the input file.
- Note: Not all combinations of input file and translation file extensions are permitted. See Document format conversions for the permitted combinations.
-
-
-### Step 2: check the document status and wait for translation to complete
-
-Retrieve the current status of a document translation process.
-
-Please note that the `seconds_remaining` parameter is just an estimate and can be unreliable (e.g. sometimes it might return 2^27). We recommend polling the document status, either in regular intervals or with exponential back-off. Translation time depends on the document size and server load, but should be in the order of seconds for small documents and 1-2 minutes for larger documents once translation has started.
-
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```sh Example request: check document status
-curl -X POST 'https://api.deepl.com/v2/document/{document_id}' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---header 'Content-Type: application/json' \
---data '{
- "document_key": "0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"
-}'
-```
-
-```json Example response: translating
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "translating",
- "seconds_remaining": 20
-}
-```
-
-```json Example response: done
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "done",
- "billed_characters": 1337
-}
-```
-
-```json Example response: queued
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "queued"
-}
-```
-
-```json Example response: error
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "error",
- "message": "Source and target language are equal."
-}
-```
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```http Example request: check document status
-POST /v2/document/{document_id} HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: 83
-Content-Type: application/json
-
-{"document_key":"0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"}
-```
-
-```json Example response: translating
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "translating",
- "seconds_remaining": 20
-}
-```
-
-```json Example response: done
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "done",
- "billed_characters": 1337
-}
-```
-
-```json Example response: queued
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "queued"
-}
-```
-
-```json Example response: error
-{
- "document_id": "04DE5AD98A02647D83285A36021911C6",
- "status": "error",
- "message": "Source and target language are equal."
-}
-```
-
-
-
-### Step 3: download the translated document
-
-Once the status of the document translation process is `done`, the result can be downloaded.
-
-For privacy reasons the translated document is automatically removed from the server once it was downloaded and cannot be downloaded again.
-
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```sh Example request: download translated document
-curl -X POST 'https://api.deepl.com/v2/document/{document_id}/result' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---header 'Content-Type: application/json' \
---data '{
- "document_key": "0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"
-}'
-```
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```http Example request: download translated document
-POST /v2/document/{document_id}/result HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: 83
-Content-Type: application/json
-
-{"document_key":"0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"}
-```
-
-
-
-### Client libraries and document translation
-
-The examples on this page show how to translate documents with DeepL using the API directly.
-
-DeepL's [client libraries](/docs/getting-started/client-libraries) simplify API document translation by providing a convenience function to upload the document, check translation status and download the translated document with a single function call.
-
-### Document format conversions
-
-By default, the DeepL API returns translated documents in the same format as the input document.
-
-Using the `output_format` parameter during document upload, you can select alternative output formats. For example, you can translate a PDF file and receive the translation as an editable Microsoft Word Document (DOCX), allowing you to make additional changes as necessary.
-
-The range of alternative output formats you can select are indicated in the table below:
-
-| Input document format | Alternative output document formats |
-| --- | --- |
-| PDF | `docx` - Microsoft Word Document |
-| Others | None |
diff --git a/api-reference/improve-text.mdx b/api-reference/improve-text.mdx
index f8f6b9ae..720388b7 100644
--- a/api-reference/improve-text.mdx
+++ b/api-reference/improve-text.mdx
@@ -176,7 +176,7 @@ Yes. If you set a [Cost Control limit](/docs/best-practices/cost-control), it wi
#### Does the /usage endpoint response include Write API characters?
-Yes, the `character_count` field in the `/usage` endpoint response returns a sum of Translate API + Write API characters. You can learn more about the `/usage` endpoint [here](/api-reference/usage-and-quota).
+Yes, the `character_count` field in the `/usage` endpoint response returns a sum of Translate API + Write API characters. You can learn more about the `/usage` endpoint [here](/api-reference/usage-and-quota/check-usage-and-limits).
#### Do I access the DeepL Write API with the same API keys from my Pro API subscription?
@@ -184,7 +184,7 @@ Yes! The Write API is accessed using the same API keys in [the API Keys tab](htt
#### Can I see DeepL Write API usage in my reporting?
-We've added a new column to the [API key-level usage report](/docs/getting-started/managing-api-keys#get-api-key-level-usage) that breaks out text improvement characters separately. The character counts in the [Usage tab](https://www.deepl.com/your-account/usage) of your API account are a sum of both Translate *and* Write characters; these are not yet broken out separately.
+We've added a new column to the [API key-level usage report](/docs/admin/retrieving-usage-data#api-key-level-csv-export) that breaks out text improvement characters separately. The character counts in the [Usage tab](https://www.deepl.com/your-account/usage) of your API account are a sum of both Translate *and* Write characters; these are not yet broken out separately.
#### Is "Corrections Only" mode available in the API?
diff --git a/api-reference/jobs-voice-translate.mdx b/api-reference/jobs-voice-translate.mdx
index 4ea94182..6101ed23 100644
--- a/api-reference/jobs-voice-translate.mdx
+++ b/api-reference/jobs-voice-translate.mdx
@@ -15,7 +15,7 @@ The Voice Translate Job API translates pre-recorded audio files into any combina
- **SRT subtitles** (`application/x-subrip`) — preserves the original timecodes
- **Translated speech audio** — speech-to-speech in a range of audio and video container formats (see the [Reference](/api-reference/jobs-voice-translate/reference#supported-output-formats) for the full list)
-The API processes entire audio files asynchronously. This makes it suitable for pre-recorded content such as podcasts, meeting recordings, or other media files. For live audio, see the [real-time Voice API](/api-reference/voice).
+The API processes entire audio files asynchronously. This makes it suitable for pre-recorded content such as podcasts, meeting recordings, or other media files. For live audio, see the [real-time Voice API](/docs/voice/overview).
Each job can produce multiple outputs from a single source. For example, one English podcast can be translated into German plain text, French SRT subtitles, and Spanish audio in a single job.
@@ -366,4 +366,4 @@ Now that you understand how to translate audio files asynchronously:
- **Create a job:** Review the [Create Job endpoint reference](/api-reference/jobs-voice-translate/create-voice-translate-job) for the full request and response schema
- **Poll job status:** Review the [Get Job Status endpoint reference](/api-reference/jobs-voice-translate/get-voice-translate-job-status) for the full response schema
- **Look up limits and formats:** See the [Reference](/api-reference/jobs-voice-translate/reference) for status values, limits, supported audio formats, languages, and output formats
-- **Try realtime translation:** Use the [Voice API](/api-reference/voice) for streaming audio translation over WebSocket instead of batch processing
+- **Try realtime translation:** Use the [Voice API](/docs/voice/overview) for streaming audio translation over WebSocket instead of batch processing
diff --git a/api-reference/jobs-voice-translate/reference.mdx b/api-reference/jobs-voice-translate/reference.mdx
index 4792658b..ae8e97f0 100644
--- a/api-reference/jobs-voice-translate/reference.mdx
+++ b/api-reference/jobs-voice-translate/reference.mdx
@@ -46,7 +46,7 @@ Source audio over 3 hours is rejected, even if the file is under 1 GB. For longe
## Supported Languages
-Source and target languages match the [real-time Voice API](/api-reference/voice#supported-languages). `source_language` is optional; if omitted, the language is detected automatically.
+Source and target languages match the [real-time Voice API](/docs/voice/supported-languages-formats-and-limits#supported-languages). `source_language` is optional; if omitted, the language is detected automatically.
## Supported Output Formats
diff --git a/api-reference/style-rules.mdx b/api-reference/style-rules.mdx
index f83d9d50..aab27ede 100644
--- a/api-reference/style-rules.mdx
+++ b/api-reference/style-rules.mdx
@@ -921,7 +921,7 @@ Delete a specific custom instruction from a style rule list. This operation cann
### In translation requests
-To use a style rule list in a translation request, include its `style_id` parameter in your translation call. For more information on using style rules in translations, see the [translation documentation](/api-reference/translate).
+To use a style rule list in a translation request, include its `style_id` parameter in your translation call. For more information on using style rules in translations, see the [translation documentation](/api-reference/translate/request-translation).
```sh Example: translate with style rules
curl -X POST 'https://api.deepl.com/v2/translate' \
diff --git a/api-reference/translate.mdx b/api-reference/translate.mdx
deleted file mode 100644
index 3ec778c8..00000000
--- a/api-reference/translate.mdx
+++ /dev/null
@@ -1,537 +0,0 @@
----
-title: "Translate Text"
-sidebarTitle: "Overview"
-description: "API reference for translating text with the DeepL API."
-public: true
----
-
-The text-translation API currently consists of a single endpoint, `translate`, which is described below.
-
-For details on model selection, see the [`model_type` parameter](#about-the-model_type-parameter).
-
-To learn more about context in DeepL API translations, see our [context parameter guide](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter).
-
-For more detail about request body parameters, see the [Request Body Descriptions](/api-reference/translate#request-body-descriptions) section further down on the page.
-
-See [Translation memories](/docs/learning-how-tos/examples-and-guides/how-to-use-translation-memories) for a guide on using translation memories in your translations.
-
-We also provide a spec that is auto-generated from DeepL's OpenAPI file. [You can find it here](/api-reference/translate/request-translation).
-
-
-The total request body size for text translation requests must not exceed 128 KiB (128 · 1024 bytes). Please split up your text into multiple calls if it exceeds this limit.
-
-
-
-
-The examples below use our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```sh Example request: text translation (without glossary)
-curl -X POST 'https://api.deepl.com/v2/translate' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---header 'Content-Type: application/json' \
---data '{
- "text": [
- "Hello, world!"
- ],
- "target_lang": "DE"
-}'
-```
-
-```sh Example request: text translation (with glossary)
-curl -X POST 'https://api.deepl.com/v2/translate' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---header 'Content-Type: application/json' \
---data '{
- "text": [
- "Hello, world!"
- ],
- "target_lang": "DE",
- "source_lang": "EN",
- "glossary_id": "[yourGlossaryId]"
-}'
-```
-
-```json Example response
-{
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "Hallo, Welt!"
- }
- ]
-}
-```
-
-
-The examples below use our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```http Example request: text translation (without glossary)
-POST /v2/translate HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: 45
-Content-Type: application/json
-
-{"text":["Hello, world!"],"target_lang":"DE"}
-```
-
-```http Example request: text translation (with glossary)
-POST /v2/translate HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: 97
-Content-Type: application/json
-
-{"text":["Hello, world!"],"target_lang":"DE","source_lang":"EN","glossary_id":"[yourGlossaryId]"}
-```
-
-```json Example response
-{
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "Hallo, Welt!"
- }
- ]
-}
-```
-
-
-```py Example request: text translation (without glossary)
-import deepl
-
-auth_key = "f63c02c5-f056-..." # Replace with your key
-deepl_client = deepl.DeepLClient(auth_key)
-
-result = deepl_client.translate_text("Hello, world!", target_lang="FR")
-print(result.text) # "Bonjour, le monde !"
-```
-
-
-```php Example request: text translation (without glossary)
-$authKey = "f63c02c5-f056-..."; // Replace with your key
-$deeplClient = new DeepL\DeepLClient($authKey);
-
-$result = $deeplClient->translateText('Hello, world!', null, 'fr');
-echo $result->text; // Bonjour, le monde!
-```
-
-
-```cs Example request: text translation (without glossary)
-var authKey = "f63c02c5-f056-..."; // Replace with your key
-var deeplClient = new DeepLClient(authKey);
-
-// Translate text into a target language, in this case, French:
-var translatedText = await deeplClient.TranslateTextAsync(
- "Hello, world!",
- LanguageCode.English,
- LanguageCode.French);
-Console.WriteLine(translatedText); // "Bonjour, le monde !"
-// Note: printing or converting the result to a string uses the output text.
-```
-
-
-```javascript Example request: text translation (without glossary)
-import * as deepl from 'deepl-node';
-
-const authKey = "f63c02c5-f056-..."; // Replace with your key
-const deeplClient = new deepl.DeepLClient(authKey);
-
-(async () => {
- const result = await deeplClient.translateText('Hello, world!', null, 'fr');
- console.log(result.text); // Bonjour, le monde !
-})();
-```
-
-
-```java Example request: text translation (without glossary)
-import com.deepl.api.*;
-
-class Example {
- DeepLClient deeplClient;
-
- public Example() throws Exception {
- String authKey = "f63c02c5-f056-..."; // Replace with your key
- deeplClient = new DeepLClient(authKey);
- TextResult result =
- deeplClient.translateText("Hello, world!", null, "fr");
- System.out.println(result.getText()); // "Bonjour, le monde !"
- }
-}
-```
-
-
-
-These examples are for demonstration purposes only. In production code, the authentication key should not be hard-coded but instead fetched from a configuration file or environment variable.
-
-Note that we do not include examples for our client libraries in every single section of this reference, but our client libraries *do* support all use cases shown on this page.
-
-
- Please note that the Translate API is intended to be used for translation between different languages, but requests with the same source and target language are still counted toward billing.
-
- If trying to convert between variants of the same language (e.g. `EN-US` to `EN-GB`), please refer to [this guide](/docs/learning-how-tos/examples-and-guides/translating-between-variants). Translating between variants of the same language will result in no change to the text.
-
-
-### Request Body Descriptions
-
-
- Text to be translated. Only UTF-8-encoded plain text is supported. The parameter may be specified multiple times and translations are returned in the same order as they are requested. Each of the parameter values may contain multiple sentences. Up to 50 texts can be sent for translation in one request.
-
-
- Each text in the array is translated independently — texts do not share context with each other. If one text provides context that would help translate another (e.g. a headline and its article body), either combine them into a single text or use the context parameter to provide shared context.
-
-
-
- Language of the text to be translated. If omitted, the API will attempt to detect the language of the text and translate it. You can find supported source languages here.
-
-
- The language into which the text should be translated. You can find supported target languages here.
-
-
- The context parameter makes it possible to include additional context that can influence a translation but is not translated itself. This additional context can potentially improve translation quality when translating short, low-context source texts such as product names on an e-commerce website, article headlines on a news website, or UI elements.
-
- For example:
-
- - When translating a product name, you might pass the product description as context.
- - When translating a news article headline, you might pass the first few sentences or a summary of the article as context.
-
-
- For best results, we recommend sending a few complete sentences of context in the same language as the source text. There is no size limit for the context parameter itself, but the request body size limit of 128 KiB still applies to all text translation requests.
-
- If you send a request with multiple text parameters, the context parameter will be applied to each one.
-
- Characters included in the context parameter will not be counted toward billing (i.e., there is no additional cost for using the context parameter, and only characters sent in the text parameter(s) will be counted toward billing for text translation even when the context parameter is included in a request).
-
- See How to Use the Context Parameter Effectively for examples and best practices.
-
-
- Specifies which DeepL model should be used for translation.
-
- Possible values:
- - `latency_optimized`: Optimizes for the lowest latency (default parameter value)
- - `quality_optimized`: Optimizes for the highest translation quality
- - `prefer_quality_optimized`: Same as `quality_optimized`
-
- When the `model_type` parameter is set, the response includes a `model_type_used` field indicating which model was used.
-
- See [About the model_type parameter](#about-the-model_type-parameter) for more details.
-
-
- Sets whether the translation engine should first split the input into sentences. For text translations where tag_handling is not set to html, the default value is 1, meaning the engine splits on punctuation and on newlines.
-
- For text translations where tag_handling=html, the default value is nonewlines, meaning the engine splits on punctuation only, ignoring newlines.
-
- The use of nonewlines as the default value for text translations where tag_handling=html is new behavior that was implemented in November 2022, when HTML handling was moved out of beta.
-
- Possible values are:
-
- 0 - no splitting at all; whole input is treated as one sentence
- 1 (default when tag_handling is not set to html) - splits on punctuation and on newlines
- nonewlines (default when tag_handling=html) - splits on punctuation only, ignoring newlines
-
-
- For applications that send one sentence per text parameter, we recommend setting split_sentences to 0, in order to prevent the engine from splitting the sentence unintentionally.
-
- Please note that newlines will split sentences when split_sentences=1. We recommend cleaning files so they don't contain breaking sentences or setting the parameter split_sentences to nonewlines.
-
- Please note that this value may be overridden by the translation engine. When overridden, a value of:
-
- 0 will be used if tag_handling is not enabled
- nonewlines will be used if tag_handling is enabled
-
-
- ...as these settings yield the best quality.
-
-
- Sets whether the translation engine should respect the original formatting, even if it would usually correct some aspects.
- The formatting aspects affected by this setting include:
-
- - Punctuation at the beginning and end of the sentence
- - Upper/lower case at the beginning of the sentence
-
-
-
- Note: for requests sent as URL-encoded forms, boolean values should be specified as "1" or "0".
-
-
-
- Sets whether the translated text should lean towards formal or informal language. This feature currently only works for target languages DE (German), FR (French), IT (Italian), ES (Spanish), ES-419 (Latin American Spanish), NL (Dutch), PL (Polish), PT-BR and PT-PT (Portuguese), JA (Japanese), and RU (Russian). Learn more about the plain/polite feature for Japanese ↗️. To check formality support dynamically, call GET /v3/languages?resource=translate_text and look for the formality feature key on the target language.
-
- Setting this parameter with a target language that does not support formality will fail, unless one of the prefer_... options are used. Possible options are:
-
- default (default)
- more - for a more formal language
- less - for a more informal language
- prefer_more - for a more formal language if available, otherwise fallback to default formality
- prefer_less - for a more informal language if available, otherwise fallback to default formality
-
-
-
- Specify the glossary to use for the translation.
-
- Important: This requires the source_lang parameter to be set and the language pair of the glossary has to match the language pair of the request.
-
- Cannot be used together with glossary_ids.
-
- To check glossary support for a language pair, call GET /v3/languages?resource=translate_text and verify the glossary feature key is present on both the source and target language.
-
-
- Specify up to 5 glossaries to use for the translation, as an array of glossary IDs. Each glossary's matching terms are applied to the translation.
-
- Important: This requires the source_lang parameter to be set, and every listed glossary must contain a dictionary for the requested language pair.
-
- Cannot be used together with glossary_id.
-
-
-
- Specify the style rule list to use for the translation which can be used to customize translations according to the selected formatting and style conventions.
-
- The target language has to match the language of the style rule list.
-
-
-
-
- Specify a list of instructions to customize the translation behavior. Up to 10 custom instructions can be specified, each with a maximum of 300 characters.
-
-
- The target language must be `de`, `en`, `es`, `fr`, `it`, `ja`, `ko`, `zh` or any variants of these languages.
-
- You can find best practices on how to write custom instructions [here](/docs/best-practices/custom-instructions).
-
- To check language support dynamically, call GET /v3/languages?resource=translate_text and check for the style_rules feature key on the target language.
-
-
- The [translation memory](/api-reference/translation-memory/list-translation-memories) to use for the translation. The value should be the UUID of a translation memory associated with your account.
-
-
- The minimum matching percentage required for a translation memory segment to be applied (recommended to be 75% or higher). Accepts values from 0 to 100. Default: `75`.
-
-
- When true, the response will include an additional key-value pair with the key billed_characters and a value that is an integer showing the number of characters from the request that will be counted by DeepL for billing purposes.
-
- For example: "billed_characters": 42
-
- At some point in the future, we intend to include billed_characters in the API response by default, at which point it will be necessary to set show_billed_characters to false in order for an API response not to include billed_characters. We will notify users in advance of making this change.
-
- For requests sent as URL-encoded forms, boolean values should be specified as "1" or "0".
-
-
-
- Sets which kind of tags should be handled. Options currently available:
-
- To check tag handling support for a language pair, call GET /v3/languages?resource=translate_text and check the tag_handling feature key is present on both the source and target language.
-
-
- Select which version of the tag handling algorithm should be used. See tag handling v2.
-
- v2: Use the improved v2 algorithm.
- v1: Use the previous v1 algorithm.
-
- When `tag_handling` is set, the response includes a `tag_handling_version` field showing which version was applied, including the default when you don't specify one.
-
-
- The automatic detection of the XML structure won't yield best results in all XML files. You can disable this automatic mechanism altogether by setting the outline_detection parameter to false and selecting the tags that should be considered structure tags. This will split sentences using the splitting_tags parameter.
-
- In the example below, we achieve the same results as the automatic engine by disabling automatic detection with outline_detection=false and setting the parameters manually to tag_handling=xml, split_sentences=nonewlines, and splitting_tags=par,title.
-
- ```markup Example request
-
-
- A document's title
-
-
- This is the first sentence. Followed by a second one.
- This is the third sentence.
-
-
- ```
-
- ```markup Example response
-
-
- Der Titel eines Dokuments
-
-
- Das ist der erste Satz. Gefolgt von einem zweiten.
- Dies ist der dritte Satz.
-
-
- ```
-
- While this approach is slightly more complicated, it allows for greater control over the structure of the translation output.
-
-
- Note: For requests sent as URL-encoded forms, boolean values should be specified as "1" or "0".
-
-
-
- Comma-separated list of XML tags which never split sentences. Learn more
-
-
- Comma-separated list of XML tags which always cause splits. Learn more
-
-
- Comma-separated list of XML tags that indicate text not to be translated. Learn more
-
-
-
-### About the model\_type parameter
-
-The `model_type` parameter lets a user specify if they would like to optimize for speed until a request is served (latency) or translation quality. This is done on a best-effort basis by DeepL, not every language pair and feature must behave differently depending on this parameter.
-Currently, the DeepL translation API defaults to `latency_optimized` if no `model_type` is included in the request. All features and language pairs are compatible with all `model_type` values.
-Note that the API intentionally does not allow the user to specify a model, but rather their goal, so that the DeepL backend can choose the most suitable model for the user (this avoids users constantly having to update their code with new model versions and learning many different models name and their specifics).
-
-As of December 2025, all source and target languages are supported by next-gen models. Please note that DeepL reserves the right to quietly change which model serves e.g. a `model_type=quality_optimized` request, as long as we think it is a net benefit to the user (e.g. no significant latency increase, but a quality increase, or a significant latency reduction with no or only very slight decrease in quality).
-
-The `/languages` endpoint has not yet been updated to include information about `model_type` support, but we expect to make such a change in the future.
-
-### Multiple Sentences
-
-The translation function will (by default) try to split the text into sentences before translating. Splitting normally works on punctuation marks (e.g. "." or ";"), though you should not assume that every period will be handled as a sentence separator. This means that you can send multiple sentences as a value of the *text* parameter. The translation function will separate the sentences and return the whole translated paragraph.
-
-In some cases, the sentence splitting functionality may cause issues by splitting sentences where there is actually only one sentence. This is especially the case if you're using special/uncommon character sequences which contain punctuation. In this case, you can disable sentence splitting altogether by setting the parameter *split\_sentences* to *0*. Please note that this will cause overlong sentences to be cut off, as the DeepL API cannot translate overly long sentences. In this case, you should split the sentences manually before submitting them for translation.
-
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```sh Example request: multiple sentences
-curl -X POST 'https://api.deepl.com/v2/translate' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---header 'Content-Type: application/json' \
---data '{
- "text": [
- "The table is green. The chair is black."
- ],
- "target_lang": "DE"
-}'
-```
-
-```json Example response
-{
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "Der Tisch ist grün. Der Stuhl ist schwarz."
- }
- ]
-}
-```
-
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```http Example request: multiple sentences
-POST /v2/translate HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: 71
-Content-Type: application/json
-
-{"text": ["The table is green. The chair is black."],"target_lang":"DE"}
-```
-
-```json Example response
-{
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "Der Tisch ist grün. Der Stuhl ist schwarz."
- }
- ]
-}
-```
-
-
-
-### Translating Large Volumes of Text
-
-There are a few methods to translate larger volumes of text:
-
-* If your text is contiguous, you can submit whole paragraphs to be translated in one request and with one text parameter. Prior to translation, your text will be split into sentences and translated accordingly.
-* The translate function can take several text parameters and will return translations of each such parameter separately in the same order as they are requested (see example below). Each of the parameter values may contain multiple sentences. Up to 50 texts can be sent for translation per request.
-* You can make parallel requests by calling the translate function from several threads/processes.
-
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```sh Example request: large volumes of text
-curl -X POST 'https://api.deepl.com/v2/translate' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---header 'Content-Type: application/json' \
---data '{
- "text": [
- "This is the first sentence.",
- "This is the second sentence.",
- "This is the third sentence."
- ],
- "target_lang": "DE"
-}'
-```
-
-```json Example response
-{
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "Das ist der erste Satz."
- },
- {
- "detected_source_language": "EN",
- "text": "Das ist der zweite Satz."
- },
- {
- "detected_source_language": "EN",
- "text": "Dies ist der dritte Satz."
- }
- ]
-}
-```
-
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```http Example request: large volumes of text
-POST /v2/translate HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-Content-Length: 120
-Content-Type: application/json
-
-{"text":["This is the first sentence.","This is the second sentence.","This is the third sentence."],"target_lang":"DE"}
-```
-
-```json Example response
-{
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "Das ist der erste Satz."
- },
- {
- "detected_source_language": "EN",
- "text": "Das ist der zweite Satz."
- },
- {
- "detected_source_language": "EN",
- "text": "Dies ist der dritte Satz."
- }
- ]
-}
-```
-
-
-
-### In-Text Markup
-
-You should take precaution with uncommon characters you may have embedded in your texts. Uncommon character sequences, which may be recognized markers within your system, might get translated or removed, resulting in a corrupted structure. In this case, it is advisable to either split the text so that there is no need to send markers, or to convert your markers to XML tags and enable [XML handling](/docs/xml-and-html-handling/xml) or [HTML handling](/docs/xml-and-html-handling/html).
diff --git a/api-reference/usage-and-quota.mdx b/api-reference/usage-and-quota.mdx
deleted file mode 100644
index f7c3dbb1..00000000
--- a/api-reference/usage-and-quota.mdx
+++ /dev/null
@@ -1,79 +0,0 @@
----
-title: "Retrieve usage and quota"
-public: true
-sidebarTitle: "Overview"
-description: "API reference for retrieving usage and quota for the current billing period with the DeepL API."
----
-Retrieve usage information **within the current billing period** together with the corresponding account limits. For **Pro API users**, the `/usage`endpoint returns the following:
-
-* Text and document translation characters consumed in the current billing period in total _and_ for the API key used to make the request
-* Text improvement (`/write`) characters consumed in the current billing period in total _and_ for the API key used to make the request
-* Total characters consumed in the current billing period by the API key used to make the request
-* The key-level character limit for the API key used to make the request, if applicable (if a [key-level usage limit](../docs/getting-started/managing-api-keys#set-api-key-level-usage-limits) is set, it will be reflected in the `api_key_character_limit` field in the response; `1000000000000` will be returned if no key-level limit is set)
-* The current billing period start timestamp
-* The current billing period end timestamp
-* Total characters consumed in the current billing period
-* Subscription-level character limit that applies to the current billing period (if [Cost Control](../docs/best-practices/cost-control.md) is set, it will be reflected in the `character_limit` field in the response; `1000000000000` will be returned if no limit is set)
-
-An example request and response is shown below.
-
-
-Note that responses for Free API and Pro Classic users only contain `character_count` and `character_limit`.
-
-
-The value in the `character_count`field includes both text and document translations as well as text improvement (DeepL API for Write) characters. Characters are counted based on the source text length in Unicode code points, so for example "A", "Δ", "あ", and "深" are each counted as a single character.
-
-We also provide a spec that is auto-generated from DeepL's OpenAPI file. [You can find it here](/api-reference/usage-and-quota/check-usage-and-limits).
-
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```bash Example request: check usage and limits
-curl -X GET 'https://api.deepl.com/v2/usage' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]'
-```
-
-```json Example response
-{
- "products": [
- {
- "product_type": "write",
- "api_key_character_count": 1000000,
- "character_count": 1250000
- },
- {
- "product_type": "translate",
- "api_key_character_count": 880000,
- "character_count": 900000
- }
- ],
- "api_key_character_count": 1880000,
- "api_key_character_limit": 0,
- "start_time": "2025-04-24T14:58:02Z",
- "end_time": "2025-05-24T14:58:02Z",
- "character_count": 2150000,
- "character_limit": 20000000
-}
-```
-
-
-The example below uses our API Pro endpoint `https://api.deepl.com`. If you're an API Free user, remember to update your requests to use `https://api-free.deepl.com` instead.
-
-```http Example request: check usage and limits
-GET /v2/usage HTTP/2
-Host: api.deepl.com
-Authorization: DeepL-Auth-Key [yourAuthKey]
-User-Agent: YourApp/1.2.3
-```
-
-```json Example response
-{
- "character_count": 180118,
- "character_limit": 1250000
-}
-```
-
-
-
-If you are looking for general API limitations, please see [here](/docs/resources/usage-limits).
diff --git a/api-reference/usage-and-quota/check-usage-and-limits.mdx b/api-reference/usage-and-quota/check-usage-and-limits.mdx
index eedd165a..4ce465a9 100644
--- a/api-reference/usage-and-quota/check-usage-and-limits.mdx
+++ b/api-reference/usage-and-quota/check-usage-and-limits.mdx
@@ -1,4 +1,15 @@
---
openapi: get /v2/usage
title: "Check usage and limits"
----
\ No newline at end of file
+description: "Retrieve near-real-time character usage and account limits for the current billing period."
+---
+
+Returns usage within the current billing period together with the corresponding limits. Data is near-real-time: typically up to date within a few minutes of the usage being generated.
+
+Response behavior the schema alone doesn't convey:
+
+- For Pro API accounts, the response breaks usage down by product (`translate`, `write`) and reports both account totals and counts for the API key used to make the request. Responses for Free API and Pro Classic accounts contain only `character_count` and `character_limit`.
+- `character_count` sums text translation, document translation, and text improvement characters. Characters are counted from the source text length in Unicode code points, so "A", "Δ", "あ", and "深" each count as one character.
+- `character_limit` reflects a [Cost Control](/docs/best-practices/cost-control) limit if one is set; `api_key_character_limit` reflects a [key-level usage limit](/docs/admin/managing-api-keys#set-a-key-level-usage-limit) if one is set. Both fields return `1000000000000` when no limit is configured.
+
+For usage data beyond the current billing period, or broken down by key or custom tag, see [Retrieving Usage Data](/docs/admin/retrieving-usage-data). For general API limitations, see [Usage limits](/docs/resources/usage-limits).
diff --git a/api-reference/voice.mdx b/api-reference/voice.mdx
deleted file mode 100644
index 75fff3df..00000000
--- a/api-reference/voice.mdx
+++ /dev/null
@@ -1,401 +0,0 @@
----
-title: "Translate Speech in Realtime"
-sidebarTitle: "Overview"
-description: "API reference for real-time voice transcription and translation with the DeepL Voice API."
-public: true
----
-
-The Voice API provides real-time voice transcription and translation services using a WebSocket connection.
-
-
- The Voice API provides **speech-to-text** capabilities: real-time transcription and text translation of spoken audio. These features are available to all customers with a paid DeepL API subscription.
-
- **Speech-to-speech** (producing translated TTS output) is a separate capability currently in closed beta and not included in standard API subscriptions.
-
- Please note that the existing provisions applying to customers' DeepL API Enterprise subscription also apply to
- DeepL Voice API speech to text with the following applicable additions to the
- [Terms and Conditions, the Service Specification and the Data
- Processing Agreement](/api-reference/voice/deepl-voice-api-service-specification-updates)
- (as new sub-processors have been added to serve specific languages for the Voice API).
-
-
-## Overview
-
-The Voice API provides a way to open WebSocket connections to transcribe and translate audio data. With each connection, you can:
-
-* Send a single audio stream
-* Receive transcripts in the source language
-* Receive translations in multiple target languages
-* closed beta Receive translated speech
-
-The API uses a two-step flow:
-1. [**Request a streaming URL**](/api-reference/voice/request-session) via POST request
-2. [**Stream audio and text**](/api-reference/voice/websocket-streaming) via WebSocket
-
-## Getting Started
-
-To start using the Voice API:
-
-1. Ensure you have a DeepL API Pro account with Voice API access
-2. Review the [Request Session](/api-reference/voice/request-session) documentation
-3. Review the [WebSocket Streaming](/api-reference/voice/websocket-streaming) documentation
-4. Choose your audio format and configuration
-5. Implement the two-step flow in your application
-
-## Supported Languages
-
-We support a wide range of source and target languages (see below). However, while translation is always provided by
-DeepL, for some languages we use external service partners to provide transcription and translated speech.
-All source languages can be translated into any target language.
-
-
-| **Language** | **Transcription** | **Translation** | closed beta
Translated Speech |
-| :------------------------------------- | :---------------: | :-------------: | :------------------------------------------------------------: |
-| Arabic | ⎋ | ✓ | ⎋ |
-| Bengali | ⎋ | ✓ | — |
-| Bulgarian | ⎋ | ✓ | ⎋ |
-| Chinese (Simplified/Traditional) | ✓ | ✓ | ✓ |
-| Croatian | ⎋ | ✓ | — |
-| Czech | ✓ | ✓ | ⎋ |
-| Danish | ⎋ | ✓ | ⎋ |
-| Dutch | ✓ | ✓ | ✓ |
-| English (American/British) | ✓ | ✓ | ✓ |
-| Estonian | ⎋ | ✓ | — |
-| Finnish | ⎋ | ✓ | ⎋ |
-| French | ✓ | ✓ | ✓ |
-| German | ✓ | ✓ | ✓ |
-| Greek | ⎋ | ✓ | ⎋ |
-| Hebrew | ⎋ | ✓ | — |
-| Hindi beta | ⎋ | ✓ | ⎋ |
-| Hungarian | ⎋ | ✓ | ⎋ |
-| Indonesian | ✓ | ✓ | ⎋ |
-| Irish | ⎋ | ✓ | — |
-| Italian | ✓ | ✓ | ✓ |
-| Japanese | ✓ | ✓ | ✓ |
-| Korean | ✓ | ✓ | ✓ |
-| Latvian | ⎋ | ✓ | — |
-| Lithuanian | ⎋ | ✓ | — |
-| Malay beta | ⎋ | ✓ | ⎋ |
-| Maltese | ⎋ | ✓ | — |
-| Norwegian Bokmål | ⎋ | ✓ | ⎋ |
-| Polish | ✓ | ✓ | ✓ |
-| Portuguese (Brazil/Portugal) | ✓ | ✓ | ✓ |
-| Romanian | ✓ | ✓ | ⎋ |
-| Russian | ✓ | ✓ | ✓ |
-| Slovak | ⎋ | ✓ | ⎋ |
-| Slovenian | ⎋ | ✓ | — |
-| Spanish | ✓ | ✓ | ✓ |
-| Swedish | ✓ | ✓ | ✓ |
-| Thai | ⎋ | ✓ | — |
-| Tagalog | ⎋ | ✓ | — |
-| Tamil beta | ⎋ | ✓ | ⎋ |
-| Turkish | ✓ | ✓ | ✓ |
-| Ukrainian | ✓ | ✓ | ⎋ |
-| Vietnamese | ⎋ | ✓ | ⎋ |
-
-✓ provided by DeepL / ⎋ provided by an external service partner / — not available
-
-
-
- Transcription provided by external service partners (marked with ⎋) cannot yet auto-detect the source language,
- which you must therefore specify explicitly.
-
-
-To retrieve supported languages and feature availability programmatically, call [`GET /v3/languages?resource=voice`](/api-reference/languages/retrieve-supported-languages-by-resource) and check for the `transcription` and `translated_speech` feature keys. The external flag on these features indicates if they are provided by an external service partner.
-
-## Supported Audio Formats
-
-The API supports various common combinations of streaming codecs and containers with a single channel (mono) audio stream.
-For a detailed list of supported input audio formats, please refer to
-[Source Media Content Type](/api-reference/voice/request-session#body-source-media-content-type).
-For supported output audio formats refer to
-[Target Media Content Type](/api-reference/voice/request-session#body-target-media-content-type).
-
-| **Audio Codec** | **Audio Container** | **Recommended Bitrate** |
-| :--------------------------- | :---------------------------------- | :--------------------------------------------------- |
-| **PCM** | **-** | **256 kbps (16kHz), default recommendation** |
-| **OPUS** | **Matroska / MPEG-TS / Ogg / WebM** | **32 kbps, recommended for low bandwidth scenarios** |
-| AAC | Matroska / MPEG-TS | 96 kbps |
-| FLAC | FLAC / Matroska / Ogg | 256 kbps (16kHz) |
-| MP3 | MPEG / Matroska | 128 kbps |
-
-
-## Customization
-
-Two optional features let you tailor transcription and translation to your domain:
-
-* beta **Spoken terms** — Improve transcription of frequently used terms like company-specific terminology, acronyms, product names, and team member names. Manage in [DeepL Home](https://www.deepl.com/en/voice/spoken-terms); management via API coming soon.
-* **Glossaries** — Enforce specific translations for terms in the target language. Manage in [DeepL Home](https://www.deepl.com/en/glossary) or programmatically with the [Glossaries API](/api-reference/multilingual-glossaries).
-
-## Connecting
-
-The Voice API uses a two-step flow to initiate a session.
-
-
-
- Make a POST request `v3/voice/realtime` to obtain an ephemeral streaming URL and authentication token. The response will look like this:
-
- ```json
- {
- "streaming_url": "wss://api.deepl.com/v3/voice/realtime/connect",
- "token": "VGhpcyBpcyBhIGZha2UgdG9rZW4K",
- "session_id": "4f911080-cfe2-41d4-8269-0e6ec15a0354"
- }
- ```
-
- This step handles:
- * Authentication and authorization
- * Main configuration options (audio formats, languages, glossaries, spoken terms, message encoding, etc.)
-
-
- URL and token are valid for one-time use only.
-
-
- See the [Request Session](/api-reference/voice/request-session) documentation for details.
-
-
- Use the received URL to establish a WebSocket connection to `wss://api.deepl.com/v3/voice/realtime/connect?token=VGhpcyBpcyBhIGZha2UgdG9rZW4K`.
- This step handles exchanging messages on the WebSocket connection:
- * Sending audio data
- * Receiving transcripts, translations, and translated speech in real-time
-
- Messages are sent as TEXT frames (JSON) or BINARY frames (MessagePack), depending on the `message_format` configured in Step 1.
-
-
- Once a WebSocket connection is established, you must send audio data to prevent connection closure within 30 seconds.
-
-
- See the [WebSocket Streaming](/api-reference/voice/websocket-streaming) documentation for details.
-
-
-
-
-The following sequence diagram shows the complete flow.
-```mermaid
-sequenceDiagram
- participant Client
- participant Voice API
-
- Note over Client,Voice API: Step 1: Request Session (POST)
-
- Client->>Voice API: Configuration options
- Voice API->>Client: Streaming URL and token
-
- Note over Client,Voice API: Step 2: Start Streaming (WebSocket)
-
- Client->>Voice API: Establish WebSocket connection
using the streaming URL
-
- Note over Client,Voice API: WebSocket Connection Established
-
- Client<<->>Voice API: Bidirectional message exchange:
Send audio, receive transcripts,
translations, and speech
-
- Note over Client,Voice API: Stream Closed
-```
-
-
-## Streaming Audio and Text
-
-**Sending Source Audio**
-
-Continuously send audio using [source media chunk](/api-reference/voice/websocket-streaming) messages.
-Use smaller chunks to get a lower latency. The recommended chunk duration is 50-250 milliseconds for optimal performance.
-Send an [end of source media](/api-reference/voice/websocket-streaming) message to signal that the
-audio stream is complete and to finalize the processing.
-
-**Receiving Transcripts and Translations**
-
-As the audio is processed, transcripts and translations are delivered incrementally in real-time via
-[source transcript updates](/api-reference/voice/websocket-streaming) and
-[target transcript updates](/api-reference/voice/websocket-streaming):
-
-* **Concluded segments** - Finalized text that will not change. These segments are sent once and remain fixed.
-* **Tentative segments** - Preliminary text that may be refined as more audio context becomes available. These segments may be updated in subsequent messages.
-
-Applications typically merge finalized content into the complete transcript and can display tentative content as
-provisional that will be updated.
-
- closed beta **Receiving Translated Speech**
-
-Translated speech is delivered incrementally as speech-only audio via
-[target media chunks](/api-reference/voice/websocket-streaming). To save on bandwidth,
-the audio stream contains only synthesized speech without silence or padding. Depending on the
-source audio content there will be pauses w/o data delivered.
-
-Using the text and audio duration information in the response, you are able to mark currently spoken text in the
-received translations or subtitle audio output.
-
-
-The following sequence diagram shows the detailed message exchange during streaming.
-```mermaid
-sequenceDiagram
- participant Client
- participant Voice API
-
- Note over Client,Voice API: WebSocket Connection Established
-
- par
- loop Send audio data
- Client->>Voice API: source_media_chunk
- end
- and
- loop Receive updates
- Voice API-->>Client: source_transcript_update
- end
- and Per target language
- loop Receive updates
- Voice API-->>Client: target_transcript_update
- end
- and Per target language
- loop Receive translated speech
- Voice API-->>Client: target_media_chunk
- end
- end
-
- Client->>Voice API: end_of_source_media
-
- par
- loop Final updates
- Voice API-->>Client: source_transcript_update
- end
- and Per target language
- loop Final updates
- Voice API-->>Client: target_transcript_update
- end
- and Per target language
- loop Final audio chunks
- Voice API-->>Client: target_media_chunk
- end
- end
-
- Voice API-->>Client: end_of_source_transcript
-
- Voice API-->>Client: end_of_target_transcript
(once per target language)
-
- Voice API-->>Client: end_of_target_media
(once per target language)
-
- Voice API-->>Client: end_of_stream
-
- Note over Client,Voice API: Stream Closed
-```
-`par` means parallel execution and `loop` means looped execution.
-
-
-## Reconnecting
-
-Network connections are inherently unreliable.
-Disconnections are unavoidable and must be planned for.
-In case your connection gets disconnected, request a new authentication token to pick up where you left off.
-Make a GET request `v3/voice/realtime?token=`.
-The response will look like this:
-
-```json
-{
- "streaming_url": "wss://api.deepl.com/v3/voice/realtime/connect",
- "token": "VGhpcyBpcyBhIGZha2UgdG9rZW4K",
- "session_id": "4f911080-cfe2-41d4-8269-0e6ec15a0354"
-}
-```
-
-Use the received URL and token to establish a new WebSocket connection.
-Should another reconnection become necessary, repeat the procedure.
-
-See the [Reconnect Session](/api-reference/voice/reconnect-session) documentation for details.
-
-
-Always use the latest authentication token to request a new authentication token.
-The use of outdated tokens will invalidate your session for security reasons.
-
-
-
-If you still have an active connection, requesting a reconnection token will disconnect you.
-
-
-## Message Encoding
-
-The Voice API supports two message encoding formats for WebSocket communication.
-For best developer experience, we recommend starting with the default JSON format
-and later switch to MessagePack if you need better performance.
-
-
- WebSocket messages must be sent as TEXT frames when using JSON format, and as BINARY frames when using MessagePack format. Sending the wrong frame type will result in connection errors.
-
-
-**JSON (Default)**
-
-This format is human-readable and easy to debug.
-Messages are JSON-encoded and sent as **TEXT** WebSocket frames.
-Fields with binary data (such as audio chunks) are base64-encoded strings.
-
-**MessagePack**
-
-This format offers better bandwidth and performance characteristics.
-Messages are [MessagePack](https://msgpack.org/)-encoded and sent as **BINARY** WebSocket frames. **Messages must be encoded as maps with string keys, not arrays** - ensure your MessagePack library is configured correctly.
-Fields with binary data (such as audio chunks) contain raw binary data instead of base64-encoded strings.
-Compared to JSON, MessagePack typically reduces bandwidth usage by 25-30% and improves message
-encoding/decoding speed by 2x-4x.
-
-
-MessagePack messages **must be encoded as maps with string keys**,
-not as arrays. The message structure must match the JSON schema exactly, with all field names
-preserved as string keys (e.g., `{"source_media_chunk": {"data": }}`). Array-based encoding is not supported.
-
-Ensure your MessagePack library is configured to encode objects as maps rather than arrays.
-Some libraries default to array encoding for performance - check your library's documentation for the correct configuration.
-
-
-
-
-```javascript JSON
-// Raw binary audio data
-const audioData = getAudioChunk();
-
-// Base64 encode the audio data
-const base64Audio = btoa(audioData);
-
-const message = {
- source_media_chunk: {
- data: base64Audio
- }
-};
-
-// Send as TEXT frame
-websocket.send(JSON.stringify(message));
-```
-
-```javascript MessagePack
-import { pack } from 'msgpackr';
-
-// Raw binary audio data
-const audioData = getAudioChunk();
-
-const message = {
- source_media_chunk: {
- data: audioData // No base64 encoding needed
- }
-};
-
-// Send as BINARY frame
-websocket.send(pack(message));
-```
-
-
-
-## Usage Examples
-
-You can find a reference usage example for python at our
-[Github repository for the DeepL Python Library](https://github.com/DeepLcom/deepl-python/tree/main/examples/voice/cli).
-There's no integration of the Voice API in the official DeepL SDKs yet, but you can use any WebSocket client library
-to interact with the API.
-
-## Limitations and Constraints
-
-* Maximum 5 translation targets per session (including translated speech targets)
-* Maximum 1 translated speech target per session
-* Audio chunk size: should not exceed 100 kilobyte or 1 second duration
-* Recommended chunk duration: 50-250 milliseconds for low latency
-* Audio stream speed: maximum 2x real-time
-* Timeout: If no data is received for 30 seconds, the session will be terminated
-* Maximum connection duration: After 1 hour, the connection will be closed. You can establish a new connection by [reconnecting](/api-reference/voice/reconnect-session) to the session.
-* Using any given token more than once to establish a WebSocket connection will terminate the associated session immediately for security reasons.
-
-If you need more translation targets or translated speech targets than these limits allow, open multiple concurrent sessions over the same source audio.
diff --git a/docs.json b/docs.json
index fbf6e412..078764a1 100644
--- a/docs.json
+++ b/docs.json
@@ -3,7 +3,7 @@
"theme": "mint",
"name": "DeepL Documentation",
"banner": {
- "content": "[Join the Developer Community on DeepL Bridges](https://dee.pl/7iwrt)",
+ "content": "[Join the Developer Community on Discord](https://discord.gg/deepl)",
"dismissible": true
},
"colors": {
@@ -32,7 +32,8 @@
"navigation": {
"tabs": [
{
- "tab": "Documentation",
+ "tab": "Home",
+ "icon": "house",
"groups": [
{
"group": "Getting Started",
@@ -49,51 +50,6 @@
"docs/resources/language-release-process"
]
},
- {
- "group": "Translate",
- "pages": [
- {
- "group": "Text Translation",
- "pages": [
- "docs/learning-how-tos/examples-and-guides/translation-beginners-guide",
- "docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter",
- "docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags",
- "docs/learning-how-tos/examples-and-guides/translating-between-variants",
- "docs/learning-how-tos/examples-and-guides/customizations-for-variants",
- "docs/learning-how-tos/examples-and-guides/placeholder-tags",
- "docs/best-practices/language-detection"
- ],
- "drilldown": false
- },
- "docs/best-practices/document-translations",
- {
- "group": "XML & HTML",
- "pages": [
- "docs/xml-and-html-handling/xml",
- "docs/xml-and-html-handling/structured-content",
- "docs/xml-and-html-handling/html",
- "docs/xml-and-html-handling/customized-xml-outline-detection",
- "docs/xml-and-html-handling/tag-handling-v2"
- ],
- "drilldown": false
- }
- ]
- },
- {
- "group": "Customize",
- "pages": [
- "docs/learning-how-tos/examples-and-guides/glossaries-in-the-real-world",
- "docs/best-practices/custom-instructions",
- "docs/learning-how-tos/examples-and-guides/how-to-use-translation-memories"
- ]
- },
- {
- "group": "Admin",
- "pages": [
- "docs/getting-started/managing-api-keys",
- "docs/retrieving-usage-data"
- ]
- },
{
"group": "Going to Production",
"pages": [
@@ -150,8 +106,70 @@
}
]
},
+ {
+ "tab": "Translate",
+ "icon": "language",
+ "pages": [
+ "docs/translate/overview",
+ {
+ "group": "Text Translation",
+ "pages": [
+ "docs/translate/translate-text-quickstart",
+ "docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter",
+ "docs/translate/translating-large-volumes",
+ "docs/translate/understanding-model-types",
+ "docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags",
+ "docs/learning-how-tos/examples-and-guides/translating-between-variants",
+ "docs/learning-how-tos/examples-and-guides/customizations-for-variants",
+ "docs/learning-how-tos/examples-and-guides/placeholder-tags",
+ "docs/translate/translating-xml",
+ "docs/translate/translating-html",
+ "docs/best-practices/language-detection"
+ ]
+ },
+ {
+ "group": "Document Translation",
+ "pages": [
+ "docs/translate/translate-documents-quickstart",
+ "docs/best-practices/document-translations"
+ ]
+ },
+ {
+ "group": "Customize",
+ "pages": [
+ "docs/learning-how-tos/examples-and-guides/glossaries-in-the-real-world",
+ "docs/best-practices/custom-instructions",
+ "docs/learning-how-tos/examples-and-guides/how-to-use-translation-memories"
+ ]
+ }
+ ]
+ },
+ {
+ "tab": "Voice",
+ "icon": "waveform-lines",
+ "pages": [
+ "docs/voice/overview",
+ "docs/voice/real-time-voice-quickstart",
+ "docs/voice/understanding-voice-sessions",
+ "docs/voice/message-encoding",
+ "docs/voice/supported-languages-formats-and-limits"
+ ]
+ },
+ {
+ "tab": "Admin",
+ "icon": "sliders",
+ "pages": [
+ "docs/admin/overview",
+ "docs/admin/quickstart",
+ "docs/admin/managing-api-keys",
+ "docs/admin/api-key-permissions",
+ "docs/admin/permission-scopes",
+ "docs/admin/retrieving-usage-data"
+ ]
+ },
{
"tab": "API Reference",
+ "icon": "code",
"groups": [
{
"group": "Translate",
@@ -159,7 +177,6 @@
{
"group": "Translate Text",
"pages": [
- "api-reference/translate",
"api-reference/translate/request-translation"
],
"drilldown": false
@@ -167,7 +184,6 @@
{
"group": "Translate Documents",
"pages": [
- "api-reference/document",
"api-reference/document/upload-and-translate-a-document",
"api-reference/document/check-document-status",
"api-reference/document/download-translated-document"
@@ -239,7 +255,6 @@
{
"group": "Voice",
"pages": [
- "api-reference/voice",
"api-reference/voice/request-session",
"api-reference/voice/websocket-streaming",
"api-reference/voice/reconnect-session"
@@ -286,12 +301,9 @@
{
"group": "Admin",
"pages": [
- "api-reference/admin-api",
- "api-reference/admin-api/managing-admin-keys",
{
"group": "Managing Developer Keys",
"pages": [
- "api-reference/admin-api/managing-developer-keys",
"api-reference/admin-api/managing-developer-keys/create-key",
"api-reference/admin-api/managing-developer-keys/get-keys",
"api-reference/admin-api/managing-developer-keys/deactivate-key",
@@ -303,7 +315,6 @@
{
"group": "Usage & Quota",
"pages": [
- "api-reference/usage-and-quota",
"api-reference/usage-and-quota/check-usage-and-limits"
],
"drilldown": false
@@ -311,7 +322,6 @@
{
"group": "Organization Usage Analytics",
"pages": [
- "api-reference/admin-api/organization-usage-analytics",
"api-reference/admin-api/get-usage-analytics",
"api-reference/admin-api/get-custom-tag-usage-analytics"
],
@@ -345,21 +355,29 @@
{
"title": "Resources",
"items": [
- { "label": "API Status", "href": "https://api-status.deepl.com" },
- { "label": "DeepL Status", "href": "https://www.deeplstatus.com" }
+ {
+ "label": "API Status",
+ "href": "https://api-status.deepl.com"
+ },
+ {
+ "label": "DeepL Status",
+ "href": "https://www.deeplstatus.com"
+ }
]
}
],
"socials": {
"facebook": "https://www.facebook.com/DeepLcom/",
"linkedin": "https://www.linkedin.com/company/deepl",
- "github": "https://github.com/DeepLcom",
+ "github": "https://github.com/DeepL",
"instagram": "https://www.instagram.com/deeplhq/"
}
},
"api": {
"examples": {
- "languages": ["curl"],
+ "languages": [
+ "curl"
+ ],
"defaults": "required"
},
"playground": {
@@ -372,6 +390,58 @@
}
},
"redirects": [
+ {
+ "source": "/docs/xml-and-html-handling/xml",
+ "destination": "/docs/translate/translating-xml"
+ },
+ {
+ "source": "/docs/xml-and-html-handling/structured-content",
+ "destination": "/docs/translate/translating-xml"
+ },
+ {
+ "source": "/docs/xml-and-html-handling/customized-xml-outline-detection",
+ "destination": "/docs/translate/translating-xml"
+ },
+ {
+ "source": "/docs/xml-and-html-handling/tag-handling-v2",
+ "destination": "/docs/translate/translating-xml"
+ },
+ {
+ "source": "/docs/xml-and-html-handling/html",
+ "destination": "/docs/translate/translating-html"
+ },
+ {
+ "source": "/api-reference/voice",
+ "destination": "/docs/voice/overview"
+ },
+ {
+ "source": "/docs/getting-started/managing-api-keys",
+ "destination": "/docs/admin/managing-api-keys"
+ },
+ {
+ "source": "/docs/retrieving-usage-data",
+ "destination": "/docs/admin/retrieving-usage-data"
+ },
+ {
+ "source": "/api-reference/admin-api",
+ "destination": "/docs/admin/overview"
+ },
+ {
+ "source": "/api-reference/admin-api/managing-admin-keys",
+ "destination": "/docs/admin/managing-api-keys"
+ },
+ {
+ "source": "/api-reference/admin-api/managing-developer-keys",
+ "destination": "/api-reference/admin-api/managing-developer-keys/create-key"
+ },
+ {
+ "source": "/api-reference/admin-api/organization-usage-analytics",
+ "destination": "/docs/admin/retrieving-usage-data"
+ },
+ {
+ "source": "/api-reference/usage-and-quota",
+ "destination": "/api-reference/usage-and-quota/check-usage-and-limits"
+ },
{
"source": "/api-reference/languages/retrieve-supported-languages-by-product",
"destination": "/api-reference/languages/retrieve-supported-languages-by-resource"
@@ -438,19 +508,39 @@
},
{
"source": "/docs/learning-how-tos/examples-and-guides/deepl-api-101",
- "destination": "/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api"
+ "destination": "/docs/translate/translate-text-quickstart"
},
{
"source": "/docs/learning-how-tos/examples-and-guides/deepl-api-101/first-things-to-try-with-the-deepl-api",
- "destination": "/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api"
+ "destination": "/docs/translate/translate-text-quickstart"
},
{
"source": "/docs/resources/examples-and-guides/deepl-api-101",
- "destination": "/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api"
+ "destination": "/docs/translate/translate-text-quickstart"
},
{
"source": "/docs/resources/examples-and-guides/deepl-api-101/first-things-to-try-with-the-deepl-api",
- "destination": "/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api"
+ "destination": "/docs/translate/translate-text-quickstart"
+ },
+ {
+ "source": "/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api",
+ "destination": "/docs/translate/translate-text-quickstart"
+ },
+ {
+ "source": "/docs/learning-how-tos/examples-and-guides/translation-beginners-guide",
+ "destination": "/docs/translate/translate-text-quickstart"
+ },
+ {
+ "source": "/docs/translate/quickstart",
+ "destination": "/docs/translate/translate-text-quickstart"
+ },
+ {
+ "source": "/api-reference/translate",
+ "destination": "/api-reference/translate/request-translation"
+ },
+ {
+ "source": "/api-reference/document",
+ "destination": "/api-reference/document/upload-and-translate-a-document"
},
{
"source": "/docs/resources/examples-and-guides",
@@ -576,4 +666,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/docs/admin/api-key-permissions.mdx b/docs/admin/api-key-permissions.mdx
new file mode 100644
index 00000000..8e74b8b4
--- /dev/null
+++ b/docs/admin/api-key-permissions.mdx
@@ -0,0 +1,43 @@
+---
+title: "Understanding API Key Permissions"
+description: "Why scoped API keys exist, how DeepL enforces permission scopes, and when to choose a scoped key over an unrestricted one."
+public: true
+---
+
+API key permissions let you limit what a developer API key can do. Instead of one key with full access to every endpoint, you can issue keys that are scoped to specific operations, for example a key that can only translate text or a key that can only read glossaries. Permissions are available on the API Pro, API Developer, API Growth, and API Enterprise plans, and currently apply only to developer keys; [admin keys](/docs/admin/managing-api-keys#manage-admin-api-keys) can't be scoped.
+
+This page explains how the permissions model works. For the UI steps, see [Set key permissions](/docs/admin/managing-api-keys#set-key-permissions); for the full list of scopes, see [Permission Scopes](/docs/admin/permission-scopes).
+
+## Permissions and scopes
+
+Permissions are implemented as scopes. Each scope groups a set of related operations into a single capability you can grant to a key: `translate:text` covers text translation, `glossaries:read` covers reading glossaries, and so on. "Permissions" is the user-facing feature; "scopes" is the technical mechanism behind it.
+
+## Why scoped keys
+
+Before permissions were introduced in June 2026, every DeepL API key had full access to every endpoint. That's convenient, but it means a key embedded in a translation widget could also delete your glossaries, and a leaked key exposes your entire API surface.
+
+Scoped keys apply the principle of least privilege: each key gets exactly the access its workload needs. A scoped key that leaks, or a service with a bug, can only do what its scopes allow.
+
+| **Key type** | **Choose when** |
+| --- | --- |
+| Unrestricted | The key needs access to any endpoint and doesn't need to be limited |
+| Scoped | The key should reach only specific endpoints, for example to prevent glossaries from being modified inadvertently |
+
+## How enforcement works
+
+A developer key becomes scoped the moment you assign it one or more scopes. Once scoped:
+
+- The key can call only the endpoints fully covered by its scopes.
+- Every other endpoint returns `403 Forbidden`, including endpoints that have no scope requirement of their own (currently the case for Voice API endpoints).
+- Some endpoints require more than one scope. The key must hold all of them; if any is missing, the request is denied.
+
+When a scoped key calls an endpoint outside its scopes, the `detail` field of the response lists what's missing:
+
+```json
+{
+ "message": "Forbidden",
+ "detail": "Missing required scope(s): glossaries:write"
+}
+```
+
+Enforcement applies only to scoped keys. Unrestricted keys retain full access to every endpoint, and existing keys remain unrestricted until you assign them scopes. An account can hold any mix of scoped and unrestricted keys.
diff --git a/docs/admin/managing-api-keys.mdx b/docs/admin/managing-api-keys.mdx
new file mode 100644
index 00000000..5511bb35
--- /dev/null
+++ b/docs/admin/managing-api-keys.mdx
@@ -0,0 +1,122 @@
+---
+title: "Managing API Keys in the Account UI"
+sidebarTitle: "Managing API Keys"
+description: "Create, rename, deactivate, and set usage limits and permissions on DeepL API keys in the account UI."
+public: true
+---
+
+Manage your API keys in the ["API Keys & Limits" tab](https://www.deepl.com/your-account/keys) when signed into your DeepL API account. A single subscription can have multiple simultaneously active keys: up to 25 on Pro API plans and up to 2 on Free API plans.
+
+
+To create, deactivate, and limit developer keys programmatically instead, use the [Admin API](/docs/admin/overview#the-admin-api).
+
+
+
+
+
+
+## Create a key
+
+Click "Create key". You can optionally name the key during creation; if you don't, it's named "DeepL API Key" automatically. Naming keys lets you find them later using the search bar on the "API keys" tab.
+
+
+
+
+
+After you confirm, a popup shows the new key. Copy it from this popup to use it immediately, or copy it from the key table at any time.
+
+
+
+
+
+To create a key that can only access specific endpoints, select **Custom permissions** during creation. See [Set key permissions](#set-key-permissions).
+
+## Copy a key
+
+Click the "Copy" icon next to the key. For security reasons, the full key is never shown in the key table. Both active and deactivated keys can be copied.
+
+
+
+
+
+## Rename a key
+
+Select "Rename key" from the key's options menu. Both active and deactivated keys can be renamed, and two keys can share the same name.
+
+
+
+
+
+## Deactivate a key
+
+
+A key stops working immediately when deactivated, and deactivation is permanent: a deactivated key cannot be reactivated.
+
+
+Select "Deactivate key" from the key's options menu, then confirm.
+
+
+
+
+
+
+
+
+
+## Set a key-level usage limit
+
+Key-level limits cap the total characters (across text translation, document translation, and text improvement) a key can consume in a one-month usage period. For example, a key with a 1,000,000 character limit stops consuming at 1,000,000 characters and starts fresh when the next usage period begins. You can see your current usage period dates in the [API Usage tab](https://www.deepl.com/your-account/usage).
+
+To set a limit, select "Set limit" from the key's options menu, activate the limit, and enter a character amount. Setting the limit to 0 prevents the key from consuming any characters.
+
+
+
+
+
+
+
+
+
+As with subscription-level [cost control](/docs/best-practices/cost-control):
+
+- You receive notification emails when a key reaches 80% and 100% of its limit
+- The API responds with `456 Quota exceeded` errors once 100% of the limit is reached
+
+To monitor consumption against a limit, check the "Characters consumed" column in the key table or see [Retrieving Usage Data](/docs/admin/retrieving-usage-data).
+
+## Set key permissions
+
+Permissions restrict a developer key to specific endpoints. This section covers the UI steps; to understand how permissions are enforced, see [Understanding API Key Permissions](/docs/admin/api-key-permissions), and for what each scope covers, see [Permission Scopes](/docs/admin/permission-scopes).
+
+To create a scoped key, click "Create key", select **Custom permissions**, choose one or more scopes from the list, and confirm.
+
+
+
+
+
+To change permissions on an existing key, select "Edit permissions" from the key's options menu. Choose **All access** to make the key unrestricted, or **Custom permissions** to select specific scopes, then save.
+
+
+
+
+
+The "Permissions" column in the key table shows each key's status as a badge. Hover over a badge to see the assigned scopes.
+
+
+
+
+
+## Manage admin API keys
+
+If your account has [Admin API access](/docs/admin/overview#the-admin-api), you manage admin keys separately in the ["Admin Keys" tab](https://www.deepl.com/your-account/admin).
+
+
+
+
+
+Admin keys support the same actions as developer keys: create, copy, rename, and deactivate them from the "Admin Keys" tab exactly as described above. The differences:
+
+- Admin keys always end with an `:adm` suffix, which distinguishes them from developer keys
+- Unnamed admin keys are called "DeepL Admin Key" by default
+- You can create up to 25 simultaneously active admin keys on any plan with Admin API access
+- Usage limits and permissions don't apply to admin keys
diff --git a/docs/admin/overview.mdx b/docs/admin/overview.mdx
new file mode 100644
index 00000000..3977667b
--- /dev/null
+++ b/docs/admin/overview.mdx
@@ -0,0 +1,41 @@
+---
+title: "Admin"
+sidebarTitle: "Overview"
+description: "Manage API keys, control what each key can access, and monitor usage across your organization, from the account UI or programmatically with the Admin API."
+public: true
+---
+
+You can administer your DeepL API subscription in two ways:
+
+- **Account UI**: the [API Keys & Limits](https://www.deepl.com/your-account/keys) and [API Usage](https://www.deepl.com/your-account/usage) tabs of your DeepL account, available on all plans
+- **Admin API**: programmatic key management and usage analytics, for automating key provisioning, enforcing limits, and feeding usage data into your own dashboards or billing systems (see the [Admin API reference](/api-reference/admin-api/managing-developer-keys/create-key))
+
+## The Admin API
+
+The Admin API is available to all API Growth and API Enterprise subscribers, and to a limited set of Pro API subscribers. To enable access, contact your DeepL customer success manager or DeepL support.
+
+The Admin API uses its own key type: admin keys, which always carry an `:adm` suffix to distinguish them from developer keys. You create admin keys in the ["Admin Keys" tab](https://www.deepl.com/your-account/admin) of your account (see [Managing API Keys in the Account UI](/docs/admin/managing-api-keys#manage-admin-api-keys)) and pass them in the `Authorization` header of each request, just like developer keys:
+
+`Authorization: DeepL-Auth-Key [yourAdminKey]`
+
+Admin API endpoints are available on the Pro endpoint `https://api.deepl.com`. See the [Admin API reference](/api-reference/admin-api/managing-developer-keys/create-key) for request and response schemas.
+
+## Start here
+
+
+
+ Create a developer key, cap its usage, and pull a usage report in four API calls.
+
+
+ Create, rename, deactivate, and set usage limits on developer and admin keys in the account UI.
+
+
+ Understand how permission scopes restrict what a developer key can do.
+
+
+ Pick the right usage data source and pull consumption data for your account, keys, or custom tags.
+
+
+ Endpoint reference for programmatic key management and usage analytics.
+
+
diff --git a/docs/admin/permission-scopes.mdx b/docs/admin/permission-scopes.mdx
new file mode 100644
index 00000000..4fb1c3f7
--- /dev/null
+++ b/docs/admin/permission-scopes.mdx
@@ -0,0 +1,98 @@
+---
+title: "Permission Scopes"
+description: "Every permission scope for DeepL developer API keys and the endpoints each scope covers."
+public: true
+---
+
+Each scope grants a [scoped API key](/docs/admin/api-key-permissions) access to the endpoints listed under it. A scoped key can call only endpoints fully covered by its scopes; requests to any other endpoint return `403 Forbidden`.
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `POST` | [`/v2/translate`](/api-reference/translate/request-translation) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `POST` | [`/v2/document`](/api-reference/document/upload-and-translate-a-document) |
+ | `GET` | [`/v2/document/{document_id}`](/api-reference/document/check-document-status) |
+ | `GET` | [`/v2/document/{document_id}/result`](/api-reference/document/download-translated-document) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `POST` | [`/v2/write/rephrase`](/api-reference/improve-text/request-text-improvement) |
+ | `POST` | [`/v2/write/correct`](/api-reference/improve-text/correct-text) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `GET` | [`/v3/glossaries`](/api-reference/multilingual-glossaries/list-all-glossaries) |
+ | `GET` | [`/v3/glossaries/{glossary_id}`](/api-reference/multilingual-glossaries/retrieve-glossary-details) |
+ | `GET` | [`/v3/glossaries/{glossary_id}/entries`](/api-reference/multilingual-glossaries/retrieve-glossary-entries) |
+ | `GET` | [`/v2/glossaries`](/api-reference/glossaries/list-all-glossaries) |
+ | `GET` | [`/v2/glossaries/{glossary_id}`](/api-reference/glossaries/retrieve-glossary-details) |
+ | `GET` | [`/v2/glossaries/{glossary_id}/entries`](/api-reference/glossaries/retrieve-glossary-entries) |
+ | `GET` | [`/v2/glossary-language-pairs`](/api-reference/multilingual-glossaries/list-language-pairs-supported-by-glossaries) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `POST` | [`/v3/glossaries`](/api-reference/multilingual-glossaries/create-a-glossary) |
+ | `PATCH` | [`/v3/glossaries/{glossary_id}`](/api-reference/multilingual-glossaries/edit-glossary-details) |
+ | `PUT` | [`/v3/glossaries/{glossary_id}/dictionaries`](/api-reference/multilingual-glossaries/replaces-or-creates-a-dictionary-in-the-glossary-with-the-specified-entries) |
+ | `DELETE` | [`/v3/glossaries/{glossary_id}`](/api-reference/multilingual-glossaries/delete-a-glossary) |
+ | `DELETE` | [`/v3/glossaries/{glossary_id}/dictionaries`](/api-reference/multilingual-glossaries/deletes-the-dictionary-associated-with-the-given-language-pair-with-the-given-glossary-id) |
+ | `POST` | [`/v2/glossaries`](/api-reference/glossaries/create-a-glossary) |
+ | `DELETE` | [`/v2/glossaries/{glossary_id}`](/api-reference/glossaries/delete-a-glossary) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `GET` | [`/v3/style_rules`](/api-reference/style-rules/list-all-style-rules) |
+ | `GET` | [`/v3/style_rules/{style_id}`](/api-reference/style-rules/get-style-rule) |
+ | `GET` | [`/v3/style_rules/{style_id}/custom_instructions/{instruction_id}`](/api-reference/style-rules/get-custom-instruction) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `POST` | [`/v3/style_rules`](/api-reference/style-rules/create-style-rule) |
+ | `PATCH` | [`/v3/style_rules/{style_id}`](/api-reference/style-rules/update-style-rule) |
+ | `PUT` | [`/v3/style_rules/{style_id}/configured_rules`](/api-reference/style-rules/update-configured-rules) |
+ | `DELETE` | [`/v3/style_rules/{style_id}`](/api-reference/style-rules/delete-style-rule) |
+ | `POST` | [`/v3/style_rules/{style_id}/custom_instructions`](/api-reference/style-rules/create-custom-instruction) |
+ | `PUT` | [`/v3/style_rules/{style_id}/custom_instructions/{instruction_id}`](/api-reference/style-rules/update-custom-instruction) |
+ | `DELETE` | [`/v3/style_rules/{style_id}/custom_instructions/{instruction_id}`](/api-reference/style-rules/delete-custom-instruction) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `GET` | [`/v3/translation_memories`](/api-reference/translation-memory/list-translation-memories) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `GET` | [`/v3/languages`](/api-reference/languages/retrieve-languages-by-resource) |
+ | `GET` | [`/v3/languages/resources`](/api-reference/languages/retrieve-resources) |
+ | `GET` | [`/v2/languages`](/api-reference/languages/retrieve-supported-languages) |
+
+
+
+ | **Method** | **Endpoint** |
+ | --- | --- |
+ | `GET` | [`/v2/usage`](/api-reference/usage-and-quota/check-usage-and-limits) |
+
+
+
+
+No scope covers the Voice API yet, so Voice endpoints are accessible only with unrestricted keys. Voice scopes will be added in a future update.
+
diff --git a/docs/admin/quickstart.mdx b/docs/admin/quickstart.mdx
new file mode 100644
index 00000000..bfdfa53e
--- /dev/null
+++ b/docs/admin/quickstart.mdx
@@ -0,0 +1,189 @@
+---
+title: "Admin API Quickstart"
+description: "Create a developer API key, set a usage limit on it, and pull a per-key usage report in four calls to the Admin API."
+covers: [Admin]
+public: true
+---
+
+In this tutorial, we'll use the Admin API to provision a new developer API key for a team, set a character limit to control costs, and then retrieve a usage report to confirm activity. By the end, you'll have made four API calls that cover the core Admin API workflow.
+
+## What you'll learn
+
+- How to create a developer API key programmatically
+- How to apply a character usage limit to a key
+- How to retrieve an organization-wide usage report broken down by key
+- What the response objects look like at each step
+
+## Prerequisites
+
+- An API Growth or API Enterprise subscription, or a Pro API subscription with [Admin API access](/docs/admin/overview#the-admin-api)
+- An [**admin API key**](/docs/admin/managing-api-keys#manage-admin-api-keys) for your DeepL organization. Regular developer keys cannot access Admin API endpoints.
+- `curl` installed on your machine
+
+
+Responses in this tutorial are shown formatted. To pretty-print JSON in your terminal, install [jq](https://jqlang.org/) and pipe curl output through it: `curl ... | jq`
+
+
+## Building with an AI coding agent?
+
+Wire it up to the [DeepL Docs MCP Server](/docs/getting-started/docs-mcp-server) so it can search and read this documentation while it writes code. In Claude Code:
+
+```bash
+claude mcp add --transport http deepl-docs https://developers.deepl.com/mcp
+```
+
+Then describe what you want to build. To get the same result as this tutorial, paste:
+
+```text wrap
+Using the DeepL Admin API, write a script that creates a developer API key labeled "Staging Team Key", sets a 500,000 character usage limit on it, and then displays a per-key usage report for the last month.
+```
+
+## Step 1: List existing developer keys
+
+Before creating a new key, let's see what's already in the organization. This gives us a baseline and confirms that authentication is working.
+
+```bash
+curl https://api.deepl.com/v2/admin/developer-keys \
+ -H "Authorization: DeepL-Auth-Key YOUR_ADMIN_KEY"
+```
+
+You'll receive an array with one object per developer key, active and deactivated:
+
+```json
+[
+ {
+ "key_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890:1f2e3d4c-5b6a-7980-dcba-0987654321fe",
+ "label": "Production API Key",
+ "creation_time": "2026-05-12T09:41:03.512Z",
+ "deactivated_time": null,
+ "is_deactivated": false,
+ "usage_limits": {
+ "characters": null,
+ "speech_to_text_milliseconds": null
+ }
+ }
+]
+```
+
+Notice the `key_id` field, composed of two GUIDs separated by a `:` symbol. You'll use it to target specific keys in later steps. `null` usage limits mean no cap is set on that key.
+
+If you get a `403 Forbidden` response here, double-check that you're using an admin key with an `:adm` suffix, not a developer key.
+
+## Step 2: Create a new developer key
+
+Now let's create a key for a new team or service. We'll give it a descriptive label so it's easy to identify later.
+
+```bash
+curl https://api.deepl.com/v2/admin/developer-keys \
+ -H "Authorization: DeepL-Auth-Key YOUR_ADMIN_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{"label": "Staging Team Key"}'
+```
+
+The response returns the newly created key object:
+
+```json
+{
+ "key_id": "f9e8d7c6-b5a4-3210-fedc-ba9876543210:0a1b2c3d-4e5f-6789-abcd-ef0123456789",
+ "label": "Staging Team Key",
+ "creation_time": "2026-07-09T10:02:47.118Z",
+ "deactivated_time": null,
+ "is_deactivated": false,
+ "usage_limits": {
+ "characters": null,
+ "speech_to_text_milliseconds": null
+ }
+}
+```
+
+Copy the `key_id` from this response. You'll need it in the next step.
+
+## Step 3: Set a character usage limit
+
+By default, a new key has no usage cap. Let's set a character limit so the staging key can't consume more quota than intended.
+
+Replace `KEY_ID` with the `key_id` from the previous step.
+
+```bash
+curl https://api.deepl.com/v2/admin/developer-keys/limits \
+ -X PUT \
+ -H "Authorization: DeepL-Auth-Key YOUR_ADMIN_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "key_id": "KEY_ID",
+ "characters": 500000
+ }'
+```
+
+The response returns the updated key object. Confirm that `usage_limits.characters` now shows `500000`:
+
+```json
+{
+ "key_id": "f9e8d7c6-b5a4-3210-fedc-ba9876543210:0a1b2c3d-4e5f-6789-abcd-ef0123456789",
+ "label": "Staging Team Key",
+ "creation_time": "2026-07-09T10:02:47.118Z",
+ "deactivated_time": null,
+ "is_deactivated": false,
+ "usage_limits": {
+ "characters": 500000,
+ "speech_to_text_milliseconds": null
+ }
+}
+```
+
+Once the key reaches its character limit, requests using it return `456 Quota exceeded` errors until the next usage period starts or you raise the limit.
+
+## Step 4: Pull a usage report by key
+
+After the team has started using the key, let's retrieve a usage report to see how much quota each key has consumed. We'll group the results by API key so we can see per-key totals.
+
+Replace the dates with a range that covers the period you want to inspect. Date ranges can span up to 366 days, and data is available up to and including the previous UTC calendar day.
+
+```bash
+curl "https://api.deepl.com/v2/admin/analytics?start_date=2026-06-01&end_date=2026-07-01&group_by=key" \
+ -H "Authorization: DeepL-Auth-Key YOUR_ADMIN_KEY"
+```
+
+The response includes a `usage_report` object with per-key breakdowns and an organization-wide total:
+
+```json
+{
+ "usage_report": {
+ "start_date": "2026-06-01T00:00:00",
+ "end_date": "2026-07-01T00:00:00",
+ "group_by": "key",
+ "key_usages": [
+ {
+ "api_key": "f9e8****6789",
+ "api_key_label": "Staging Team Key",
+ "usage": {
+ "text_translation_characters": 4892,
+ "text_improvement_characters": 4727,
+ "document_translation_characters": 0,
+ "speech_to_text_minutes": 107.46,
+ "total_characters": 9619
+ }
+ }
+ ],
+ "total_usage": {
+ "text_translation_characters": 4892,
+ "text_improvement_characters": 4727,
+ "document_translation_characters": 0,
+ "speech_to_text_minutes": 107.46,
+ "total_characters": 9619
+ }
+ }
+}
+```
+
+Notice that `api_key` values are partially masked in the response for security. You can match keys to their labels using the `api_key_label` field.
+
+You have now created a key, capped its usage, and confirmed activity through the analytics endpoint.
+
+## What's next
+
+- **Rename or reorganize keys**: Use the [rename endpoint](/api-reference/admin-api/managing-developer-keys/rename-key) to update a key's label as teams or services change.
+- **Deactivate a key**: When a key is no longer needed, [deactivate it](/api-reference/admin-api/managing-developer-keys/deactivate-key). Deactivation is permanent, but deactivated keys remain visible in your key list.
+- **Daily usage breakdowns**: Change `group_by` to `key_and_day` to see per-key usage broken down by day, which is useful for spotting spikes.
+- **Custom tag analytics**: If you annotate API requests with custom tags, use the [custom tag analytics endpoint](/api-reference/admin-api/get-custom-tag-usage-analytics) to break down usage by tag.
+- **Other data sources**: See [Retrieving Usage Data](/docs/admin/retrieving-usage-data) for a comparison of all the ways to monitor your DeepL API usage.
diff --git a/docs/admin/retrieving-usage-data.mdx b/docs/admin/retrieving-usage-data.mdx
new file mode 100644
index 00000000..7fbe8842
--- /dev/null
+++ b/docs/admin/retrieving-usage-data.mdx
@@ -0,0 +1,77 @@
+---
+title: "Retrieving Usage Data"
+description: "Compare DeepL's usage data sources and pull character and minute consumption for your account, API keys, or custom tags."
+covers: [Admin]
+public: true
+---
+
+DeepL offers several ways to retrieve usage data so you can track character and minute consumption and the associated costs. This guide compares the available data sources and shows how to use each one.
+
+
+Consumption data in the account UI, in CSV exports, and in the [Admin API analytics endpoints](/api-reference/admin-api/get-usage-analytics) is available up to and including the previous UTC calendar day. For near-real-time data, use the [`/usage` endpoint](/api-reference/usage-and-quota/check-usage-and-limits).
+
+
+## Choose a data source
+
+| Data source | Scope | Time range | Data freshness | Interface |
+| --- | --- | --- | --- | --- |
+| [API Keys & Limits tab](#api-keys-and-limits-tab) | Per API key | Current usage period only | Previous UTC day | Account UI |
+| [API Usage tab](#api-usage-tab) | Account total (plus year-to-date on yearly plans) | Current usage period (and yearly period) | Previous UTC day | Account UI |
+| [Key-level CSV export](#api-key-level-csv-export) | Per API key | Custom or preset ranges up to 4 months, optional grouping by day | Previous UTC day | CSV download |
+| [`/usage` endpoint](#the-usage-endpoint) | Account total | Current usage period only | Near-real-time (within minutes) | REST API |
+| [Admin API analytics](#admin-api-analytics) | Per API key or per custom tag | Custom date range, optional grouping by day | Previous UTC day | REST API |
+
+Use the **account UI** for a quick check while signed in, the **CSV export** for detailed or offline analysis per key, the **`/usage` endpoint** for programmatic near-real-time quota checks, and the **Admin API analytics endpoints** for programmatic reporting and cost attribution via custom tags.
+
+## API Keys and Limits tab
+
+To check per-key consumption for the current monthly usage period, open the [API Keys & Limits tab](https://www.deepl.com/your-account/keys). It shows character and speech-to-text (STT) minute consumption for each API key.
+
+
+
+
+
+## API Usage tab
+
+To check your account totals, open the [API Usage tab](https://www.deepl.com/your-account/usage). It shows total character and STT minute usage for the current monthly usage period, and if you're on a yearly plan, usage to date for your yearly billing period, too.
+
+
+
+
+
+## API key-level CSV export
+
+Generate a CSV report with key-level characters translated for a chosen time period. Key-level usage is not broken out on invoices; it's only available via CSV export or on the "API Keys & Limits" tab.
+
+To download a report, click "Download key-level usage report" on the [API Keys & Limits tab](https://www.deepl.com/your-account/keys) or "Download report" on the [API Usage tab](https://www.deepl.com/your-account/usage), then select a time period and click "Download your report".
+
+
+
+
+
+Select a custom date range of up to 4 months (on UTC calendar days) or one of the presets, which cover rolling windows from the last 24 hours up to the last year as well as calendar months and usage periods. Rolling presets include the current day; calendar-month and usage-period ranges align to UTC day or period boundaries, so they might not start and end on a full calendar day.
+
+For all time ranges except "Last 24 hours", "Current usage period", and "Last usage period", you can also group key-level usage data by UTC calendar day:
+
+
+
+
+
+
+Document translation data is only included in reports with a time period starting on or after May 16, 2024 00:00 UTC. Text translation data is included for all time periods.
+
+
+## The usage endpoint
+
+The [`/usage` endpoint](/api-reference/usage-and-quota/check-usage-and-limits) returns a near-real-time snapshot of character and minute usage in the current monthly usage period, typically up to date within a few minutes of the usage being generated. Use it for programmatic quota checks, for example before submitting a large translation batch.
+
+## Admin API analytics
+
+The Admin API provides programmatic access to usage data over a custom date range, with optional grouping by day. It requires [Admin API access](/docs/admin/overview#the-admin-api) and an [admin key](/docs/admin/managing-api-keys#manage-admin-api-keys) for authentication. Two endpoints are available:
+
+- [Get usage analytics](/api-reference/admin-api/get-usage-analytics) returns usage statistics across all services (text translation, document translation, text improvement, and speech-to-text), in total or grouped by API key
+- [Get custom tag usage analytics](/api-reference/admin-api/get-custom-tag-usage-analytics) returns usage broken down by custom tag
+
+Custom tags are an optional dimension for cost attribution: attach a tag to individual API requests with the `X-DeepL-Reporting-Tag` header to track consumption by team, project, or any other category. Only tagged requests appear in custom-tag analytics, so results reflect a subset of total usage unless every request is tagged. See [How to use custom reporting tags](/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags) for setup and naming guidance.
+
+For a worked example of pulling analytics data into a dashboard, see the [usage analytics dashboard cookbook](/docs/learning-how-tos/cookbook/usage-analytics-dashboard).
diff --git a/docs/best-practices/custom-instructions.mdx b/docs/best-practices/custom-instructions.mdx
index d8eca577..759d8206 100644
--- a/docs/best-practices/custom-instructions.mdx
+++ b/docs/best-practices/custom-instructions.mdx
@@ -89,7 +89,7 @@ When using custom instructions, keep these constraints in mind:
## Related documentation
-- [Text translation API reference](/api-reference/translate)
+- [Text translation API reference](/api-reference/translate/request-translation)
- [Working with context](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter)
- [Style rules API](/api-reference/style-rules)
- [Multilingual glossaries](/api-reference/multilingual-glossaries)
diff --git a/docs/best-practices/document-translations.mdx b/docs/best-practices/document-translations.mdx
index 5a9e73f1..fd8ee75c 100644
--- a/docs/best-practices/document-translations.mdx
+++ b/docs/best-practices/document-translations.mdx
@@ -12,6 +12,9 @@ For DOCX and PPTX, our .NET, PHP and NodeJS client libraries offer functionality
This allows users to translate files that might hit the size limit.
+### Billing minimums
+Every submitted document of type `.pptx`, `.docx`, `.doc`, `.xlsx`, or `.pdf` is billed a minimum of 50,000 characters on DeepL API plans, no matter how many characters the document contains.
+
### One source/target language pair per upload
The `source_lang` and `target_lang` values on the request apply to the entire uploaded file. For most formats, keep each upload to a single source language for consistent results — behavior on content that isn't in the selected source language is not guaranteed.
@@ -67,6 +70,18 @@ Each supported format has behaviors and constraints worth knowing before you upl
- Some valid FrameMaker 10 MIF files may fail with HTTP 500 — try re-saving from a newer FrameMaker version.
- MIF does not use `translate="no"`. Protect content via FrameMaker conditional text or character formatting.
+### Polling and translation time
+Translation time depends on document size and server load: small documents typically finish in seconds, larger ones in 1-2 minutes once translation has started. Poll the [status endpoint](/api-reference/document/check-document-status) at regular intervals or with exponential backoff. Treat the `seconds_remaining` field as a rough estimate only; it can be unreliable and occasionally returns implausible values (e.g. 2^27).
+
+### Using glossaries with documents
+You can apply a glossary to a document translation with the `glossary_id` parameter (or up to 5 glossaries with `glossary_ids`). This requires the `source_lang` parameter to be set, and the glossary's language pair has to match the language pair of the request.
+
+### Document format conversions
+By default, the translated document comes back in the same format as the input. Two conversions differ:
+
+- Translating a `.doc` file returns a `.docx` file.
+- With the `output_format` parameter on upload, you can translate a PDF and receive an editable Microsoft Word document (`output_format=docx`). No other input formats support alternative output formats.
+
### Error 429: Too Many Requests
This error may occur when:
diff --git a/docs/best-practices/error-handling.mdx b/docs/best-practices/error-handling.mdx
index cb9ee7f6..33c544e6 100644
--- a/docs/best-practices/error-handling.mdx
+++ b/docs/best-practices/error-handling.mdx
@@ -8,7 +8,7 @@ Errors are indicated by [standard HTTP status codes](https://developer.mozilla.o
* **HTTP 429: too many requests.** This is an error that you might receive when sending many API requests in a short period of time. Your application should be configured to resend the requests after some delay. Specifically, we recommend implementing retries with exponential backoff. This is implemented in all of the official, DeepL-supported [client libraries](/docs/getting-started/client-libraries).
-* **HTTP 456: quota exceeded** **If you're a Free API user**, you'll receive this error when the monthly 500,000 character limit of your subscription has been reached. You can consider [upgrading your subscription](https://www.deepl.com/pro) if you need more character volume. **If you're a Pro API user**, you'll receive this error when your [Cost Control](/docs/best-practices/cost-control) limit has been reached, and you can increase or remove your Cost Control limit if you need to continue translating. You can also use the [usage endpoint](/api-reference/usage-and-quota) to find out your currently used and available quota.
+* **HTTP 456: quota exceeded** **If you're a Free API user**, you'll receive this error when the monthly 500,000 character limit of your subscription has been reached. You can consider [upgrading your subscription](https://www.deepl.com/pro) if you need more character volume. **If you're a Pro API user**, you'll receive this error when your [Cost Control](/docs/best-practices/cost-control) limit has been reached, and you can increase or remove your Cost Control limit if you need to continue translating. You can also use the [usage endpoint](/api-reference/usage-and-quota/check-usage-and-limits) to find out your currently used and available quota.
* **HTTP 500: internal server error** This is an error you'll receive if there are temporary errors in DeepL Services. Your application should be configured to resend the requests after some delay. Specifically, we recommend implementing retries with exponential backoff. This is implemented in all of the official, DeepL-supported [client libraries](/docs/getting-started/client-libraries). You can check the [API Status Page](https://api-status.deepl.com) for current service availability and incident information.
diff --git a/docs/best-practices/estimating-character-usage.mdx b/docs/best-practices/estimating-character-usage.mdx
index e672366c..134525f4 100644
--- a/docs/best-practices/estimating-character-usage.mdx
+++ b/docs/best-practices/estimating-character-usage.mdx
@@ -10,7 +10,7 @@ This guide walks through techniques for counting characters in different content
## Before you start
-DeepL bills by source-text length in Unicode code points. Characters in the [`context` parameter](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter) and HTML/XML tags (when [tag handling](/docs/xml-and-html-handling/xml) is enabled) do not count. For the full billing rules and per-document character minimums, see [Usage and limits](/docs/resources/usage-limits#your-usage).
+DeepL bills by source-text length in Unicode code points. Characters in the [`context` parameter](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter) and HTML/XML tags (when [tag handling](/docs/translate/translating-xml) is enabled) do not count. For the full billing rules and per-document character minimums, see [Usage and limits](/docs/resources/usage-limits#your-usage).
## Estimate website content
@@ -94,7 +94,7 @@ For a Drupal site specifically, the `node_field_data` and `node__body` tables co
## Estimate document content
-For documents you plan to translate via the [Document Translation API](/api-reference/document), you can extract text locally to get a rough character count.
+For documents you plan to translate via the [Document Translation API](/api-reference/document/upload-and-translate-a-document), you can extract text locally to get a rough character count.
```python
import zipfile
@@ -140,7 +140,7 @@ If you're translating the same content into multiple languages, each language co
## Validate your estimate
-Once you've estimated your characters, you can [sign up for a DeepL API plan for free](https://www.deepl.com/en/pro#api) and test a small sample against the live API. Use the [`show_billed_characters`](/api-reference/translate#request-body-descriptions) parameter to compare actual billed characters against your local count.
+Once you've estimated your characters, you can [sign up for a DeepL API plan for free](https://www.deepl.com/en/pro#api) and test a small sample against the live API. Use the [`show_billed_characters`](/api-reference/translate/request-translation) parameter to compare actual billed characters against your local count. DeepL intends to include `billed_characters` in responses by default in the future, with advance notice to API users before the change.
```bash
curl -X POST https://api.deepl.com/v2/translate \
@@ -171,7 +171,7 @@ Run this on 5-10 representative pages or documents and compare the `billed_chara
After you start translating, monitor actual usage against your estimates:
-- **[`/v2/usage` endpoint](/api-reference/usage-and-quota)** - programmatic access to your current billing period consumption
+- **[`/v2/usage` endpoint](/api-reference/usage-and-quota/check-usage-and-limits)** - programmatic access to your current billing period consumption
- **[Usage Analytics Dashboard](/docs/learning-how-tos/cookbook/usage-analytics-dashboard)** - visualize usage across API keys with the open-source demo dashboard
- **[API Usage Logger](/docs/learning-how-tos/cookbook/api-usage-logger)** - per-request logging with billed characters, language pairs, and reporting tags
- **[Cost Control](/docs/best-practices/cost-control)** - set a monthly character limit on your Pro API subscription to cap spend
diff --git a/docs/best-practices/pre-production-checklist.mdx b/docs/best-practices/pre-production-checklist.mdx
index 41b4e7ff..c12b6e50 100644
--- a/docs/best-practices/pre-production-checklist.mdx
+++ b/docs/best-practices/pre-production-checklist.mdx
@@ -12,5 +12,5 @@ As you prepare to open your DeepL-powered application up to the world, these tip
* Uploading a file for document translation requires an HTTP POST request with `Content-Type: multipart/form-data`; this content type should not be used for text translation.
4. **No query parameters:** Please do not make API requests using query parameters. The examples throughout the API reference include properly formed HTTP POST requests. For security reasons, be especially sure not to send your authentication key via query parameters.
5. **CORS requests:** It's not possible to send requests to the DeepL API from the browser, as requests to third-party APIs from front-end applications would expose your credentials on the web. [You can learn more here](/docs/best-practices/cors-requests).
-6. **Translation context:** DeepL considers the broader context of a source text or document when translating. In general, including more context in a source text or document can result in a higher-quality DeepL translation. For text translation, you can also try the [`context` parameter](/api-reference/translate#request-body-descriptions). [Learn more about working with context here](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter).
+6. **Translation context:** DeepL considers the broader context of a source text or document when translating. In general, including more context in a source text or document can result in a higher-quality DeepL translation. For text translation, you can also try the [`context` parameter](/api-reference/translate/request-translation). [Learn more about working with context here](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter).
7. **Cache results from translation requests:** Storing API responses lets apps serve content faster and avoids extra costs from repeated requests for unchanged content.
diff --git a/docs/getting-started/about.mdx b/docs/getting-started/about.mdx
index c0ead69e..0834d9da 100644
--- a/docs/getting-started/about.mdx
+++ b/docs/getting-started/about.mdx
@@ -22,7 +22,7 @@ In addition, many leading computer-assisted translation (CAT) tool providers hav
## Why the DeepL API?
-- **High-quality text and document translations**: DeepL [consistently outperforms the competition](https://www.deepl.com/quality.html) in translation quality—and not only for text translation. The API also supports [many document, publishing, and localization formats](/api-reference/document) including DOCX, PPTX, XLSX, PDF, HTML, IDML, XLIFF, XML, JSON, DITA, and MIF.
+- **High-quality text and document translations**: DeepL [consistently outperforms the competition](https://www.deepl.com/quality.html) in translation quality—and not only for text translation. The API also supports [many document, publishing, and localization formats](/api-reference/document/upload-and-translate-a-document) including DOCX, PPTX, XLSX, PDF, HTML, IDML, XLIFF, XML, JSON, DITA, and MIF.
- **Maximum data security**: With DeepL API paid plans, texts aren’t saved on persistent storage and aren’t used to train our models. And DeepL adheres strictly to EU data protection laws and ISO 27001. [Learn more about data security at DeepL](https://www.deepl.com/pro-data-security/).
- **Customization with glossaries**: [Specify your own translations for words and phrases](/api-reference/multilingual-glossaries), and customize your translations consistently and at scale.
diff --git a/docs/getting-started/auth.mdx b/docs/getting-started/auth.mdx
index b953d57b..6a495887 100644
--- a/docs/getting-started/auth.mdx
+++ b/docs/getting-started/auth.mdx
@@ -32,7 +32,7 @@ Keep your API key secure at all times. Do not use it in client-side code.
If your authentication key becomes compromised, you also deactivate it and create a new key in [the "API Keys" tab](https://www.deepl.com/your-account/keys).
-Learn more about managing your DeepL API keys [here](/docs/getting-started/managing-api-keys).
+Learn more about managing your DeepL API keys [here](/docs/admin/managing-api-keys).
The authentication key is provided by setting the *Authorization* HTTP header to `DeepL-Auth-Key [yourAuthKey]`.
diff --git a/docs/getting-started/client-libraries.mdx b/docs/getting-started/client-libraries.mdx
index 436e0615..3674bda8 100644
--- a/docs/getting-started/client-libraries.mdx
+++ b/docs/getting-started/client-libraries.mdx
@@ -42,5 +42,5 @@ The DeepL community [maintains client libraries](https://github.com/DeepLcom/awe
Now that you've found your client library, here are a few ways to keep learning about the DeepL API:
* try sample requests [in our playground](https://developers.deepl.com/api-reference/translate/request-translation?playground=open)
-* [DeepL 101](/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api) - a quick guide to text and document translation
-* [Translation: a beginner's guide](/docs/learning-how-tos/examples-and-guides/translation-beginners-guide) - a detailed guide to fundamental translation features
+* [Translate Text Quickstart](/docs/translate/translate-text-quickstart) - send your first text translation requests
+* [Translate Documents Quickstart](/docs/translate/translate-documents-quickstart) - translate a complete file, formatting included
diff --git a/docs/getting-started/managing-api-keys.mdx b/docs/getting-started/managing-api-keys.mdx
deleted file mode 100644
index 20f9d935..00000000
--- a/docs/getting-started/managing-api-keys.mdx
+++ /dev/null
@@ -1,281 +0,0 @@
----
-title: "Managing API keys"
-description: "A guide to creating API keys, getting API key-level usage, setting API key-level limits, and scoping keys to specific endpoints."
-public: true
----
-
-
-This page describes managing API keys in the self-admin area. An [Admin API](/api-reference/admin-api) for API key management is also available to all API Growth and API Enterprise subscribers, and to a limited set of Pro API subscribers.
-
-
-### Get started
-
-You can find and manage your API keys in the [“API Keys & Limits” tab](https://www.deepl.com/your-account/keys) when signed into your DeepL API account. It’s possible to create multiple, simultaneously active API keys in a single API subscription.
-
-
-
-
-
-### **Basic API key management**
-
-**Create new key**
-
-Creates a new API key. You can optionally give an API key a name of your choosing during the creation process. If you do not name the key, the name “DeepL API Key” will be given to the key automatically.
-
-
-
-
-
-Pro API subscribers can create up to 25 simultaneously active API keys. Free API subscribers can create up to 2 simultaneously active API keys.
-
-Giving your API keys a name during the key creation process makes it possible for you to search for the key by name using the search bar on the “API keys” tab:
-
-
-
-
-
-After creating a key, a popup with the newly created key will appear. You can copy the key from this popup and use the key immediately. You can also copy the key from the table in the “API keys” tab at any time.
-
-
-
-
-
-#### Deactivate key
-
-Deactivates an active API key. **IMPORTANT:** an API key will stop working immediately when it is deactivated. After a key is deactivated, it cannot be reactivated—deactivating a key is permanent!
-
-
-
-
-
-
-
-
-
-
-
-
-
-#### Rename key
-
-Allows you to edit the name of an API key. Note that it *is* possible for two keys to have the same name.
-
-Both active and deactivated keys can be renamed.
-
-
-
-
-
-**Copy key**
-
-Copies the API key to your clipboard. For security reasons, we do not show the full key in the table in the “API Keys & Limits” tab. Both active and revoked keys can be copied.
-
-
-
-
-
-
-To learn how to see API key-level usage data, see [Retrieving usage data](/docs/retrieving-usage-data).
-
-
-### **Set API key-level usage limits**
-
-It's possible to set an API key-level usage limit. Key-level limits restrict the number of total characters (across text translation, document translation, and text improvement) that can be consumed by an API key in a one-month usage period. You can see the dates of your current usage period in [the Usage tab](https://www.deepl.com/your-account/usage).
-
-For example, if you set a key-level usage limit of 1,000,000 characters, the API key will not consume more than 1,000,000 characters per usage period.
-
-In the ["API Keys & Limits" tab](https://www.deepl.com/your-account/keys), the "Characters consumed" column in the API keys table shows the number of characters consumed by an API key in the current usage period. The character count will "reset" at the start of the next usage period, at which point the key will again be able to consume characters.
-
-As with subscription-level cost control:
-
-* You'll receive notification emails when 80% and 100% of a key-level limit has been reached
-* The API will respond with `456 Quota exceeded` errors when 100% of a key-level limit has been reached
-
-
-It's possible to set an API key-level limit to 0, which means the API key will not be able to consume characters.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-### API key permissions
-
-API key permissions, introduced in June 2026, let you limit what a developer API key can do. Instead of one key with full access to every endpoint, you can issue keys that are scoped to specific operations, for example a key that can only translate text or a key that can only read glossaries.
-
-Permissions are implemented as scopes. Each scope groups a set of related operations into a single capability you can grant to a key. This section uses "permissions" for the user-facing feature and "scopes" for the technical mechanism.
-
-Permissions are currently supported only for developer API keys. An account can hold any mix of scoped and unrestricted developer keys.
-
-API key permissions are available on the API Pro, API Developer, API Growth, and API Enterprise plans.
-
-**When to use scoped keys**
-
-| **Key Type** | **Choose When** |
-| --- | --- |
-| **Unrestricted** | A key can access any endpoint and doesn't need to be limited in any way. |
-| **Scoped** | A key should have access only to specific endpoints, for example to prevent glossaries from being modified inadvertently. |
-
-Before API key permissions, every DeepL API key behaved like an unrestricted key.
-
-**How scopes work**
-
-Developer keys can be turned into scoped keys by assigning them one or more scopes. Once a key is scoped:
-
-- It can call only the endpoints fully covered by its scopes.
-- Every other endpoint returns `403 Forbidden`, including any endpoint that has no scope requirement of its own.
-- Some endpoints require more than one scope. A key must hold all of them; if any is missing, the request is denied and the response lists the missing scopes.
-
-Scopes are enforced only on scoped keys. Unrestricted keys retain full access to every endpoint. Existing keys remain unrestricted by default, but you can assign them scopes at any time.
-
-**Available scopes**
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `POST` | [`/v2/translate`](/api-reference/translate/request-translation) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `POST` | [`/v2/document`](/api-reference/document/upload-and-translate-a-document) |
- | `GET` | [`/v2/document/{document_id}`](/api-reference/document/check-document-status) |
- | `GET` | [`/v2/document/{document_id}/result`](/api-reference/document/download-translated-document) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `POST` | [`/v2/write/rephrase`](/api-reference/improve-text/request-text-improvement) |
- | `POST` | [`/v2/write/correct`](/api-reference/improve-text/correct-text) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `GET` | [`/v3/glossaries`](/api-reference/multilingual-glossaries/list-all-glossaries) |
- | `GET` | [`/v3/glossaries/{glossary_id}`](/api-reference/multilingual-glossaries/retrieve-glossary-details) |
- | `GET` | [`/v3/glossaries/{glossary_id}/entries`](/api-reference/multilingual-glossaries/retrieve-glossary-entries) |
- | `GET` | [`/v2/glossaries`](/api-reference/glossaries/list-all-glossaries) |
- | `GET` | [`/v2/glossaries/{glossary_id}`](/api-reference/glossaries/retrieve-glossary-details) |
- | `GET` | [`/v2/glossaries/{glossary_id}/entries`](/api-reference/glossaries/retrieve-glossary-entries) |
- | `GET` | [`/v2/glossary-language-pairs`](/api-reference/multilingual-glossaries/list-language-pairs-supported-by-glossaries) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `POST` | [`/v3/glossaries`](/api-reference/multilingual-glossaries/create-a-glossary) |
- | `PATCH` | [`/v3/glossaries/{glossary_id}`](/api-reference/multilingual-glossaries/edit-glossary-details) |
- | `PUT` | [`/v3/glossaries/{glossary_id}/dictionaries`](/api-reference/multilingual-glossaries/replaces-or-creates-a-dictionary-in-the-glossary-with-the-specified-entries) |
- | `DELETE` | [`/v3/glossaries/{glossary_id}`](/api-reference/multilingual-glossaries/delete-a-glossary) |
- | `DELETE` | [`/v3/glossaries/{glossary_id}/dictionaries`](/api-reference/multilingual-glossaries/deletes-the-dictionary-associated-with-the-given-language-pair-with-the-given-glossary-id) |
- | `POST` | [`/v2/glossaries`](/api-reference/glossaries/create-a-glossary) |
- | `DELETE` | [`/v2/glossaries/{glossary_id}`](/api-reference/glossaries/delete-a-glossary) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `GET` | [`/v3/style_rules`](/api-reference/style-rules/list-all-style-rules) |
- | `GET` | [`/v3/style_rules/{style_id}`](/api-reference/style-rules/get-style-rule) |
- | `GET` | [`/v3/style_rules/{style_id}/custom_instructions/{instruction_id}`](/api-reference/style-rules/get-custom-instruction) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `POST` | [`/v3/style_rules`](/api-reference/style-rules/create-style-rule) |
- | `PATCH` | [`/v3/style_rules/{style_id}`](/api-reference/style-rules/update-style-rule) |
- | `PUT` | [`/v3/style_rules/{style_id}/configured_rules`](/api-reference/style-rules/update-configured-rules) |
- | `DELETE` | [`/v3/style_rules/{style_id}`](/api-reference/style-rules/delete-style-rule) |
- | `POST` | [`/v3/style_rules/{style_id}/custom_instructions`](/api-reference/style-rules/create-custom-instruction) |
- | `PUT` | [`/v3/style_rules/{style_id}/custom_instructions/{instruction_id}`](/api-reference/style-rules/update-custom-instruction) |
- | `DELETE` | [`/v3/style_rules/{style_id}/custom_instructions/{instruction_id}`](/api-reference/style-rules/delete-custom-instruction) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `GET` | [`/v3/translation_memories`](/api-reference/translation-memory/list-translation-memories) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `GET` | [`/v3/languages`](/api-reference/languages/retrieve-languages-by-resource) |
- | `GET` | [`/v3/languages/resources`](/api-reference/languages/retrieve-resources) |
- | `GET` | [`/v2/languages`](/api-reference/languages/retrieve-supported-languages) |
-
-
-
- | **Method** | **Endpoint** |
- | --- | --- |
- | `GET` | [`/v2/usage`](/api-reference/usage-and-quota/check-usage-and-limits) |
-
-
-
-
- **Voice API support is coming.** Permissions don't yet cover the Voice API, so there's no Voice scope to assign. Because a scoped key is blocked from every endpoint its scopes don't cover, a scoped key can't currently reach the Voice API at all. Use an unrestricted key for any workload that needs Voice until Voice scopes ship in a future update.
-
-
-**Create a scoped key**
-
-Open the ["API Keys & Limits" tab](https://www.deepl.com/your-account/keys) in your account. Click "Create key" and optionally name the key.
-
-Select **Custom permissions**, then choose one or more scopes from the list.
-
-Click "Create key" to confirm. The key is created with the chosen scopes and shown once in a popup so you can copy it.
-
-
-
-
-
-**Edit scopes on an existing key**
-
-You can change scopes on any existing developer API key, including keys that were originally unrestricted.
-
-In the API keys table, open the key's menu and select "Edit permissions". Choose **All access** to make the key unrestricted, or **Custom permissions** to select specific scopes. Click "Save" to apply.
-
-
-
-
-
-
-
-
-
-**Identify scoped and unrestricted keys**
-
-The API keys table includes a column showing each key's permissions. Hover over the badge to view the assigned scopes.
-
-
-
-
-
-
-
-
-
-**Error responses**
-
-When a scoped key calls an endpoint outside its scopes, the API returns a `403 Forbidden` response. The `detail` field lists the scopes the key is missing:
-
-```json
-{
- "message": "Forbidden",
- "detail": "Missing required scope(s): glossaries:write"
-}
-```
-
-To resolve it, call an endpoint covered by the key's scopes, or add the missing scope to the key.
diff --git a/docs/getting-started/quickstart.mdx b/docs/getting-started/quickstart.mdx
index 3001d5b0..2ff1d6dc 100644
--- a/docs/getting-started/quickstart.mdx
+++ b/docs/getting-started/quickstart.mdx
@@ -12,24 +12,16 @@ New user? Follow these quick steps to get started with the DeepL API.
Visit [our plans page](https://www.deepl.com/pro-api#api-pricing), choose a plan, and sign up.
-
- If you already have a DeepL Translator account, you will need to log out and [create a new account for the DeepL API](https://support.deepl.com/hc/articles/360019358999-Change-plan).
-
+ If you already have a DeepL Translator account, you will need to log out and [create a new account](https://support.deepl.com/hc/articles/360019358999-Change-plan).
-
+
Find your API key [here](https://www.deepl.com/your-account/keys).
- Then try making a simple translation request in one of these ways:
- * cURL or an HTTP request
- * with [our client libraries](/docs/getting-started/client-libraries) for [Python](https://www.github.com/deeplcom/deepl-python), [JavaScript](https://www.github.com/deeplcom/deepl-node), [PHP](https://www.github.com/deeplcom/deepl-php), [.NET](https://www.github.com/deeplcom/deepl-dotnet), [Java](https://www.github.com/deeplcom/deepl-java), or [Ruby](https://www.github.com/deeplcom/deepl-rb)
- * [in our playground](https://developers.deepl.com/api-reference/translate/request-translation?playground=open)
- * [in Postman](/docs/getting-started/test-your-api-requests-with-postman)
-
- If you use the sample code below, be sure to replace `{YOUR_API_KEY}` with your own API key.
+ Then try making a simple translation request.
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
+ If you chose a free API plan, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
```http Sample request
@@ -56,7 +48,7 @@ New user? Follow these quick steps to get started with the DeepL API.
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
+ If you chose a free API plan, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
```sh Set the API key
@@ -126,7 +118,6 @@ New user? Follow these quick steps to get started with the DeepL API.
```text Sample output
Hallo, Welt!
-
```
In production code, it's safer to store your API key in an environment variable.
@@ -235,17 +226,30 @@ New user? Follow these quick steps to get started with the DeepL API.
-
- [Our official client libraries](/docs/getting-started/client-libraries) let you use the API with six popular programming languages - [Python](https://www.github.com/deeplcom/deepl-python), [JavaScript](https://www.github.com/deeplcom/deepl-node), [PHP](https://www.github.com/deeplcom/deepl-php), [.NET](https://www.github.com/deeplcom/deepl-dotnet), [Java](https://www.github.com/deeplcom/deepl-java), or [Ruby](https://www.github.com/deeplcom/deepl-rb). The DeepL community has [contributed client libraries](https://github.com/DeepLcom/awesome-deepl?tab=readme-ov-file#community-libraries--sdks) for other languages, including [Dart](https://github.com/komape/deepl_dart), [Go](https://github.com/candy12t/go-deepl), and [Rust](https://github.com/Avimitin/deepl-rs). You may also wish to check out [these examples and guides](/docs/learning-how-tos/examples-and-guides).
+
+ Pick the product you want to integrate:
+
+
+
+ Translate text strings and complete documents, with quickstarts for both.
+
+
+ Transcribe and translate spoken audio in real time, starting with the Real-Time Voice Quickstart.
+
+
+ Manage API keys, permissions, and usage across your organization, in the account UI or via the Admin API.
+
+
+
+ [Our official client libraries](/docs/getting-started/client-libraries) wrap the API for Python, JavaScript, PHP, .NET, Java, and Ruby, and the community maintains [libraries for more languages](https://github.com/DeepLcom/awesome-deepl?tab=readme-ov-file#community-libraries--sdks), including Dart, Go, and Rust.
## Keep exploring
-- [**DeepL 101**](/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api) - A quick guide to text and document translation, using Postman to play with the API, client libraries for your favorite programming language, and joining our developer community
-- [Translation: a beginner's guide](/docs/learning-how-tos/examples-and-guides/translation-beginners-guide) - A detailed guide to fundamental translation features
-- [Cookbook](/docs/learning-how-tos/cookbook) - Explore short tutorials, examples, projects, and use cases
-- [Guides](/docs/learning-how-tos/examples-and-guides) - Discover in-depth explanations for API features and real-world applications
+- [**Cookbook**](/docs/learning-how-tos/cookbook) - Short tutorials, examples, projects, and use cases
+- [**Guides**](/docs/learning-how-tos/examples-and-guides) - In-depth explanations for API features and real-world applications
+- [**Docs MCP Server**](/docs/getting-started/docs-mcp-server) - Connect your AI tools to this documentation for source-grounded answers
## Community and Support
@@ -253,8 +257,8 @@ New user? Follow these quick steps to get started with the DeepL API.
Support Center
-
- DeepL Bridges - Developer Community
+
+ Discord Community
API Status Page
@@ -262,7 +266,7 @@ New user? Follow these quick steps to get started with the DeepL API.
DeepL Status Page (all services)
-
+
Release Notes
diff --git a/docs/getting-started/regional-endpoints.mdx b/docs/getting-started/regional-endpoints.mdx
index 43c7d4d7..13c3c705 100644
--- a/docs/getting-started/regional-endpoints.mdx
+++ b/docs/getting-started/regional-endpoints.mdx
@@ -197,5 +197,5 @@ For more details, see the [Style rules documentation](/api-reference/style-rules
- [Client libraries](/docs/getting-started/client-libraries) - Language-specific client library documentation and configuration
- [Authentication and access](/docs/getting-started/auth) - API authentication methods and security best practices
-- [Text translation](/api-reference/translate) - Text translation API reference
-- [Admin API](/api-reference/admin-api) - Programmatic API key management for enterprise administrators
+- [Text translation](/api-reference/translate/request-translation) - Text translation API reference
+- [Admin API](/docs/admin/overview) - Programmatic API key management for enterprise administrators
diff --git a/docs/learning-how-tos/cookbook/api-usage-logger.mdx b/docs/learning-how-tos/cookbook/api-usage-logger.mdx
index 4fbdc213..20675c33 100644
--- a/docs/learning-how-tos/cookbook/api-usage-logger.mdx
+++ b/docs/learning-how-tos/cookbook/api-usage-logger.mdx
@@ -11,7 +11,7 @@ public: true
This open-source reference project shows how to capture per-request usage data for the DeepL API (billed characters, language pairs, reporting tags, API key identifiers, and errors) and explore it through a local Streamlit dashboard. It wraps the [DeepL Python client](/docs/getting-started/client-libraries) so every text and document translation request is logged to a local DuckDB file as it happens, alongside any errors returned by the API.
-The project is intended for teams that need usage reporting with request-level granularity. If you instead want to retrieve subscription-level or API key-level data via a single API call, see the [Usage Analytics Dashboard](/docs/learning-how-tos/cookbook/usage-analytics-dashboard) cookbook, which uses the [Admin API](/api-reference/admin-api/organization-usage-analytics).
+The project is intended for teams that need usage reporting with request-level granularity. If you instead want to retrieve subscription-level or API key-level data via a single API call, see the [Usage Analytics Dashboard](/docs/learning-how-tos/cookbook/usage-analytics-dashboard) cookbook, which uses the [Admin API](/api-reference/admin-api/get-usage-analytics).
## Features
diff --git a/docs/learning-how-tos/cookbook/usage-analytics-dashboard.mdx b/docs/learning-how-tos/cookbook/usage-analytics-dashboard.mdx
index b860c796..9a8ad939 100644
--- a/docs/learning-how-tos/cookbook/usage-analytics-dashboard.mdx
+++ b/docs/learning-how-tos/cookbook/usage-analytics-dashboard.mdx
@@ -13,7 +13,7 @@ This open-source demo dashboard shows how to visualize DeepL API key usage acros
The dashboard is designed to be lightweight and easy to set up, with zero NPM dependencies and sample data included for testing. It can be used as-is, or as an example of how similar data can be incorporated into your own internal workflows and dashboards.
-For more information about the DeepL Admin API endpoint, check out the [Admin API documentation](/api-reference/admin-api/organization-usage-analytics).
+For more information about the DeepL Admin API endpoint, check out the [Admin API documentation](/api-reference/admin-api/get-usage-analytics).
If you need per-request logging instead of account-wide views, see the [API Usage Logger](/docs/learning-how-tos/cookbook/api-usage-logger) cookbook.
diff --git a/docs/learning-how-tos/examples-and-guides.mdx b/docs/learning-how-tos/examples-and-guides.mdx
index 7a08841e..4943284b 100644
--- a/docs/learning-how-tos/examples-and-guides.mdx
+++ b/docs/learning-how-tos/examples-and-guides.mdx
@@ -5,9 +5,9 @@ description: "Learn how to use DeepL API features to achieve your translation g
public: true
---
-
+
-
+
diff --git a/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api.mdx b/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api.mdx
deleted file mode 100644
index 5784a321..00000000
--- a/docs/learning-how-tos/examples-and-guides/first-things-to-try-with-the-deepl-api.mdx
+++ /dev/null
@@ -1,70 +0,0 @@
----
-title: "First Things To Try With The DeepL API"
-sidebarTitle: "DeepL API 101"
-description: "New around here? We've got you covered"
-public: true
----
-
-At DeepL, we’re on a mission to break down communication barriers and help developers integrate our powerful translation engine into their own projects and systems. Whether you’re a DeepL API newbie or you’re worried you’re missing out on some awesome features, this guide is for you.
-
-Before trying any of the features below, you’ll need to [sign up for a DeepL API account](https://www.deepl.com/pro-api?cta=header-pro-api), then head to [your account](https://deepl.com/your-account/keys) to find your API key.
-
-You’re then ready to get exploring the DeepL API!
-
-### 1. Send your first translation request
-
-Most people’s first experience of the translation power of DeepL is by translating some text in the web translator, so what better way to test out the same power in the API than sending a text translation.
-
-Open up your terminal and paste the following in (making sure you replace \[yourAuthKey] with your own):
-
-```bash
-curl -X POST 'https://api-free.deepl.com/v2/translate' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---header 'Content-Type: application/json' \
---data '{
- "text": [
- "Hello, world!"
- ],
- "target_lang": "DE"
-}'
-```
-
-Hit return, et voila (that’s French for - well, find out for yourself) - you’ll see the translation returned back to you in the terminal, and congratulations, you’ve just sent your first API request!
-
-### 2. Set up a Postman environment
-
-Getting up and running with the DeepL API needn’t be daunting. Before you open up a terminal or IDE to start writing your own code, the easiest way to get started is to set up an environment in Postman.
-
-Postman is a simple (but powerful) API tool that allows you to make API requests without writing a line of code.
-
-The best bit? [DeepL already has an official workspace](https://www.postman.com/deepl-api/workspace/deepl-api-developers) there to get you up and running even faster, with a collection that has references to all the API functionality - click the button below to get started!
-
-[](https://app.getpostman.com/run-collection/27518486-e9e2969d-d589-4d3d-9df6-cc514cf3ee5e?action=collection%2Ffork\&source=rip_markdown\&collection-url=entityId%3D27518486-e9e2969d-d589-4d3d-9df6-cc514cf3ee5e%26entityType%3Dcollection%26workspaceId%3D48a52b53-0654-484b-861d-ae228857c2f6)
-
-### 3. Translate a document
-
-Just like translating text, the DeepL API also has the functionality to translate entire documents, meaning you don’t need to copy, paste, translate and back again. The DeepL API supports a [huge range of document formats](/api-reference/document), and just like sending a text translation request, you only need a small amount of code:
-
-
-```bash
-curl -X POST 'https://api-free.deepl.com/v2/document' \
---header 'Authorization: DeepL-Auth-Key [yourAuthKey]' \
---form 'target_lang=DE' \
---form 'file=@document.docx'
-```
-
-There are a few more steps involved to retrieve the translated document, [so check out the full documentation to find out how](/api-reference/document), or [take a look at our Postman flow](https://www.postman.com/deepl-api/workspace/deepl-api-developers/flow/65cf6a521364d0003107d306) that shows all the steps connected.
-
-### 4. Get started super fast with a client library
-
-Ready to start building with DeepL? Rather than starting from scratch, why not take some of the strain out of building your first DeepL powered application by using a client library in your favorite programming language?
-
-With client libraries, you don’t need to worry about building your own connection and authentication code, or handling multi-step processes like document translation - client libraries handle all the heavy lifting so you can concentrate on the fun stuff.
-
-Right now, client libraries are available for .NET, PHP, Node, Python, Ruby and Java - you can find them all with great documentation in our [GitHub repository](https://github.com/DeepLcom/)
-
-### 5. Get involved with the developer community
-
-Created a killer app powered by DeepL? Want to ask what the best what practise is for integrating using C#? [The official DeepL Developer Community on DeepL Bridges is the place to go](https://dee.pl/7iwrt).
-
-As well as finding other community members - and maybe helping them with their own questions - you'll also find community exclusive events to attend and even a DeepL staffer or two talking about all things API development.
diff --git a/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter.mdx b/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter.mdx
index 8ac03cd9..8c0266a3 100644
--- a/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter.mdx
+++ b/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter.mdx
@@ -153,7 +153,7 @@ When translating names in headlines or short snippets, the same name might be tr
### Example
-As noted in the [`text` field reference](/api-reference/translate#request-body-descriptions), each text in the array is translated independently and texts do not share context with each other. This results in different transliterations for the name "Sergej".
+As noted in the [`text` field reference](/api-reference/translate/request-translation), each text in the array is translated independently and texts do not share context with each other. This results in different transliterations for the name "Sergej".
```sh
curl -X POST 'https://api.deepl.com/v2/translate' \
@@ -253,7 +253,7 @@ There is no size limit for the `context` parameter itself, but the request body
### Multi-`text` requests
-As noted in the [`text` field reference](/api-reference/translate#request-body-descriptions), each text in the array is translated independently — they do not share context with each other.
+As noted in the [`text` field reference](/api-reference/translate/request-translation), each text in the array is translated independently — they do not share context with each other.
In this example, "Tor" might be translated as "gate" instead of "goal" because the first `text` doesn't have access to the second one's content.
@@ -273,7 +273,7 @@ If you send a request with both `context` and multiple `text` parameters, the `c
### Document translation
-When using the [document translation endpoint](/api-reference/document), the engine automatically uses the broader document context. You don't need to provide explicit context for full documents.
+When using the [document translation endpoint](/api-reference/document/upload-and-translate-a-document), the engine automatically uses the broader document context. You don't need to provide explicit context for full documents.
### Tag handling
@@ -285,7 +285,7 @@ When using `tag_handling=xml` or `tag_handling=html`, tags are *not* used as a c
Now that you understand the context parameter:
-- **Try it yourself:** Review the [text translation API reference](/api-reference/translate) for complete context parameter specifications
+- **Try it yourself:** Review the [text translation API reference](/api-reference/translate/request-translation) for complete context parameter specifications
- **Enforce terminology:** Learn how to use [glossaries](/api-reference/multilingual-glossaries) for consistent translations across all content
- **Control style and tone:** Explore [style rules](/api-reference/style-rules) for formatting and tone instructions
-- **Translate full documents:** Understand how [document translation](/api-reference/document) automatically handles context
\ No newline at end of file
+- **Translate full documents:** Understand how [document translation](/api-reference/document/upload-and-translate-a-document) automatically handles context
\ No newline at end of file
diff --git a/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags.mdx b/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags.mdx
index a7d7a2ae..664c2bdb 100644
--- a/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags.mdx
+++ b/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags.mdx
@@ -94,5 +94,5 @@ Tags are a reporting feature only. You cannot use them to enforce limits, quotas
- **Use the client libraries:** See [Sending Custom Reporting Tags with Client Libraries](/docs/learning-how-tos/cookbook/sending-custom-reporting-tags-from-client-libraries) for code snippets in Python, Node.js, Java, .NET, and PHP.
- **Query your tagged usage:** See the [Get custom tag usage analytics](/api-reference/admin-api/get-custom-tag-usage-analytics) reference for date ranges, aggregation options, and pagination.
-- **Get the bigger picture:** Read the [usage analytics overview](/api-reference/admin-api/organization-usage-analytics) to understand how custom-tag reporting fits alongside total organization usage.
+- **Get the bigger picture:** Read the [usage data guide](/docs/admin/retrieving-usage-data) to understand how custom-tag reporting fits alongside the other usage data sources.
- **Explore other optional translate parameters:** Learn [how to use the context parameter](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter) to improve translation accuracy for ambiguous content.
diff --git a/docs/learning-how-tos/examples-and-guides/translating-between-variants.mdx b/docs/learning-how-tos/examples-and-guides/translating-between-variants.mdx
index 45700286..322cf4ae 100644
--- a/docs/learning-how-tos/examples-and-guides/translating-between-variants.mdx
+++ b/docs/learning-how-tos/examples-and-guides/translating-between-variants.mdx
@@ -127,7 +127,7 @@ You can specify up to 10 custom instructions per request, each with a maximum of
Now that you understand how to translate between language variants:
-- **Try it yourself:** Test out style rules and custom instructions in the [text translation API playground](/api-reference/translate)
+- **Try it yourself:** Test out style rules and custom instructions in the [text translation API playground](/api-reference/translate/request-translation?playground=open)
- **Learn about the Write API:** Explore the [/write/rephrase endpoint](/api-reference/improve-text) for high-quality variant translation and rephrasing
- **Manage reusable rules:** Learn how to create [style rules](/api-reference/style-rules) for systematic variant transformations
- **Improve translation quality:** Understand how [the context parameter](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter) can enhance ambiguous translations
diff --git a/docs/learning-how-tos/examples-and-guides/translation-beginners-guide.mdx b/docs/learning-how-tos/examples-and-guides/translation-beginners-guide.mdx
deleted file mode 100644
index 48337845..00000000
--- a/docs/learning-how-tos/examples-and-guides/translation-beginners-guide.mdx
+++ /dev/null
@@ -1,850 +0,0 @@
----
-title: "Translation: a beginner's guide"
-description: "An introduction to sending translation requests with the DeepL API"
-sidebarTitle: "Translation: a beginner's guide"
-public: true
----
-
-This guide explains the fundamentals of translating text with the DeepL API. We’ll explore:
-
-* getting an API key
-* using client libraries
-* language codes and regional variants
-* where to send your request
-* choosing a `model_type`
-* limits
-
-Let’s get started!
-
-## Getting an API key
-
-If you haven’t already signed up for a DeepL API account, you’ll need to do so. Visit [our plans page](https://www.deepl.com/en/pro/change-plan#developer), choose a plan, and sign up.
-
-
-If you already have a DeepL account for the translator, you need to log out of your account, then create a new account for the DeepL API.
-
-
-When you send a request to our API, you use your API key to identify yourself. You can find that API key [here](https://www.deepl.com/en/your-account/keys).
-
-And now you’re ready to make your first API request!
-
-
-For more information about API keys and authentication, see [Authentication](/docs/getting-started/auth#authentication)
-
-
-## Finding your client library
-
-Like many APIs, the DeepL API uses HTTP requests and responses to receive and send data. While you can construct your own HTTP requests, most people find it easier to let their favorite programming language generate requests and handle the responses. To this end, DeepL provides [official client libraries](/docs/getting-started/client-libraries) for six popular languages:
-
-* [Python](https://www.github.com/deeplcom/deepl-python)
-* [JavaScript](https://www.github.com/deeplcom/deepl-node)
-* [PHP](https://www.github.com/deeplcom/deepl-php)
-* [C#](https://www.github.com/deeplcom/deepl-dotnet)
-* [Java](https://www.github.com/deeplcom/deepl-java)
-* [Ruby](https://www.github.com/deeplcom/deepl-rb)
-
-The DeepL community has [contributed client libraries](https://github.com/DeepLcom/awesome-deepl?tab=readme-ov-file#community-libraries--sdks) for other programming languages, including [Dart](https://github.com/komape/deepl_dart), [Go](https://github.com/candy12t/go-deepl), and [Rust](https://github.com/Avimitin/deepl-rs).
-
-The documentation on this site frequently includes code samples in these languages. For more about how to use the DeepL API in your favorite language, try the links above.
-
-
-JavaScript/TypeScript users: for security reasons, you cannot call the DeepL API directly from client-side JavaScript. To do this during testing or prototyping, try one of [these quick proxies](/docs/learning-how-tos/cookbook/nodejs-proxy).
-
-
-## Making a translation request
-
-### Source and target languages
-
-The **source language** is the language you’re translating from. The **target language** is the language you’re translating to.
-
-Any DeepL API translation request must include these two parameters:
-
-* `text`: some text to translate
-* `target_lang`: the target language
-
-That’s all you need! Since DeepL is quite good at detecting the source language, normally you can omit the `source_lang` parameter. If your text is very short, contains a mix of languages, or if you want to specify the source language for any other reason, you can include `source_lang`.
-
-### A sample translation request
-
-For example, if you wanted to translate the phrase “Hello, bright universe!” to Japanese:
-
-* “Hello, bright universe!” is the `text`
-* Japanese is the `target_lang`
-* the source language is English, so you could include this as the `source_lang`, but you don't need to.
-
-The first tab below shows the HTTP request you’d use here and a typical response from the API. Other tabs show how you’d make this request [using cURL](https://curl.se/docs/tooldocs.html) and using our official client libraries. To see how you’d handle the response in your favorite programming language, check the appropriate tab.
-
-
-
-
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
-
-
- ```http Sample request
- POST /v2/translate HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAuthKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 72
- Content-Type: application/json
-
- {"text":["Hello, bright universe!"],"target_lang":"JA"}
- ```
-
- ```json Sample response
- {
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "こんにちは、輝く宇宙"
- }
- ]
- }
- ```
-
-
-
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
-
-
- ```sh Set the API key
- export API_KEY={YOUR_API_KEY}
- ```
-
- ```sh Sample request
- curl -X POST https://api.deepl.com/v2/translate \
- --header "Content-Type: application/json" \
- --header "Authorization: DeepL-Auth-Key $API_KEY" \
- --data '{
- "text": ["Hello, bright universe!"],
- "target_lang": "JA"
- }'
- ```
-
- ```json Sample response
- {
- "translations": [
- {
- "detected_source_language": "EN",
- "text": "こんにちは、輝く宇宙"
- }
- ]
- }
- ```
-
-
- ```py Sample request
- import deepl
-
- auth_key = "{YOUR_API_KEY}" # replace with your key
- deepl_client = deepl.DeepLClient(auth_key)
-
- result = deepl_client.translate_text("Hello, bright universe!", target_lang="JA")
- print(result.text)
- ```
-
- ```text Sample output
- こんにちは、輝く宇宙
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```javascript Sample request
- import * as deepl from 'deepl-node';
-
- const authKey = "{YOUR_API_KEY}"; // replace with your key
- const deeplClient = new deepl.DeepLClient(authKey);
-
- (async () => {
- const result = await deeplClient.translateText('Hello, bright universe!', null, 'JA');
- console.log(result.text);
- })();
- ```
-
- ```text Sample output
- こんにちは、輝く宇宙
-
- ```
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```php Sample request
- require_once 'vendor/autoload.php';
- use DeepL\Client;
-
- $authKey = "{YOUR_API_KEY}"; // replace with your key
- $deeplClient = new DeepL\DeepLClient($authKey);
-
- $result = $deeplClient->translateText('Hello, bright universe!', null, 'JA');
- echo $result->text;
- ```
-
- ```text Sample output
- こんにちは、輝く宇宙
- ```
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```csharp Sample request
- using DeepL; // this imports the DeepL namespace. Use the code below in your main program.
-
- var authKey = "{YOUR_API_KEY}"; // replace with your key
- var client = new DeepLClient(authKey);
-
- var translatedText = await client.TranslateTextAsync(
- "Hello, bright universe!",
- null,
- LanguageCode.Japanese);
- Console.WriteLine(translatedText);
- ```
-
- ```text Sample output
- こんにちは、輝く宇宙
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```java Sample request
- import com.deepl.api.*;
-
- public class Main {
- public static void main(String[] args) throws DeepLException, InterruptedException {
- String authKey = "{YOUR_API_KEY}"; // replace with your key
- DeepLClient client = new DeepLClient(authKey);
-
- TextResult result = client.translateText("Hello, bright universe!", null, "JA");
- System.out.println(result.getText());
- }
- }
- ```
-
- ```text Sample output
- こんにちは、輝く宇宙
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```ruby Sample request
- require 'deepl'
-
- DeepL.configure do |config|
- config.auth_key = '{YOUR_API_KEY}' # replace with your key
- end
-
- translation = DeepL.translate 'Hello, bright universe!', nil, 'JA'
- puts translation.text
- ```
-
- ```text Sample output
- こんにちは、輝く宇宙
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
-
-### Sending multiple text strings
-
-If you look at the HTTP request above, you’ll notice that the translation text is in square brackets - in an array. In fact, a translation request can include multiple text strings:
-
-
-
-
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
-
-
- ```http Sample request
- POST /v2/translate HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAuthKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 121
- Content-Type: application/json
-
- {
- "text": [
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ],
- "target_lang": "HI"
- }
- ```
-
- ```json Sample response
- {
- "translations": [
- {
- "text": "स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?",
- "detected_source_language": "ES"
- },
- {
- "text": "हाँ++",
- "detected_source_language": "ES"
- }
- ]
- }
- ```
-
-
-
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
-
-
- ```sh Set the API key
- export API_KEY={YOUR_API_KEY}
- ```
-
- ```sh Sample request
- curl -X POST https://api.deepl.com/v2/translate \
- --header "Content-Type: application/json" \
- --header "Authorization: DeepL-Auth-Key $API_KEY" \
- --data '{
- "text": [
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ],
- "target_lang": "HI"
- }'
- ```
-
- ```json Sample response
- {
- "translations": [
- {
- "text": "स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?",
- "detected_source_language": "ES"
- },
- {
- "text": "हाँ++",
- "detected_source_language": "ES"
- }
- ]
- }
- ```
-
-
- ```py Sample request
- import deepl
-
- auth_key = "{YOUR_API_KEY}" # replace with your key
- deepl_client = deepl.DeepLClient(auth_key)
-
- result = deepl_client.translate_text(
- [
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ],
- target_lang="HI"
- )
-
- print (f"{result[0].text}\n{result[1].text}")
- ```
-
- ```text Sample output
- स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?
- हाँ++
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```javascript Sample request
- import * as deepl from 'deepl-node';
-
- const authKey = "{YOUR_API_KEY}"; // replace with your key
- const deeplClient = new deepl.DeepLClient(authKey);
-
- (async () => {
- const result = await deeplClient.translateText(
- [
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ],
- null,
- 'HI'
- );
-
- console.log(result[0].text + "\n" + result[1].text);
- })();
- ```
-
- ```text Sample output
- स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?
- हाँ++
-
- ```
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```php Sample request
- require_once 'vendor/autoload.php';
- use DeepL\Client;
-
- $authKey = "{YOUR_API_KEY}"; // replace with your key
- $deeplClient = new DeepL\DeepLClient($authKey);
-
- $result = $deeplClient->translateText([
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ],
- null,
- 'HI'
- );
-
- echo $result[0]->text . "\n" . $result[1]->text;
- ```
-
- ```text Sample output
- स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?
- हाँ++
- ```
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```csharp Sample request
- using DeepL; // this imports the DeepL namespace. Use the code below in your main program.
-
- var authKey = "{YOUR_API_KEY}"; // replace with your key
- var client = new DeepLClient(authKey);
-
- var translated = await client.TranslateTextAsync(
- [
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ],
- null,
- LanguageCode.Hindi
- );
-
- Console.WriteLine(translated[0].Text + "\n" + translated[1].Text);
- ```
-
- ```text Sample output
- स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?
- हाँ++
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```java Sample request
- import com.deepl.api.*;
- import java.util.List;
-
- public class Main {
- public static void main(String[] args) throws DeepLException, InterruptedException {
- String authKey = "{YOUR_API_KEY}"; // replace with your key
- DeepLClient client = new DeepLClient(authKey);
-
- List results = client.translateText(
- List.of(
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ),
- null,
- "HI"
- );
-
- System.out.println(results.get(0).getText() + "\n" + results.get(1).getText());
- }
- }
- ```
-
- ```text Sample output
- स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?
- हाँ++
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```ruby Sample request
- require 'deepl'
-
- DeepL.configure do |config|
- config.auth_key = '{YOUR_API_KEY}' # replace with your key
- end
-
- translations = DeepL.translate(
- [
- "¿En qué lenguaje programan los programadores españoles?",
- "Sí++"
- ],
- nil,
- 'HI'
- )
-
- puts translations[0].text
- puts translations[1].text
- ```
-
- ```text Sample output
- स्पेनिश प्रोग्रामर कौन-सी प्रोग्रामिंग भाषाएँ उपयोग करते हैं?
- हाँ++
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
-
-
- Jokes are notoriously difficult to translate, especially jokes that rely on an indefensible pun
-
-
-In fact, these text strings can be in different languages. If you don’t set the source language, DeepL will detect that separately for each string.
-
-
-
-
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
-
-
- ```http Sample request
- POST /v2/translate HTTP/2
- Host: api.deepl.com
- Authorization: DeepL-Auth-Key [yourAuthKey]
- User-Agent: YourApp/1.2.3
- Content-Length: 110
- Content-Type: application/json
-
- {
- "text": [
- "What does the 'R' in 'Recursion' stand for?",
- "Recursão"
- ],
- "target_lang": "HA"
- }
- ```
-
- ```json Sample response
- {
- "translations": [
- {
- "text": "Menene R ke nufi a cikin 'Recursion'?",
- "detected_source_language": "EN"
- },
- {
- "text": "Maimaita",
- "detected_source_language": "PT"
- }
- ]
- }
- ```
-
-
-
- If you chose a free API plan and you are writing cURL or HTTP requests, replace `https://api.deepl.com` with `https://api-free.deepl.com`.
-
-
- ```sh Set the API key
- export API_KEY={YOUR_API_KEY}
- ```
-
- ```sh Sample request
- curl -X POST https://api.deepl.com/v2/translate \
- --header "Content-Type: application/json" \
- --header "Authorization: DeepL-Auth-Key $API_KEY" \
- --data '{
- "text": [
- "What does the '\''R'\'' in '\''Recursion'\'' stand for?",
- "Recursão"
- ],
- "target_lang": "HA"
- }'
- ```
-
- ```json Sample response
- {
- "translations": [
- {
- "text": "Menene R ke nufi a cikin 'Recursion'?",
- "detected_source_language": "EN"
- },
- {
- "text": "Maimaita",
- "detected_source_language": "PT"
- }
- ]
- }
- ```
-
-
- ```py Sample request
- import deepl
-
- auth_key = "{YOUR_API_KEY}" # replace with your key
- deepl_client = deepl.DeepLClient(auth_key)
-
- result = deepl_client.translate_text(
- [
- "What does the 'R' in 'Recursion' stand for?",
- "Recursão"
- ],
- target_lang="HA"
- )
-
- print (f"{result[0].text}\n{result[1].text}")
- ```
-
- ```text Sample output
- Menene R ke nufi a cikin 'Recursion'?
- Maimaita
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```javascript Sample request
- import * as deepl from 'deepl-node';
-
- const authKey = "{YOUR_API_KEY}"; // replace with your key
- const deeplClient = new deepl.DeepLClient(authKey);
-
- (async () => {
- const result = await deeplClient.translateText(
- [
- "What does the 'R' in 'Recursion' stand for?",
- "Recursão"
- ],
- null,
- 'HA'
- );
-
- console.log(result[0].text + "\n" + result[1].text);
- })();
- ```
-
- ```text Sample output
- Menene R ke nufi a cikin 'Recursion'?
- Maimaita
-
- ```
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```php Sample request
- require_once 'vendor/autoload.php';
- use DeepL\Client;
-
- $authKey = "{YOUR_API_KEY}"; // replace with your key
- $deeplClient = new DeepL\DeepLClient($authKey);
-
- $result = $deeplClient->translateText([
- "What does the 'R' in 'Recursion' stand for?",
- "Recursão"
- ],
- null,
- 'HA'
- );
-
- echo $result[0]->text . "\n" . $result[1]->text;
- ```
-
- ```text Sample output
- Menene R ke nufi a cikin 'Recursion'?
- Maimaita
- ```
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```csharp Sample request
- using DeepL; // this imports the DeepL namespace. Use the code below in your main program.
-
- var authKey = "{YOUR_API_KEY}"; // replace with your key
- var client = new DeepLClient(authKey);
-
- var translated = await client.TranslateTextAsync(
- [
- "What does the 'R' in 'Recursion' stand for?",
- "Recursão"
- ],
- null,
- LanguageCode.Hausa
- );
-
- Console.WriteLine(translated[0].Text + "\n" + translated[1].Text);
- ```
-
- ```text Sample output
- Menene R ke nufi a cikin 'Recursion'?
- Maimaita
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```java Sample request
- import com.deepl.api.*;
- import java.util.List;
-
- public class Main {
- public static void main(String[] args) throws DeepLException, InterruptedException {
- String authKey = "{YOUR_API_KEY}"; // replace with your key
- DeepLClient client = new DeepLClient(authKey);
-
- List results = client.translateText(
- List.of(
- "What does the 'R' in 'Recursion' stand for?",
- "Recursão"
- ),
- null,
- "HA"
- );
-
- System.out.println(results.get(0).getText() + "\n" + results.get(1).getText());
- }
- }
- ```
-
- ```text Sample output
- Menene R ke nufi a cikin 'Recursion'?
- Maimaita
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
- ```ruby Sample request
- require 'deepl'
-
- DeepL.configure do |config|
- config.auth_key = '{YOUR_API_KEY}' # replace with your key
- end
-
- translations = DeepL.translate(
- [
- "What does the 'R' in 'Recursion' stand for?",
- "Recursão"
- ],
- nil,
- 'HA'
- )
-
- puts translations[0].text
- puts translations[1].text
- ```
-
- ```text Sample output
- Menene R ke nufi a cikin 'Recursion'?
- Maimaita
- ```
-
-
- In production code, it's safer to store your API key in an environment variable.
-
-
-
-
-
-
-## Language codes and variants
-
-The DeepL API can translate in any of [these supported languages](/docs/getting-started/supported-languages). Normally, any supported source language can be used as a target language, and vice versa. But it’s best to check the list to make sure.
-
-To specify a language, use its [ISO-639 language code](https://www.loc.gov/standards/iso639-2/php/code_list.php), such as `FR` for French or `VI` for Vietnamese. While most language codes have two letters, a few have three. For example, the code for Cantonese is `YUE`.
-
-For certain target languages, DeepL supports a set of regional variants, which are listed among [the supported languages](/docs/getting-started/supported-languages). For example, `en-GB` indicates British English, and `en-US` indicates English spoken in the United States. To specify a variant, append to the language code a hyphen, then the [ISO-3166 country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes). So, for Brazilian Portuguese, use `pt-BR`.
-
-In the DeepL API, language codes are case-insensitive. It accepts language codes in uppercase or lowercase, or a mix of the two. So, for Brazilian Portuguese you could use `pt-BR`, `pt-br`, `PT-BR`, or even `pT-Br`.
-
-Regional variants can only be used in target languages. If you try a source language with a variant like `ZH-HANS`, the API will return an error.
-
-If DeepL supports variants of a given language, you are encouraged to choose one. If you don’t include the variant in a raw HTTP request, DeepL will translate into the variant which has been designated as the default. If you’re using a client library, the API will throw an error.
-
-Although you can ask the API to translate from one language variant to another, the methods described in our [How To Translate Between Language Variants guide](/docs/learning-how-tos/examples-and-guides/translating-between-variants) yield better results.
-
-## Where to send your request
-
-The URL you send requests to depends on your API plan. If you are using a free plan, you’ll use `https://api-free.deepl.com`. For a paid plan, use `https://api.deepl.com`.
-
-If you’re using a client library, you don’t need to worry about this, as DeepL’s client libraries detect your account type and send requests to the correct URL.
-
-You may also wish to send requests to an API endpoint corresponding to a specific geographic region, for data residency or compliance needs, or to minimize latency. For more information, instructions on how to set this up, and code samples featuring the `server_url` parameter, see [Regional API Endpoints](/docs/getting-started/regional-endpoints).
-
-## Model type
-
-DeepL hosts many AI models for language translation. As AI is evolving rapidly, we are constantly working on our models and deploying new ones. It would be difficult for users to determine which model to choose for a particular language pair, text, and parameters. Rather than requiring users to select a specific model for a given translation, DeepL follows a simpler approach:
-
-* The [translator app](https://www.deepl.com/en/translator) offers a choice between “classic” and “next-gen” models. “Classic” models often maximize speed, and “next-gen” models generally maximize quality.
-* The DeepL API offers the `model_type` parameter, which lets you choose whether you would prefer a model that maximizes translation quality or a model that runs as quickly as possible. The API will then make its best effort to execute your translation with such a model, and its response will tell you what sort of model we used.
-
-As our models evolve, the distinction between “classic” and “next-gen” is not always meaningful. For some language pairs or translation requests, only one DeepL model can be used. Under some circumstances, we might offer more than two options. The API will simply do the work of choosing for you. The response indicates which model type was used.
-
-The `model_type` parameter can have one of three values:
-
-* `latency_optimized`: aims to maximize speed
-* `quality_optimized`: aims to maximize quality
-* `prefer_quality_optimized`: a legacy value, whose behavior is currently identical to `quality_optimized`
-
-Naturally, the API tries to provide excellent translation quality and low latency for every request.
-
-If you omit the `model_type`, the API normally defaults to `latency_optimized`.
-
-### Notes
-
-* All features and language pairs are compatible with all `model_type` values.
-
-## Limits
-
-The total request body size for text translation requests is limited to 128K. As a request consists of multiple elements along with your text, this means your text can’t hit 128K exactly, but has to be a little smaller.
-
-If you need to send larger strings, you can place them in documents, which have a limit of 10 MB. If that’s not high enough, get in touch with us.
-
-For more, see [Usage and Limits](/docs/resources/usage-limits).
-
-## Summary and next steps
-
-Congratulations! Now you know how to send the DeepL API a translation request including any of these parameters:
-
-| Item | parameter | required? |
-| :---- | :---- | :---- |
-| source language | `source_lang` | optional |
-| target language | `target_lang` | required |
-| text to translate | `text` | required |
-| optimize for speed or quality | `model_type` | optional |
-
-Here are some possible next steps:
-
-* Play with translation requests using these parameters and other options in [our playground](https://developers.deepl.com/api-reference/translate/request-translation?playground=open) or [Postman](/docs/getting-started/test-your-api-requests-with-postman).
-* For complete information on the `/translate` endpoint, see [the `/translate` reference](/api-reference/translate/request-translation)
-* See this [introduction to DeepL glossaries](/docs/learning-how-tos/examples-and-guides/glossaries-in-the-real-world)
-* To learn how to translate text in files - PDFs, presentations, powerpoints, HTML, images, and more - see [the `/document` reference](/api-reference/document)
-* To translate audio, see [the `/voice` reference](/api-reference/voice)
-
diff --git a/docs/mcp.mdx b/docs/mcp.mdx
index 23fb234d..37a2201d 100644
--- a/docs/mcp.mdx
+++ b/docs/mcp.mdx
@@ -106,4 +106,4 @@ and style-rule tools are read-only.
## Related
- [Supported languages](/docs/getting-started/supported-languages)
-- [Translate Text API reference](/docs/api-reference/translate)
+- [Translate Text API reference](/api-reference/translate/request-translation)
diff --git a/docs/multiple-api-keys.mdx b/docs/multiple-api-keys.mdx
index e418afc3..d959cb76 100644
--- a/docs/multiple-api-keys.mdx
+++ b/docs/multiple-api-keys.mdx
@@ -5,7 +5,7 @@ public: true
---
-**Notice**: This page is out-of-date and will soon be removed. Please refer to the ["Managing API Keys"](/docs/getting-started/managing-api-keys) guide in our documentation instead.
+**Notice**: This page is out-of-date and will soon be removed. Please refer to the ["Managing API Keys"](/docs/admin/managing-api-keys) guide in our documentation instead.
## Introducing multiple API keys
diff --git a/docs/resources/breaking-changes-change-notices/march-2025-deprecating-get-requests-to-translate-and-authenticating-with-auth_key.mdx b/docs/resources/breaking-changes-change-notices/march-2025-deprecating-get-requests-to-translate-and-authenticating-with-auth_key.mdx
index 19cf3b6b..a3799ec4 100644
--- a/docs/resources/breaking-changes-change-notices/march-2025-deprecating-get-requests-to-translate-and-authenticating-with-auth_key.mdx
+++ b/docs/resources/breaking-changes-change-notices/march-2025-deprecating-get-requests-to-translate-and-authenticating-with-auth_key.mdx
@@ -24,7 +24,7 @@ On or after March 14, 2025, DeepL will deprecate two little-used API features.
Going forward, you will need to send requests to the `/translate` endpoint using POST, not GET. This also means you will not be able to send such requests using only a URL. You will need to send data in the request body, not in query parameters.
-[This example from the documentation](/api-reference/translate) shows an HTTP POST request to translate the English sentence "Hello, world!" into German.
+[This example from the documentation](/api-reference/translate/request-translation) shows an HTTP POST request to translate the English sentence "Hello, world!" into German.
```HTTP
diff --git a/docs/resources/deepl-developer-community.mdx b/docs/resources/deepl-developer-community.mdx
index 236266ca..369dcbfd 100644
--- a/docs/resources/deepl-developer-community.mdx
+++ b/docs/resources/deepl-developer-community.mdx
@@ -3,9 +3,12 @@ title: "Developer Community"
mode: "wide"
---
-
+The official DeepL Developer Community is on [Discord](https://discord.gg/deepl) and open for everyone to join. It's a friendly, collaborative space to discuss everything DeepL, development, AI, tech and more!
-We're excited to announce [the official DeepL Developer Community](https://www.deepl-bridges.com/) is now available on [DeepL Bridges](https://www.deepl-bridges.com/) for everyone to join. This is a friendly, collaborative space to discuss everything DeepL, development, AI, tech and more!
+
+

+

+
The community is a place to:
@@ -14,4 +17,4 @@ The community is a place to:
* Join upcoming live events and webinars exclusive to the community
* Ask for coding help and tips on development best practice, as well as offering your own help and experience
-[Join Deepl Bridges here!](https://www.deepl-bridges.com/)
+[Join the Discord community here!](https://discord.gg/deepl)
diff --git a/docs/resources/roadmap-and-release-notes.mdx b/docs/resources/roadmap-and-release-notes.mdx
index ea0eb52f..f7dd6c8f 100644
--- a/docs/resources/roadmap-and-release-notes.mdx
+++ b/docs/resources/roadmap-and-release-notes.mdx
@@ -13,12 +13,12 @@ rss: true
## July 2 - New Voice API Languages: Hindi, Malay, and Tamil
- The Voice API now supports `hi` (Hindi), `ms` (Malay), and `ta` (Tamil) in beta. Translation is provided by DeepL; transcription and translated speech are provided by external service partners.
- These languages are marked `"external": true` in the [`GET /v3/languages?resource=voice`](/api-reference/languages/retrieve-supported-languages-by-resource) response. Because they are beta and external, call with `include=beta&include=external` to see them.
-- See the [supported languages table](/api-reference/voice#supported-languages) for the full list.
+- See the [supported languages table](/docs/voice/supported-languages-formats-and-limits#supported-languages) for the full list.
## June 24 - API Key Permissions General Availability
-- [API key permissions](/docs/getting-started/managing-api-keys#api-key-permissions) are now generally available. Scope a developer API key to specific endpoints so it can perform only the operations you allow.
+- [Understanding API Key Permissions](/docs/admin/api-key-permissions) are now generally available. Scope a developer API key to specific endpoints so it can perform only the operations you allow.
- Available on the API Pro, API Developer, API Growth, and API Enterprise plans.
- Assign scopes when [creating or editing a key](https://www.deepl.com/your-account/keys). A scoped key returns `403 Forbidden` on any endpoint its scopes don't cover.
@@ -26,11 +26,11 @@ rss: true
- [`POST /v2/translate`](/api-reference/translate/request-translation) and [`POST /v2/document`](/api-reference/document/upload-and-translate-a-document) now accept a `glossary_ids` parameter, allowing you to apply up to 5 glossaries to a single translation request.
- Useful when terminology is split across multiple glossaries (for example, a shared brand glossary plus a project-specific glossary) that you want applied together without merging them.
- `glossary_ids` requires `source_lang` and is mutually exclusive with the existing `glossary_id` parameter. Every listed glossary must contain a dictionary for the requested language pair.
-- See the [text translation](/api-reference/translate#request-body-descriptions) and [document translation](/api-reference/document#request-body-descriptions) overview pages for parameter details.
+- See the [text translation](/api-reference/translate/request-translation) and [document translation](/api-reference/document/upload-and-translate-a-document) overview pages for parameter details.
## June 17 - `latency_optimized` Now Supported for All Features
- The `latency_optimized` model type is now fully compatible with all Translate API features, including:
- - [Tag handling v2](/docs/xml-and-html-handling/tag-handling-v2) (`tag_handling_version=v2`)
+ - [Tag handling v2](/docs/translate/translating-xml) (`tag_handling_version=v2`)
- [Style rules](/api-reference/style-rules) (`style_id`)
- [Custom instructions](/docs/best-practices/custom-instructions) (`custom_instructions`)
- [Translation memories](/docs/learning-how-tos/examples-and-guides/how-to-use-translation-memories) (`translation_memory_id`)
@@ -38,7 +38,7 @@ rss: true
- Previously, combining `model_type=latency_optimized` with these features would return an error. These restrictions have been removed.
## June 15 - API Key Permissions (Private Beta)
-- Developer API keys can now be scoped to specific endpoints, so a key can be limited to, for example, translating text or reading glossaries. See [API key permissions](/docs/getting-started/managing-api-keys#api-key-permissions).
+- Developer API keys can now be scoped to specific endpoints, so a key can be limited to, for example, translating text or reading glossaries. See [Understanding API Key Permissions](/docs/admin/api-key-permissions).
- Assign one or more scopes when [creating or editing a key](https://www.deepl.com/your-account/keys). A scoped key returns `403 Forbidden` on any endpoint its scopes don't cover.
- Currently in private beta for select customers. To request access, contact your customer success manager or [DeepL support](https://support.deepl.com/hc/en-us/requests/new).
- Not yet supported for the Voice API; Voice scopes will follow in a future update.
@@ -52,7 +52,7 @@ rss: true
## June 5 - Voice API Spoken Terms on External-Provider Languages
- Spoken terms are now supported on languages whose transcription is provided by external service partners, in addition to languages transcribed by DeepL. The feature remains in beta on all supported languages.
- External-provider languages are marked `"external": true` in the [`GET /v3/languages?resource=voice`](/api-reference/languages/retrieve-supported-languages-by-resource) response. Call with `include=beta&include=external` to see the full list.
-- See [Voice API Customization](/api-reference/voice#customization) for usage details.
+- See [Voice API Customization](/docs/voice/overview#customization) for usage details.
## June 3 - Docs MCP Server
- DeepL's developer documentation now exposes an MCP server at `https://developers.deepl.com/mcp`.
@@ -76,7 +76,7 @@ rss: true
- Source code on GitHub: [`DeepLcom/deepl-api-usage-logger`](https://github.com/DeepLcom/deepl-api-usage-logger).
## May 20 - Custom Tag Usage Analytics
-- Added [`GET /v2/admin/analytics/custom-tags`](/api-reference/admin-api/organization-usage-analytics) to the Admin API, allowing admins to retrieve usage statistics broken down by custom tags.
+- Added [`GET /v2/admin/analytics/custom-tags`](/api-reference/admin-api/get-custom-tag-usage-analytics) to the Admin API, allowing admins to retrieve usage statistics broken down by custom tags.
- Supports `aggregate_by=period` (default) to aggregate usage over the full date range, or `aggregate_by=day` for daily breakdowns.
- Results are paginated; use the `next_page` integer from the response as the `page` parameter in subsequent requests.
@@ -84,7 +84,7 @@ rss: true
- New optional `spoken_terms_id` parameter on [`POST /v3/voice/realtime`](/api-reference/voice/request-session) to improve transcription of frequently used terms like company-specific terminology, acronyms, product names, and team member names.
- Spoken terms are currently in beta, supported for 18 source languages. Manage them in [DeepL Home](https://www.deepl.com/en/voice/spoken-terms); API management will follow in a future update.
- The new `spoken_terms` feature and the existing `translated_speech` feature are now exposed as beta in [`GET /v3/languages?resource=voice`](/api-reference/languages/retrieve-supported-languages-by-resource), so clients can discover language support programmatically.
-- Not yet supported for transcription provided by external service partners (languages marked with ⎋). See [Voice API Customization](/api-reference/voice#customization) for details.
+- Not yet supported for transcription provided by external service partners (languages marked with ⎋). See [Voice API Customization](/docs/voice/overview#customization) for details.
## May 18 - v3/languages General Availability
- [`GET /v3/languages`](/api-reference/languages/retrieve-supported-languages-by-resource) and [`GET /v3/languages/resources`](/api-reference/languages/retrieve-resources) are now generally available.
@@ -104,7 +104,7 @@ rss: true
- See [supported languages](../getting-started/supported-languages) for the complete language list.
## April 15 - Voice API General Availability
-- The [Voice API](/api-reference/voice) is now available to all DeepL customers with a paid API subscription. This API provides real-time speech transcription and translation and can be used with existing DeepL API keys.
+- The [Voice API](/docs/voice/overview) is now available to all DeepL customers with a paid API subscription. This API provides real-time speech transcription and translation and can be used with existing DeepL API keys.
## April 9 - Translation Memory API
- Added support for [translation memories](/docs/learning-how-tos/examples-and-guides/how-to-use-translation-memories) in the DeepL API. Translation memories store previously translated segments so the same source text produces consistent output across projects .
@@ -113,7 +113,7 @@ rss: true
- Support for uploading, modifying, and deleting translation memories via the API will follow.
## April 2 - Voice API Language Expansion
-- Added 6 new languages to the [Voice API](/api-reference/voice) for transcription: Bengali (`bn`), Croatian (`hr`), Dutch (`nl`), Irish (`ga`), Maltese (`mt`), and Tagalog (`tl`). Five of these are provided by external service partners; Dutch is provided by DeepL.
+- Added 6 new languages to the [Voice API](/docs/voice/overview) for transcription: Bengali (`bn`), Croatian (`hr`), Dutch (`nl`), Irish (`ga`), Maltese (`mt`), and Tagalog (`tl`). Five of these are provided by external service partners; Dutch is provided by DeepL.
- All supported voice languages can now be used as source languages for transcription. Previously, source language selection was restricted to a subset of the supported languages.
@@ -144,7 +144,7 @@ rss: true
## January 27 - Voice Usage Limits on Developer Keys
- Added `speech_to_text_milliseconds` to the `/v2/admin/developer-keys/limits` endpoint and the `ApiKey` response schema, so admins can set and read per-key voice usage limits alongside character limits.
-- See the [Admin API reference](/api-reference/admin-api) for usage.
+- See the [Admin API overview](/docs/admin/overview) for usage.
## January 20 - Legacy Auth Deprecation
@@ -155,7 +155,7 @@ Query parameter and request body authentication methods are now [deprecated](/do
Use the `DeepL-Auth-Key` header instead.
## January 19 - Voice API Speech-to-Speech (Closed Beta)
-- New speech-to-speech capability in the [Voice API](/api-reference/voice): synthesize translated audio (TTS output) alongside transcription and text translation in the same WebSocket session.
+- New speech-to-speech capability in the [Voice API](/docs/voice/overview): synthesize translated audio (TTS output) alongside transcription and text translation in the same WebSocket session.
- New request parameters on [`POST /v3/voice/realtime`](/api-reference/voice/request-session): `target_media_languages` (target languages for synthesized speech), `target_media_content_type` (audio format), and `target_media_voice` (voice selection).
- Translated speech is in closed beta and not included in standard API subscriptions.
@@ -177,7 +177,7 @@ See [here](../getting-started/supported-languages) for the complete language lis
## November 10 - Voice API Initial Release
- Initial release of the Voice API: `/v1/voice/realtime` (REST) and `/v1/voice/realtime/connect` (WebSocket) for real-time speech transcription and translation. The Voice API is generally available as of [April 15, 2026](#april-15---voice-api-general-availability).
-- Published a new AsyncAPI specification (`voice.asyncapi.yaml` / `voice.asyncapi.json`) documenting the WebSocket streaming protocol. See the [Voice API reference](/api-reference/voice).
+- Published a new AsyncAPI specification (`voice.asyncapi.yaml` / `voice.asyncapi.json`) documenting the WebSocket streaming protocol. See the [WebSocket Streaming reference](/api-reference/voice/websocket-streaming).
## November 6 - HE, TH, and VI in `/v2/languages`
- Hebrew (`HE`), Thai (`TH`), and Vietnamese (`VI`) now appear in the [`/v2/languages`](/api-reference/languages) response, since they support document translation in addition to text translation.
@@ -188,17 +188,17 @@ See [here](../getting-started/supported-languages) for the complete language lis
- Added API reference for the Voice API
- Add contextual menu in the to make it easier to copy any API documentation page as context for AI tools
- Add support for style rules in the API to programmatically get your created style rules and translate with them.
-- Overhauled the tag-handling algorithm that backs translation of XML and HTML in the DeepL API. To enable it and benefit from all the improvements, set the `tag_handling_version` parameter to `v2` in the text translation API. See [here](../xml-and-html-handling/tag-handling-v2) for more information.
+- Overhauled the tag-handling algorithm that backs translation of XML and HTML in the DeepL API. To enable it and benefit from all the improvements, set the `tag_handling_version` parameter to `v2` in the text translation API. See [Translating XML](/docs/translate/translating-xml) for more information.
- Added new usage analytics endpoint in the Admin API, including key-level reporting. See [here](/api-reference/admin-api/get-usage-analytics) for more details
- Enabled support for multiple admins in an API subscription
- Added support for 75 new languages, initially through the `enable_beta_languages` parameter, for text and document translation. Beta languages are not billed during the beta phase and do not yet support glossaries or formality. See [here](../getting-started/supported-languages) for more information
- Added HE, TH and VI to the languages endpoint, since they are now also available in document translation
- Added 6 additional beta languages, for text and document translation. See the previous note about 75 new languages.
- Added a new parameter to the text translation API to allow custom instructions, making it possible to customize the translation behavior (e.g. ["Use a friendly, diplomatic tone"])
-- Added support for JPEG and PNG images in [document translation](/api-reference/document), currently in Beta.
+- Added support for JPEG and PNG images in [document translation](/api-reference/document/upload-and-translate-a-document), currently in Beta.
## Q3 2025
-- Creation of an admin API, making it possible to manage API keys programmatically. See [here](/api-reference/admin-api) for more information
+- Creation of an admin API, making it possible to manage API keys programmatically. See the [Admin API overview](/docs/admin/overview) for more information
- Added support for new language: ES-419 (Latin American Spanish). For this release, this language will be available for the API in next-gen models only. See [here](../getting-started/supported-languages) for more information.
- Refreshed our API documentation and added new try-it explorers to support interacting with our APIs. See [here](/api-reference) to try it out!
@@ -207,20 +207,20 @@ See [here](../getting-started/supported-languages) for the complete language lis
- Added support for new languages: HE (Hebrew) and VI (Vietnamese). For this release, these languages will be available for Pro v2 API in next-gen models only. See [here](../getting-started/supported-languages) for more information.
- Added improvements to API glossaries, including the ability to edit glossaries and create multilingual glossaries. Learn more [here](/api-reference/multilingual-glossaries/).
- Added new events to audit logs for Pro API customers (API key management, cost control and usage limit changes)
-- Improvements to the `/usage` endpoint for Pro API customers ([API reference](/api-reference/usage-and-quota/))
-- Improvements to key-level usage reporting, making it possible to pull reports with a custom date range and to group data by calendar day. Learn more [here](../getting-started/managing-api-keys#get-api-key-level-usage).
+- Improvements to the `/usage` endpoint for Pro API customers ([API reference](/api-reference/usage-and-quota/check-usage-and-limits))
+- Improvements to key-level usage reporting, making it possible to pull reports with a custom date range and to group data by calendar day. Learn more [here](/docs/admin/retrieving-usage-data#api-key-level-csv-export).
## Q1 2025
-- Added support for API key-level usage limits, making it possible to set a character limit at the API key-level. Learn more [here](../getting-started/managing-api-keys#set-api-key-level-usage-limits).
+- Added support for API key-level usage limits, making it possible to set a character limit at the API key-level. Learn more [here](/docs/admin/managing-api-keys#set-a-key-level-usage-limit).
- DeepL API for Write is generally available to Pro API customers, making it possible to improve texts in (at the time of release) 6 different languages. Learn more and get started [here](/api-reference/improve-text/).
## Q4 2024
-- Added the `model_type` parameter, allowing users to translate text with DeepL's "next-gen" translation models. More information can be found [here](/api-reference/translate#about-the-model_type-parameter).
+- Added the `model_type` parameter, allowing users to translate text with DeepL's "next-gen" translation models. More information can be found [here](/docs/translate/understanding-model-types).
## Q3 2024
-- Added the `show_billed_characters` parameter for text translation, allowing users to optionally include the number of billed characters in the API response. [Learn more here](/api-reference/translate#request-body-descriptions).
+- Added the `show_billed_characters` parameter for text translation, allowing users to optionally include the number of billed characters in the API response. [Learn more here](/api-reference/translate/request-translation).
- Added support for a new language for text translation: ZH-HANT (Traditional Chinese). As of this initial release, document translation is not supported for Traditional Chinese. More information is available [here](/docs/getting-started/supported-languages).
- An official Ruby client library, evolved from a community-written library by Daniel Herzog. You can download it [here](https://rubygems.org/gems/deepl-rb) or find the source code on our [GitHub page](https://github.com/DeepLcom/deepl-rb).
- Added Romanian (`RO`) as a supported [glossary](/api-reference/multilingual-glossaries) language.
@@ -230,8 +230,8 @@ See [here](../getting-started/supported-languages) for the complete language lis
- Added support for API key-level usage reporting. More information is available in the [multiple API keys guide](https://developers.deepl.com/multiple-api-keys#download-a-report-with-key-level-usage).
- Launched DeepL Pro in [165 new markets](https://www.deepl.com/en/blog/deepl-pro-expands-165-new-markets), bringing the total number of markets where DeepL Pro is available to 228. This means users with billing addresses in these markets can create DeepL Pro API and Free API subscriptions.
- Added support for new glossary languages: DA (Danish), NB (Norwegian Bokmål), and Swedish (SV).
-- Moved the `context` parameter from [alpha](/docs/getting-started/alpha-and-beta-features) status to general availability. More information about the context parameter is available in the "Request body descriptions" table [here](/api-reference/translate).
-- Added support for SRT (`srt`) files in [document translation](/api-reference/document).
+- Moved the `context` parameter from [alpha](/docs/getting-started/alpha-and-beta-features) status to general availability. More information about the context parameter is available in the "Request body descriptions" table [here](/api-reference/translate/request-translation).
+- Added support for SRT (`srt`) files in [document translation](/api-reference/document/upload-and-translate-a-document).
## Q1 2024
- Added support for multiple API keys in a single account for Pro API and Free API users. More information is available in the [multiple API keys guide](https://developers.deepl.com/multiple-api-keys).
@@ -241,8 +241,8 @@ See [here](../getting-started/supported-languages) for the complete language lis
## Q4 2023
-- Added support for Microsoft Excel (`xlsx`) files in [document translation](/api-reference/document).
-- Released the `context` parameter as an [alpha feature](/docs/getting-started/alpha-and-beta-features) for text translation (see [Request Body Descriptions table](/api-reference/translate#request-body-descriptions) for more information).
+- Added support for Microsoft Excel (`xlsx`) files in [document translation](/api-reference/document/upload-and-translate-a-document).
+- Released the `context` parameter as an [alpha feature](/docs/getting-started/alpha-and-beta-features) for text translation (see [Request Body Descriptions table](/api-reference/translate/request-translation) for more information).
## Q3 2023
- Launched DeepL Pro in South Korea ([blog post here](https://www.deepl.com/en/blog/deepl-pro-available-in-south-korea)). This means users with billing addresses in South Korea can [create DeepL Pro API and Free API subscriptions](https://www.deepl.com/ko/pro#developer).
@@ -252,25 +252,25 @@ See [here](../getting-started/supported-languages) for the complete language lis
## Q2 2023
- Added support for user-provided http clients in [PHP client library](https://github.com/DeepLcom/deepl-php).
- Released an official [DeepL API Postman collection](https://www.postman.com/deepl-api/workspace/deepl-api-developers/overview).
-- Added formality support for Japanese (JA) in [text](/api-reference/translate) and [document](/api-reference/document) translation.
+- Added formality support for Japanese (JA) in [text](/api-reference/translate/request-translation) and [document](/api-reference/document/upload-and-translate-a-document) translation.
- Released in-house PDF translation; removed requirement to send data to the US when translating PDF documents ([blog post](https://www.deepl.com/en/blog/deepl-launches-in-house-pdf-translation-for-improved-security-and-efficiency)).
## Q1 2023
- Released an official [DeepL Custom Connector](https://support.deepl.com/hc/en-us/articles/8644041855516-DeepL-API-custom-connector-for-Microsoft-Power-Automate) for Microsoft Power Automate.
- Added support for glossaries in any combination of two languages from the following list: EN (English), DE (German), FR (French), IT (Italian), PL (Polish), NL (Dutch), ES (Spanish, JA (Japanese). This represents an increase from 8 to 28 supported glossary language pairs.
-- Added XLIFF as a [document translation](/api-reference/document) format (*note that only documents from version 2.0 are supported, and there is no support for the legacy 1.2 format*).
+- Added XLIFF as a [document translation](/api-reference/document/upload-and-translate-a-document) format (*note that only documents from version 2.0 are supported, and there is no support for the legacy 1.2 format*).
- Added support for new languages for text and document translation: KO (Korean) and NB (Norwegian Bokmål). [Blog post here](https://www.deepl.com/en/blog/welcome-korean-and-norwegian).
## Q4 2022
-- Moved [HTML handling](/docs/xml-and-html-handling/html) out of beta after fixing the most commonly reported user issues.
+- Moved [HTML handling](/docs/translate/translating-html) out of beta after fixing the most commonly reported user issues.
- Released an official [Java client library](https://github.com/DeepLcom/deepl-java).
-- Added support for JSON-encoded requests for [text translation](/api-reference/translate), [usage](/api-reference/usage-and-quota), and [languages](/api-reference/languages) endpoints.
+- Added support for JSON-encoded requests for [text translation](/api-reference/translate/request-translation), [usage](/api-reference/usage-and-quota/check-usage-and-limits), and [languages](/api-reference/languages) endpoints.
## Q3 2022
- Released an official [PHP client library](https://github.com/DeepLcom/deepl-php).
-- Added support for a new language for [text](/api-reference/translate) and [document](/api-reference/document) translation: UK (Ukrainian). [Blog post here](https://www.deepl.com/en/blog/deepl-learns-ukrainian).
+- Added support for a new language for [text](/api-reference/translate/request-translation) and [document](/api-reference/document/upload-and-translate-a-document) translation: UK (Ukrainian). [Blog post here](https://www.deepl.com/en/blog/deepl-learns-ukrainian).
## Before Q3 2022
- Released an official DeepL API [OpenAPI spec](https://github.com/DeepLcom/openapi).
@@ -279,8 +279,8 @@ See [here](../getting-started/supported-languages) for the complete language lis
- Released an official [Python client library](https://github.com/DeepLcom/deepl-python).
- Added support for [glossaries](/api-reference/multilingual-glossaries) in the DeepL API.
- Released an open-source sample project for [translating with DeepL in Google Sheets](https://github.com/DeepLcom/google-sheets-example).
-- Added the `prefer_less` and `prefer_more` formality options on [text translation](/api-reference/translate), giving more graceful fallback than the strict `more` and `less` values for languages without full formality support.
+- Added the `prefer_less` and `prefer_more` formality options on [text translation](/api-reference/translate/request-translation), giving more graceful fallback than the strict `more` and `less` values for languages without full formality support.
- Added CSV as an entries format for creating [glossaries](/api-reference/multilingual-glossaries), alongside the existing tab-separated format.
-- Removed the previous limit of 50 `text` parameters per [text translation](/api-reference/translate) request.
+- Removed the previous limit of 50 `text` parameters per [text translation](/api-reference/translate/request-translation) request.
- ...and much more :)
diff --git a/docs/resources/usage-limits.mdx b/docs/resources/usage-limits.mdx
index 6804f198..f9bc0e92 100644
--- a/docs/resources/usage-limits.mdx
+++ b/docs/resources/usage-limits.mdx
@@ -36,6 +36,6 @@ title: "Usage and limits"
Retrieve usage information within the current billing period together with the corresponding account limits.
-Usage is returned and tracked for translated characters. Note that for [text translation](/api-reference/translate), characters are still counted toward billing when the source and target languages are equal.
+Usage is returned and tracked for translated characters. Note that for [text translation](/api-reference/translate/request-translation), characters are still counted toward billing when the source and target languages are equal.
Character usage includes both text and document translations, and is measured by the source text length in Unicode code points. For example, "A", "Δ", "あ", and "深" are each counted as a single character.
diff --git a/docs/retrieving-usage-data.mdx b/docs/retrieving-usage-data.mdx
deleted file mode 100644
index 1a517a20..00000000
--- a/docs/retrieving-usage-data.mdx
+++ /dev/null
@@ -1,98 +0,0 @@
----
-title: "Retrieving usage data"
-description: "Learn how to retrieve and monitor your DeepL API usage data."
-public: true
----
-DeepL offers a variety of ways to retrieve usage data so you can keep track of character and minute consumption and associated costs. This guide walks through all of the ways you can get your DeepL API usage data.
-
-
-Character and minute consumption data on the ["API Keys & Limits" tab](https://www.deepl.com/en/your-account/keys), the ["API Usage" tab](https://www.deepl.com/en/your-account/usage), in API key-level CSV exports, and in the [Admin analytics API](/api-reference/admin-api/organization-usage-analytics) is available up to and including the previous UTC calendar day. For example, on 19 May 2025, data would be available up to and including 18 May 2025.
-
-We recommend the `/usage` endpoint ([docs](/api-reference/usage-and-quota)) to see near-real-time character and minute consumption data.
-
-
-## Choosing a data source
-
-| Data source | Scope | Time range | Data freshness | Interface |
-| --- | --- | --- | --- | --- |
-| [API Keys & Limits tab](#api-keys-&-limits-tab) | Per API key | Current usage period only | Previous UTC day | Admin area UI |
-| [API Usage tab](#api-usage-tab) | Account total (plus yearly-to-date on yearly plans) | Current usage period (and yearly period) | Previous UTC day | Admin area UI |
-| [API key-level CSV export](#api-key-level-csv-export) | Per API key | Custom or preset ranges up to 4 months, optional grouping by day | Previous UTC day | CSV download |
-| [`/usage` endpoint](#/usage-endpoint) | Account total | Current usage period only | Near-real-time (within minutes) | REST API |
-| [Admin analytics API](#admin-analytics-api) | Per API key or per custom tag | Custom date range, optional grouping by day | Previous UTC day | REST API |
-
-Use the **admin area UI** for a quick check while signed in, the **CSV export** for detailed or offline analysis per key, the **`/usage` endpoint** for programmatic near-real-time quota checks, and the **Admin analytics API** for programmatic reporting and cost attribution via custom tags.
-
-## Directly in the admin area UI
-
-When you are signed into your account, there are two tabs that contain API usage data.
-
-### API Keys & Limits tab
-
-The [API Keys & Limits tab](https://www.deepl.com/en/your-account/keys) shows API key-level character and speech-to-text (STT) minute consumption for the current monthly usage period only.
-
-
-
-
-
-### API Usage tab
-
-The [API Usage tab](https://www.deepl.com/en/your-account/usage) shows total character and STT minute usage for the current monthly usage period, and if you're on a yearly plan, it shows usage to date for your yearly billing period, too.
-
-
-
-
-
-## CSV exports
-
-### API key-level CSV export
-
-It's possible to generate a CSV report with key-level characters translated for the specified time period. The following time periods are currently supported. Depending on the reporting time period selected, the time period might not always start and end on a full calendar day.
-
-| Time period | Range basis | Includes current day |
-| --- | --- | --- |
-| Custom date range | Start and end on UTC calendar day, up to 4 months | Depends on selected range |
-| Last 24 hours | Current time minus 24 hours | Yes |
-| Last 7 days | Current time minus 7 days | Yes |
-| Last 30 days | Current time minus 30 days | Yes |
-| Last year | Current time minus 1 year | Yes |
-| Current month | Starts on UTC calendar day | Yes |
-| Last month | Start and end on UTC calendar day | No |
-| Current usage period | Usage period boundaries | Yes |
-| Last usage period | Usage period boundaries | No |
-
-Document translation data is only included in reports with a time period starting on or after May 16, 2024 00:00 UTC. Text translation data is included for all time periods.
-
-Key-level usage is not broken out on invoices and is only available via CSV export or on the "API Keys & Limits" tab.
-
-To download a report with key-level usage, first click on the "Download key-level usage report" button on the [API Keys tab](https://www.deepl.com/en/your-account/keys) or the "Download report" link on the [Usage tab](https://www.deepl.com/en/your-account/usage).
-
-You can then select a time period and click the "Download your report" button to download your CSV report.
-
-
-
-
-
-For all time ranges _except_ "Last 24 hours", "Current usage period", and "Last usage period", it's also possible to group key-level usage data by UTC calendar day:
-
-
-
-
-
-## /usage endpoint
-
-The [`/usage` endpoint](/api-reference/usage-and-quota) makes it possible to retrieve a near-real-time snapshot of character and minute usage in the current monthly usage period only. Data retrieved from the `/usage` endpoint is typically up to date within a few minutes of the usage being generated.
-
-## Admin analytics API
-
-The [Admin API](/api-reference/admin-api) provides programmatic access to usage data grouped by API key or by custom tag. It allows you to specify a date range and to optionally group data by day.
-
-All customers with API Growth and API Enterprise plans have access to the Admin API. The Admin API can also be enabled for select Pro API customers. Please contact your customer success manager or our support team to receive access.
-
-See the [key-level usage analytics reference](/api-reference/admin-api/get-usage-analytics) to learn more about pulling API key-level usage data.
-
-See the [custom-tag usage analytics reference](/api-reference/admin-api/get-custom-tag-usage-analytics) to learn more about pulling custom tag-level usage data.
-
-The [custom reporting tags guide](/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags) provides a more detailed overview of how to set up custom tags in your API requests.
-
-We've also created an [open source project](/docs/learning-how-tos/cookbook/usage-analytics-dashboard) that demonstrates how to build your own dashboard using our Admin API.
diff --git a/docs/translate/overview.mdx b/docs/translate/overview.mdx
new file mode 100644
index 00000000..43f91b92
--- /dev/null
+++ b/docs/translate/overview.mdx
@@ -0,0 +1,39 @@
+---
+title: "Translate"
+sidebarTitle: "Overview"
+description: "Translate text strings and complete documents with the DeepL API. Find quickstarts, markup handling guides, and customization options."
+public: true
+---
+
+The Translate API converts text between any of the [supported languages](/docs/getting-started/supported-languages) through two endpoints:
+
+- **Text translation** (`/v2/translate`): translate one or many strings per request, with automatic source language detection. Suited for UI strings, messages, and any text your application handles directly.
+- **Document translation** (`/v2/document`): upload complete files, including Word, PowerPoint, PDF, and HTML, and download the translation with the original formatting intact.
+
+## Start here
+
+
+
+ Send your first translation request and batch multiple strings into one call.
+
+
+ Upload a Word document, poll its status, and download the translated file.
+
+
+ Improve translation quality for short or ambiguous text by passing surrounding context.
+
+
+ Translate markup without breaking it: tag handling for XML, HTML, and structured content.
+
+
+ Full request and response schemas for the text and document translation endpoints.
+
+
+
+## Customize translations
+
+Beyond per-request parameters, three features let you tailor translations to your domain and keep terminology consistent:
+
+- **[Glossaries](/docs/learning-how-tos/examples-and-guides/glossaries-in-the-real-world)**: enforce specific translations for individual terms, like product names or industry vocabulary
+- **[Custom instructions](/docs/best-practices/custom-instructions)**: steer tone, style, and phrasing with natural-language instructions
+- **[Translation memories](/docs/learning-how-tos/examples-and-guides/how-to-use-translation-memories)**: reuse your previously approved translations for matching segments
diff --git a/docs/translate/translate-documents-quickstart.mdx b/docs/translate/translate-documents-quickstart.mdx
new file mode 100644
index 00000000..e6099c0b
--- /dev/null
+++ b/docs/translate/translate-documents-quickstart.mdx
@@ -0,0 +1,166 @@
+---
+title: "Translate Documents Quickstart"
+description: "Upload a Word document to the DeepL API, poll its translation status, and download the translated file, in three curl calls or one client library call."
+covers: [Translate]
+public: true
+---
+
+In this tutorial, you'll translate a complete document with the DeepL API: upload a file, poll until the translation is done, and download the result. By the end, you'll have run the full asynchronous flow with curl and seen how the client libraries collapse it into a single call.
+
+Document translation preserves the file's formatting and supports Word, PowerPoint, Excel, PDF, HTML, XLIFF, SRT subtitles, and more. See the [full list of supported formats](/api-reference/document/upload-and-translate-a-document).
+
+## Prerequisites
+
+- A DeepL API account and your API key from [your account settings](https://www.deepl.com/your-account/keys). New to the API? Start with the [Translate Text Quickstart](/docs/translate/translate-text-quickstart), which covers signup in more detail.
+- `curl` installed on your machine
+- A document to translate. The examples use a Word file named `order-confirmation.docx`; any supported format works.
+
+
+If you're on a free API plan, replace `https://api.deepl.com` with `https://api-free.deepl.com` in curl examples. Client libraries detect your account type and pick the correct URL automatically.
+
+
+## Building with an AI coding agent?
+
+Wire it up to the [DeepL Docs MCP Server](/docs/getting-started/docs-mcp-server) so it can search and read this documentation while it writes code. In Claude Code:
+
+```bash
+claude mcp add --transport http deepl-docs https://developers.deepl.com/mcp
+```
+
+Then describe what you want to build. To get the same result as this tutorial, paste:
+
+```text wrap
+Using the DeepL API, write a script that uploads order-confirmation.docx for translation to German, polls the status until it's done, and downloads the translated file.
+```
+
+Setup instructions for Claude Desktop, Cursor, VS Code, and other MCP clients are on the [Docs MCP Server page](/docs/getting-started/docs-mcp-server).
+
+## Step 1: Upload the document
+
+Document translation runs asynchronously, so the flow has three calls: upload the file, check the status, and download the result. Start by uploading the file as `multipart/form-data` with a `target_lang`:
+
+```sh Sample request
+export API_KEY={YOUR_API_KEY}
+
+curl -X POST https://api.deepl.com/v2/document \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --form 'target_lang=DE' \
+ --form 'file=@order-confirmation.docx'
+```
+
+```json Sample response
+{
+ "document_id": "04DE5AD98A02647D83285A36021911C6",
+ "document_key": "0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"
+}
+```
+
+The response returns as soon as the upload completes, while the translation continues in the background. Store both values: the `document_id` identifies the translation, and the `document_key` authorizes the status and download calls in the next steps.
+
+As with text translation, the source language is detected automatically, or you can pin it with an optional `source_lang` form field.
+
+## Step 2: Poll the translation status
+
+Check the status by sending the `document_key` to the `/v2/document/{document_id}` endpoint:
+
+```sh Sample request
+curl -X POST https://api.deepl.com/v2/document/04DE5AD98A02647D83285A36021911C6 \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --header "Content-Type: application/json" \
+ --data '{
+ "document_key": "0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"
+}'
+```
+
+While the document is being translated, the `status` field is `queued` or `translating`:
+
+```json Sample response: still translating
+{
+ "document_id": "04DE5AD98A02647D83285A36021911C6",
+ "status": "translating",
+ "seconds_remaining": 20
+}
+```
+
+Repeat the call at regular intervals or with exponential backoff until the status is `done`. Small documents typically finish in seconds; larger ones can take a minute or two. Treat `seconds_remaining` as a rough estimate only.
+
+```json Sample response: done
+{
+ "document_id": "04DE5AD98A02647D83285A36021911C6",
+ "status": "done",
+ "billed_characters": 1337
+}
+```
+
+A status of `error` comes with a `message` field explaining what went wrong, for example when the source and target language are the same.
+
+## Step 3: Download the translated file
+
+Once the status is `done`, download the result from the `/result` endpoint and save it to a file:
+
+```sh Sample request
+curl -X POST https://api.deepl.com/v2/document/04DE5AD98A02647D83285A36021911C6/result \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --header "Content-Type: application/json" \
+ --data '{
+ "document_key": "0CB0054F1C132C1625B392EADDA41CB754A742822F6877173029A6C487E7F60A"
+}' \
+ --output order-confirmation-de.docx
+```
+
+Open `order-confirmation-de.docx` and you'll find the German translation with the original layout intact.
+
+For privacy reasons, the document is removed from DeepL's servers once you download it, so it can't be downloaded twice. To translate the same file again, start over from step 1. Download promptly: leaving too many finished translations unretrieved can cause new upload requests to fail with HTTP 429.
+
+
+Every submitted `docx`, `doc`, `pptx`, `xlsx`, or `pdf` file is billed a minimum of 50,000 characters, regardless of how much text it contains.
+
+
+## Or: one call with a client library
+
+The [official client libraries](/docs/getting-started/client-libraries) wrap all three steps, upload, polling, and download, in a single method call:
+
+
+
+ ```py Sample request
+ import deepl
+
+ auth_key = "{YOUR_API_KEY}" # replace with your key
+ deepl_client = deepl.DeepLClient(auth_key)
+
+ deepl_client.translate_document_from_filepath(
+ "order-confirmation.docx",
+ "order-confirmation-de.docx",
+ target_lang="DE",
+ )
+ ```
+
+
+ ```javascript Sample request
+ import * as deepl from 'deepl-node';
+
+ const authKey = "{YOUR_API_KEY}"; // replace with your key
+ const deeplClient = new deepl.DeepLClient(authKey);
+
+ (async () => {
+ await deeplClient.translateDocument(
+ 'order-confirmation.docx',
+ 'order-confirmation-de.docx',
+ null,
+ 'de'
+ );
+ })();
+ ```
+
+
+
+The PHP, C#, Java, and Ruby libraries offer the same convenience method; see each [library's documentation](/docs/getting-started/client-libraries) for details.
+
+## Next steps
+
+You've now run the complete document translation flow. To keep going:
+
+- Read the [document translation guide](/docs/best-practices/document-translations) for format-specific behavior (XML, XLIFF, JSON, IDML) and error handling
+- Convert formats on the way through, like PDF in and editable Word out, with the `output_format` parameter in the [`/document` reference](/api-reference/document/upload-and-translate-a-document)
+- Enforce your terminology with [glossaries](/docs/learning-how-tos/examples-and-guides/glossaries-in-the-real-world)
+- Check the [upload size limits per format](/docs/resources/usage-limits#maximum-upload-limits-per-document-format) before going to production
diff --git a/docs/translate/translate-text-quickstart.mdx b/docs/translate/translate-text-quickstart.mdx
new file mode 100644
index 00000000..706d31fc
--- /dev/null
+++ b/docs/translate/translate-text-quickstart.mdx
@@ -0,0 +1,261 @@
+---
+title: "Translate Text Quickstart"
+description: "Send your first text translation request to the DeepL API and batch multiple strings into a single call."
+covers: [Translate]
+public: true
+---
+
+In this tutorial, you'll translate your first text with the DeepL API, then batch several strings into a single request. By the end, you'll have made the two most common types of text translation request, using curl or the official client library for your language.
+
+## Prerequisites
+
+- A DeepL API account. Visit [our plans page](https://www.deepl.com/pro-api#api-pricing), choose a plan, and sign up. If you already have a DeepL Translator account, you need to log out and [create a separate account](https://support.deepl.com/hc/articles/360019358999-Change-plan) for the API.
+- Your API key, which you can find in [your account settings](https://www.deepl.com/your-account/keys). To learn more about keys, see [Authentication](/docs/getting-started/auth).
+- `curl`, or one of the [official client libraries](/docs/getting-started/client-libraries) for Python, JavaScript, PHP, C#, Java, or Ruby.
+
+
+If you're on a free API plan, replace `https://api.deepl.com` with `https://api-free.deepl.com` in curl examples. Client libraries detect your account type and pick the correct URL automatically.
+
+
+## Building with an AI coding agent?
+
+Wire it up to the [DeepL Docs MCP Server](/docs/getting-started/docs-mcp-server) so it can search and read this documentation while it writes code. In Claude Code:
+
+```bash
+claude mcp add --transport http deepl-docs https://developers.deepl.com/mcp
+```
+
+Then describe what you want to build. To get the same result as this tutorial, paste:
+
+```text wrap
+Using the DeepL API, write a script that translates a list of English strings to German and prints the results.
+```
+
+Setup instructions for Claude Desktop, Cursor, VS Code, and other MCP clients are on the [Docs MCP Server page](/docs/getting-started/docs-mcp-server).
+
+## Step 1: Send your first translation request
+
+A translation request needs only two parameters: `text`, the text to translate, and `target_lang`, the language you're translating to. You don't need to specify the source language. DeepL detects it and returns it in the response as `detected_source_language`. If your text is very short or mixes languages, you can pin the source with the optional `source_lang` parameter.
+
+Language codes follow ISO 639, like `DE` for German or `JA` for Japanese, and are case-insensitive. Some target languages support regional variants, like `en-US` or `pt-BR`. See the full list of [supported languages](/docs/getting-started/supported-languages).
+
+
+
+ ```sh Set the API key
+ export API_KEY={YOUR_API_KEY}
+ ```
+
+ ```sh Sample request
+ curl -X POST https://api.deepl.com/v2/translate \
+ --header "Content-Type: application/json" \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --data '{
+ "text": ["Your order has shipped and will arrive on Tuesday."],
+ "target_lang": "DE"
+ }'
+ ```
+
+ ```json Sample response
+ {
+ "translations": [
+ {
+ "detected_source_language": "EN",
+ "text": "Ihre Bestellung wurde versandt und kommt am Dienstag an."
+ }
+ ]
+ }
+ ```
+
+
+ ```sh Install client library
+ pip install deepl
+ ```
+
+ ```py Sample request
+ import deepl
+
+ auth_key = "{YOUR_API_KEY}" # replace with your key
+ deepl_client = deepl.DeepLClient(auth_key)
+
+ result = deepl_client.translate_text(
+ "Your order has shipped and will arrive on Tuesday.",
+ target_lang="DE",
+ )
+ print(result.text)
+ ```
+
+ ```text Sample output
+ Ihre Bestellung wurde versandt und kommt am Dienstag an.
+ ```
+
+
+ ```sh Install client library
+ npm install deepl-node
+ ```
+
+ ```javascript Sample request
+ import * as deepl from 'deepl-node';
+
+ const authKey = "{YOUR_API_KEY}"; // replace with your key
+ const deeplClient = new deepl.DeepLClient(authKey);
+
+ (async () => {
+ const result = await deeplClient.translateText(
+ 'Your order has shipped and will arrive on Tuesday.',
+ null,
+ 'de'
+ );
+ console.log(result.text);
+ })();
+ ```
+
+ ```text Sample output
+ Ihre Bestellung wurde versandt und kommt am Dienstag an.
+ ```
+
+
+ ```sh Install client library
+ composer require deeplcom/deepl-php
+ ```
+
+ ```php Sample request
+ require_once 'vendor/autoload.php';
+ use DeepL\Client;
+
+ $authKey = "{YOUR_API_KEY}"; // replace with your key
+ $deeplClient = new DeepL\DeepLClient($authKey);
+
+ $result = $deeplClient->translateText(
+ 'Your order has shipped and will arrive on Tuesday.',
+ null,
+ 'de'
+ );
+ echo $result->text;
+ ```
+
+ ```text Sample output
+ Ihre Bestellung wurde versandt und kommt am Dienstag an.
+ ```
+
+
+ ```sh Install client library
+ dotnet add package DeepL.net
+ ```
+
+ ```csharp Sample request
+ using DeepL; // this imports the DeepL namespace. Use the code below in your main program.
+
+ var authKey = "{YOUR_API_KEY}"; // replace with your key
+ var client = new DeepLClient(authKey);
+
+ var translatedText = await client.TranslateTextAsync(
+ "Your order has shipped and will arrive on Tuesday.",
+ null,
+ LanguageCode.German);
+ Console.WriteLine(translatedText);
+ ```
+
+ ```text Sample output
+ Ihre Bestellung wurde versandt und kommt am Dienstag an.
+ ```
+
+
+ ```java Install client library
+ // For instructions on installing the DeepL Java library,
+ // see https://github.com/DeepLcom/deepl-java?tab=readme-ov-file#installation
+ ```
+
+ ```java Sample request
+ import com.deepl.api.*;
+
+ public class Main {
+ public static void main(String[] args) throws DeepLException, InterruptedException {
+ String authKey = "{YOUR_API_KEY}"; // replace with your key
+ DeepLClient client = new DeepLClient(authKey);
+
+ TextResult result = client.translateText(
+ "Your order has shipped and will arrive on Tuesday.", null, "de");
+ System.out.println(result.getText());
+ }
+ }
+ ```
+
+ ```text Sample output
+ Ihre Bestellung wurde versandt und kommt am Dienstag an.
+ ```
+
+
+ ```sh Install client library
+ gem install deepl-rb
+ ```
+
+ ```ruby Sample request
+ require 'deepl'
+
+ DeepL.configure do |config|
+ config.auth_key = '{YOUR_API_KEY}' # replace with your key
+ end
+
+ translation = DeepL.translate 'Your order has shipped and will arrive on Tuesday.', nil, 'DE'
+ puts translation.text
+ ```
+
+ ```text Sample output
+ Ihre Bestellung wurde versandt und kommt am Dienstag an.
+ ```
+
+
+
+The examples hardcode the key to keep them short. In production code, store your API key in an environment variable instead.
+
+
+For security reasons, you can't call the DeepL API directly from client-side JavaScript. During testing or prototyping, route requests through [a simple proxy](/docs/learning-how-tos/cookbook/nodejs-proxy) instead.
+
+
+## Step 2: Translate multiple strings in one call
+
+The `text` parameter is an array, so one request can carry many strings, like every notification in a template file. Each string is translated separately and the response preserves their order. If you don't set `source_lang`, DeepL detects the language of each string individually.
+
+```sh Sample request
+curl -X POST https://api.deepl.com/v2/translate \
+ --header "Content-Type: application/json" \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --data '{
+ "text": [
+ "Your order has shipped.",
+ "Estimated delivery: Tuesday, July 14."
+ ],
+ "target_lang": "DE"
+}'
+```
+
+```json Sample response
+{
+ "translations": [
+ {
+ "detected_source_language": "EN",
+ "text": "Ihre Bestellung wurde versandt."
+ },
+ {
+ "detected_source_language": "EN",
+ "text": "Voraussichtliche Lieferung: Dienstag, 14. Juli."
+ }
+ ]
+}
+```
+
+The client libraries accept a list of strings in the same `translate_text` methods you used in step 1.
+
+The total request body is limited to 128 KiB. For anything larger, or for files whose formatting should be preserved, translate a document instead.
+
+## Next steps
+
+You've now covered the core text translation workflow: single strings and batches. To keep going:
+
+- Translate entire files, formatting included, with the [Translate Documents Quickstart](/docs/translate/translate-documents-quickstart)
+- Try requests with more parameters in [our playground](https://developers.deepl.com/api-reference/translate/request-translation?playground=open) or [Postman](/docs/getting-started/test-your-api-requests-with-postman)
+- Improve translation quality for short or ambiguous text with the [context parameter](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter)
+- Choose between speed- and quality-optimized models with the `model_type` parameter, documented in the [`/translate` reference](/api-reference/translate/request-translation)
+- Translate into regional variants like `pt-BR` with the [language variants guide](/docs/learning-how-tos/examples-and-guides/translating-between-variants)
+- Enforce your terminology with [glossaries](/docs/learning-how-tos/examples-and-guides/glossaries-in-the-real-world)
+- Check [usage and limits](/docs/resources/usage-limits) before going to production
diff --git a/docs/translate/translating-html.mdx b/docs/translate/translating-html.mdx
new file mode 100644
index 00000000..9993b381
--- /dev/null
+++ b/docs/translate/translating-html.mdx
@@ -0,0 +1,62 @@
+---
+title: "Translating HTML"
+description: "Learn how to translate HTML content with the DeepL API and exclude specific elements from translation."
+---
+
+To translate HTML content, set the `tag_handling` parameter to `html`. The API extracts the text from the HTML structure, translates it, and places the translation back into the structure. Without `tag_handling`, tags are treated as regular text.
+
+Set `tag_handling_version` to `v2` to use the improved tag handling algorithm. HTML input is never strictly parsed, so invalid HTML doesn't cause errors in either version. For version details and defaults, see the [`tag_handling_version` parameter](/api-reference/translate/request-translation).
+
+```bash Example request
+curl -X POST https://api.deepl.com/v2/translate \
+ --header "Content-Type: application/json" \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --data '{
+ "text": ["This is a premium feature.
"],
+ "target_lang": "DE",
+ "tag_handling": "html",
+ "tag_handling_version": "v2"
+}'
+```
+
+```json Example response
+{
+ "translations": [
+ {
+ "detected_source_language": "EN",
+ "text": "Dies ist eine Premium-Funktion.
",
+ "tag_handling_version": "v2"
+ }
+ ]
+}
+```
+
+You don't need to set `split_sentences` for HTML: with `tag_handling=html` it defaults to `nonewlines`, which splits sentences on punctuation only and gives the best translation quality for HTML. To also split sentences on newlines, set `split_sentences=1`.
+
+To translate non-HTML XML content, see [Translating XML](/docs/translate/translating-xml).
+
+## Exclude elements from translation
+
+To exclude an element from translation, add the `translate="no"` or `class="notranslate"` attribute to it. In the following example, `translate="no"` prevents translation of the paragraph:
+
+
+ ```markup Example request
+
+
+
+ My First Heading
+ My first paragraph.
+
+
+ ```
+
+ ```markup Example response
+
+
+
+ Meine erste Überschrift
+ My first paragraph.
+
+
+ ```
+
diff --git a/docs/translate/translating-large-volumes.mdx b/docs/translate/translating-large-volumes.mdx
new file mode 100644
index 00000000..850fecab
--- /dev/null
+++ b/docs/translate/translating-large-volumes.mdx
@@ -0,0 +1,100 @@
+---
+title: "Translating Large Volumes of Text"
+description: "Batch texts, control sentence splitting, and parallelize requests to translate high volumes efficiently with the text translation endpoint."
+covers: [Translate]
+public: true
+---
+
+The [`/v2/translate` endpoint](/api-reference/translate/request-translation) accepts up to 50 texts per request and request bodies up to 128 KiB. This guide shows how to make the most of each request when you have a lot of text to translate: sending whole paragraphs, batching texts, running requests in parallel, and protecting content that shouldn't be translated.
+
+## Send whole paragraphs as one text
+
+If your text is contiguous, submit entire paragraphs in a single `text` value. Before translating, the engine splits the text into sentences, normally on punctuation marks and newlines, and returns the whole translated paragraph. Don't assume every period acts as a sentence separator; the engine handles abbreviations and similar cases.
+
+```sh Example request
+curl -X POST https://api.deepl.com/v2/translate \
+ --header "Content-Type: application/json" \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --data '{
+ "text": ["The table is green. The chair is black."],
+ "target_lang": "DE"
+}'
+```
+
+```json Example response
+{
+ "translations": [
+ {
+ "detected_source_language": "EN",
+ "text": "Der Tisch ist grün. Der Stuhl ist schwarz."
+ }
+ ]
+}
+```
+
+## Control sentence splitting
+
+Automatic splitting can occasionally divide what is really a single sentence, especially in text with uncommon character sequences that contain punctuation. The `split_sentences` parameter controls this behavior:
+
+| Value | Behavior |
+| :---- | :---- |
+| `1` | Split on punctuation and newlines (default) |
+| `nonewlines` | Split on punctuation only (default when `tag_handling=html`) |
+| `0` | No splitting; the whole input is treated as one sentence |
+
+If your application already sends exactly one sentence per `text` value, set `split_sentences` to `0` to prevent unintended splits. With splitting disabled, overlong inputs are cut off rather than translated, so split long text into sentences yourself before submitting.
+
+Newlines split sentences under the default setting. If your text contains line breaks mid-sentence, either clean them up before sending or use `split_sentences=nonewlines`.
+
+## Batch up to 50 texts per request
+
+The `text` array can carry up to 50 entries per request. Translations come back in the same order:
+
+```sh Example request
+curl -X POST https://api.deepl.com/v2/translate \
+ --header "Content-Type: application/json" \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --data '{
+ "text": [
+ "This is the first sentence.",
+ "This is the second sentence.",
+ "This is the third sentence."
+ ],
+ "target_lang": "DE"
+}'
+```
+
+```json Example response
+{
+ "translations": [
+ {
+ "detected_source_language": "EN",
+ "text": "Das ist der erste Satz."
+ },
+ {
+ "detected_source_language": "EN",
+ "text": "Das ist der zweite Satz."
+ },
+ {
+ "detected_source_language": "EN",
+ "text": "Dies ist der dritte Satz."
+ }
+ ]
+}
+```
+
+
+Each text in the array is translated independently; texts don't share context with each other. If one text would help translate another, like a headline and its article body, combine them into one text or pass the shared information through the [`context` parameter](/docs/learning-how-tos/examples-and-guides/how-to-use-context-parameter), which applies to every text in the request.
+
+
+## Run requests in parallel
+
+For volumes beyond what batching covers, send multiple requests concurrently from several threads or processes. Watch for HTTP 429 responses and back off accordingly; see [error handling best practices](/docs/best-practices/error-handling) for retry strategies.
+
+## Protect embedded markers
+
+Uncommon character sequences that act as markers in your system, like placeholders or template syntax, might get translated or removed, corrupting your structure. Either split your text so markers don't need to be sent, or convert markers to XML tags and enable [XML handling](/docs/translate/translating-xml) or [HTML handling](/docs/translate/translating-html).
+
+## When to switch to document translation
+
+The total request body is limited to 128 KiB, and a `text` array is capped at 50 entries. For complete files, or text that exceeds these limits, use [document translation](/docs/translate/translate-documents-quickstart) instead: upload limits are far higher and formatting is preserved. See [usage and limits](/docs/resources/usage-limits) for the exact caps per plan.
diff --git a/docs/translate/translating-xml.mdx b/docs/translate/translating-xml.mdx
new file mode 100644
index 00000000..465b0910
--- /dev/null
+++ b/docs/translate/translating-xml.mdx
@@ -0,0 +1,226 @@
+---
+title: "Translating XML"
+description: "Learn how to translate XML content with the DeepL API while preserving its structure, and how to control sentence splitting."
+---
+
+To translate XML content, set the `tag_handling` parameter to `xml`. The API extracts the text from the XML structure, translates it, and places the translation back into the structure. Without `tag_handling`, tags are treated as regular text.
+
+Set `tag_handling_version` to `v2` to use the improved tag handling algorithm. For version details and defaults, see the [`tag_handling_version` parameter](/api-reference/translate/request-translation).
+
+```bash Example request
+curl -X POST https://api.deepl.com/v2/translate \
+ --header "Content-Type: application/json" \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --data '{
+ "text": ["Press Continue to advance."],
+ "target_lang": "DE",
+ "tag_handling": "xml",
+ "tag_handling_version": "v2"
+}'
+```
+
+```json Example response
+{
+ "translations": [
+ {
+ "detected_source_language": "EN",
+ "text": "Drücken Sie „Weiter\", um fortzufahren.",
+ "tag_handling_version": "v2"
+ }
+ ]
+}
+```
+
+
+ Accounts that first used tag handling after December 1, 2025 default to v2. All other accounts default to v1 and need to set `tag_handling_version=v2` explicitly. Results differ between versions, so test representative content before switching versions in production.
+
+
+
+ With v2, XML input is strictly parsed: invalid XML (for example, an unclosed tag) returns the error `Tag handling parsing failed, please check input.` Make sure your XML is well-formed and handle this error in your integration.
+
+
+To translate HTML content, see [Translating HTML](/docs/translate/translating-html).
+
+## Translate sentences with inline markup
+
+Send marked-up text as is; tags stay attached to the words they wrap, and placeholder tags are placed next to the translation of the words that precede or follow them:
+
+
+
+ ```markup Request
+ Press Continue to advance to the next page.
+ ```
+
+ ```markup Response
+ Drücken Sie Weiter, um zur nächsten Seite zu gelangen.
+ ```
+
+
+ ```markup Request
+ Please welcome the participants to today's meeting.
+ ```
+
+ ```markup Response
+ Bitte begrüßen Sie die Teilnehmer des heutigen Treffens.
+ ```
+
+
+ ```markup Request
+ The firm said it had been conducting an internal investigation for several months.
+ ```
+
+ ```markup Response
+ Das Unternehmen sagte, dass es seit mehreren Monaten eine interne Untersuchungdurchgeführt habe.
+ ```
+
+
+ ```markup Request
+ Artificial intelligence is already shaping our everyday lives.
+ ```
+
+ ```markup Response
+ Künstliche Intelligenz prägt bereits heute unseren Alltag.
+ ```
+
+
+
+## Exclude content from translation
+
+List tags whose content should not be translated in the `ignore_tags` parameter. The example below uses `ignore_tags=x` to preserve the text between `` and `` as is:
+
+
+ ```text Parameters
+ tag_handling=xml, ignore_tags=x
+ ```
+
+ ```markup Request
+ Please open the page Settings to configure your system.
+ ```
+
+ ```markup Response
+ Bitte öffnen Sie die Seite Settings um Ihr System zu konfigurieren.
+ ```
+
+
+## Translate whole XML documents
+
+Send complete XML files the same way, with `split_sentences=nonewlines` so that line breaks in the file don't split sentences. Tags that contain text (here `title` and `par`) are treated as sentence boundaries, and the content of each is translated separately:
+
+
+ ```text Parameters
+ tag_handling=xml, split_sentences=nonewlines
+ ```
+
+ ```markup Example request
+
+
+ A document's title
+
+
+ This is the first sentence. Followed by a second one.
+ This is the third sentence.
+
+
+ ```
+
+ ```markup Example response
+
+
+ Der Titel eines Dokuments
+
+
+ Das ist der erste Satz. Gefolgt von einem zweiten.
+ Dies ist der dritte Satz.
+
+
+ ```
+
+
+Without `split_sentences=nonewlines`, a newline in the middle of a sentence causes each part to be translated separately, producing wrong results:
+
+
+ ```markup Request
+ She bought oat
+ biscuits.
+ ```
+
+ ```markup Response
+ Sie kaufte Hafer
+ Kekse.
+ ```
+
+ The two parts of the sentence have been translated separately: "oat biscuits" became "Hafer Kekse" instead of "Haferkekse".
+
+
+## Keep sentences together across tags
+
+When a single sentence is spread across multiple text-bearing tags, list those tags in the `non_splitting_tags` parameter so the sentence is translated as a whole:
+
+
+
+ ```text Parameters
+ tag_handling=xml, non_splitting_tags=par
+ ```
+
+ ```markup Request
+ The firm said it had been conducting an internal investigation.
+ ```
+
+ ```markup Response
+ Die Firma sagte, dass sie eine interne Untersuchung durchgeführt habe.
+ ```
+
+ The sentence is translated as a whole and the `par` tags are treated as markup. Because the translation of "had been" moved to another position in the German sentence, the tags are duplicated (which is expected here).
+
+
+ ```text Parameters
+ tag_handling=xml
+ ```
+
+ ```markup Request
+ The firm said it had been conducting an internal investigation.
+ ```
+
+ ```markup Response
+ Die Firma sagte, es sei eine gute Idee gewesen. Durchführung einer internen Untersuchung.
+ ```
+
+ Each `par` element is translated separately, producing an incorrect translation.
+
+
+
+## Control sentence splitting manually
+
+If automatic detection of the XML structure doesn't yield good results for your files, turn it off with `outline_detection=0` and list your structure tags in the `splitting_tags` parameter. The example below reproduces the automatic behavior for the document shown earlier:
+
+
+ ```text Parameters
+ tag_handling=xml, split_sentences=nonewlines, outline_detection=0, splitting_tags=par,title
+ ```
+
+ ```markup Example request
+
+
+ A document's title
+
+
+ This is the first sentence. Followed by a second one.
+ This is the third sentence.
+
+
+ ```
+
+ ```markup Example response
+
+
+ Der Titel eines Dokuments
+
+
+ Das ist der erste Satz. Gefolgt von einem zweiten.
+ Dies ist der dritte Satz.
+
+
+ ```
+
+
+This approach takes more setup but gives you full control over how the translation output is structured.
diff --git a/docs/translate/understanding-model-types.mdx b/docs/translate/understanding-model-types.mdx
new file mode 100644
index 00000000..9114ac57
--- /dev/null
+++ b/docs/translate/understanding-model-types.mdx
@@ -0,0 +1,55 @@
+---
+title: "Understanding Model Types"
+description: "How the model_type parameter chooses between latency-optimized and quality-optimized translation models, and how DeepL selects the model for each request."
+public: true
+---
+
+DeepL hosts many AI models for translation and deploys new ones continuously. Rather than asking you to pick a specific model, and update your integration every time models change, the `model_type` parameter of the [`/v2/translate` endpoint](/api-reference/translate/request-translation) lets you state your goal: the lowest possible latency or the highest possible translation quality. DeepL then chooses the most suitable model for your language pair and request.
+
+## Parameter values
+
+The `model_type` parameter accepts three values:
+
+| Value | Behavior |
+| :---- | :---- |
+| `latency_optimized` | Aims to serve the request as fast as possible (default when `model_type` is omitted) |
+| `quality_optimized` | Aims for the highest translation quality |
+| `prefer_quality_optimized` | Legacy value, currently identical to `quality_optimized` |
+
+All features and language pairs are compatible with all `model_type` values. As of December 2025, all source and target languages are supported by next-gen models.
+
+When you set `model_type`, the response includes a `model_type_used` field indicating which kind of model served the request:
+
+```sh Example request
+curl -X POST https://api.deepl.com/v2/translate \
+ --header "Content-Type: application/json" \
+ --header "Authorization: DeepL-Auth-Key $API_KEY" \
+ --data '{
+ "text": ["Your order has shipped and will arrive on Tuesday."],
+ "target_lang": "DE",
+ "model_type": "quality_optimized"
+}'
+```
+
+```json Example response
+{
+ "translations": [
+ {
+ "detected_source_language": "EN",
+ "text": "Ihre Bestellung wurde versandt und kommt am Dienstag an.",
+ "model_type_used": "quality_optimized"
+ }
+ ]
+}
+```
+
+## How DeepL selects the model
+
+The parameter expresses a goal, not a model name. DeepL fulfills it on a best-effort basis: for some language pairs and requests, only one model can be used, and not every pair behaves differently between the two values. DeepL may also change which model serves a given `model_type` when the change is a net benefit, for example a quality increase with no significant latency cost, or a large latency reduction with at most a very slight quality trade-off.
+
+This means you never need to update your code for new model releases or track model names: the API keeps choosing the best available model for your stated goal.
+
+## Notes
+
+- `model_type` applies to text translation only. The [`/v2/document` endpoint](/api-reference/document/upload-and-translate-a-document) accepts the parameter without error but ignores it.
+- The [`/v3/languages` endpoint](/api-reference/languages/retrieve-supported-languages-by-resource) doesn't yet report `model_type` support per language. This information will be added in a future update.
diff --git a/docs/voice/message-encoding.mdx b/docs/voice/message-encoding.mdx
new file mode 100644
index 00000000..e9d50bd3
--- /dev/null
+++ b/docs/voice/message-encoding.mdx
@@ -0,0 +1,58 @@
+---
+title: "Message Encoding"
+description: "Choose between JSON and MessagePack encoding for DeepL Voice API WebSocket messages, and avoid the frame type and map encoding pitfalls."
+---
+
+WebSocket messages in a Voice API session can be encoded in two formats, chosen with the `message_format` option when you [request the session](/api-reference/voice/request-session). Start with JSON for the best developer experience, and switch to MessagePack if you need better performance.
+
+| **Format** | **Frame type** | **Binary data** | **Trade-off** |
+| :--------- | :------------- | :-------------- | :------------ |
+| JSON (default) | TEXT | base64-encoded strings | Human-readable, easy to debug |
+| [MessagePack](https://msgpack.org/) | BINARY | raw binary | Roughly 25-30% less bandwidth, 2x-4x faster encoding/decoding |
+
+
+ Send JSON messages as TEXT frames and MessagePack messages as BINARY frames. Sending the wrong frame type results in connection errors.
+
+
+MessagePack messages must be encoded as maps with string keys, not as arrays. The structure must match the JSON schema exactly, with all field names preserved (for example, `{"source_media_chunk": {"data": }}`). Some MessagePack libraries default to array encoding for performance, so check your library's configuration.
+
+The following example sends the same audio chunk in both encodings:
+
+
+
+```javascript JSON
+// Raw binary audio data
+const audioData = getAudioChunk();
+
+// Base64 encode the audio data
+const base64Audio = btoa(audioData);
+
+const message = {
+ source_media_chunk: {
+ data: base64Audio
+ }
+};
+
+// Send as TEXT frame
+websocket.send(JSON.stringify(message));
+```
+
+```javascript MessagePack
+import { pack } from 'msgpackr';
+
+// Raw binary audio data
+const audioData = getAudioChunk();
+
+const message = {
+ source_media_chunk: {
+ data: audioData // No base64 encoding needed
+ }
+};
+
+// Send as BINARY frame
+websocket.send(pack(message));
+```
+
+
+
+For the full list of message types exchanged during a session, see the [WebSocket Streaming reference](/api-reference/voice/websocket-streaming). For how those messages fit into the session lifecycle, see [Understanding Voice Sessions](/docs/voice/understanding-voice-sessions).
diff --git a/docs/voice/overview.mdx b/docs/voice/overview.mdx
new file mode 100644
index 00000000..161edaba
--- /dev/null
+++ b/docs/voice/overview.mdx
@@ -0,0 +1,49 @@
+---
+title: "DeepL Voice API"
+sidebarTitle: "Overview"
+description: "Transcribe and translate spoken audio in real time with the DeepL Voice API. Find the streaming guide, core concepts, and language and format reference."
+---
+
+The DeepL Voice API transcribes and translates spoken audio in real time over a WebSocket connection. Within a single streaming session, you can:
+
+* Send one audio stream
+* Receive transcripts in the source language
+* Receive translations in multiple target languages
+* closed beta Receive translated speech
+
+
+ **Speech-to-text** (real-time transcription and text translation) is available to all customers with a paid DeepL API subscription. **Speech-to-speech** (translated TTS output) is a separate capability in closed beta and not included in standard API subscriptions.
+
+ The provisions applying to DeepL API Enterprise subscriptions also apply to Voice API speech-to-text, with [additions to the Terms and Conditions, Service Specification, and Data Processing Agreement](/api-reference/voice/deepl-voice-api-service-specification-updates) (new sub-processors have been added to serve specific languages).
+
+
+## Start here
+
+
+
+ Create a session, stream audio over WebSocket, and handle reconnections, with a complete Python example.
+
+
+ Understand the session flow, token lifecycle, and how audio and results are delivered.
+
+
+ Choose between JSON and MessagePack for WebSocket messages.
+
+
+ Check language availability, supported audio codecs and containers, and session limits.
+
+
+ Full request, message, and response schemas for the Voice API endpoints.
+
+
+
+## Customization
+
+Two optional features let you tailor transcription and translation to your domain:
+
+* beta **Spoken terms**: improve transcription of frequently used terms such as company-specific terminology, acronyms, product names, and team member names. Manage them in [DeepL Home](https://www.deepl.com/en/voice/spoken-terms); management via API is coming soon.
+* **Glossaries**: enforce specific translations for terms in the target language. Manage them in [DeepL Home](https://www.deepl.com/en/glossary) or programmatically with the [Glossaries API](/api-reference/multilingual-glossaries).
+
+## Code examples
+
+A reference implementation in Python is available in the [DeepL Python library repository](https://github.com/DeepLcom/deepl-python/tree/main/examples/voice/cli). The official DeepL SDKs don't integrate the Voice API yet, but you can use any WebSocket client library to interact with it.
diff --git a/docs/voice/real-time-voice-quickstart.mdx b/docs/voice/real-time-voice-quickstart.mdx
new file mode 100644
index 00000000..53ccbacd
--- /dev/null
+++ b/docs/voice/real-time-voice-quickstart.mdx
@@ -0,0 +1,259 @@
+---
+title: "Real-Time Voice Quickstart"
+description: "Stream microphone audio to the DeepL Voice API from Python and print live translations to your terminal as the speaker talks."
+covers: [Voice]
+---
+
+In this tutorial you'll run a small Python program that captures audio from your microphone, streams it to the DeepL Voice API, and prints the transcript plus German and French translations to your terminal, sentence by sentence, while you speak. The same pattern works for any live audio source: a meeting bot, a phone bridge, or a broadcast feed.
+
+## Prerequisites
+
+- A DeepL API account with Voice API access
+- Python 3.10 or later
+- A microphone (no microphone? see [Simulate a live stream from a file](#simulate-a-live-stream-from-a-file))
+
+## Building with an AI coding agent?
+
+Wire it up to the [DeepL Docs MCP Server](/docs/getting-started/docs-mcp-server) so it can search and read this documentation while it writes code. In Claude Code:
+
+```bash
+claude mcp add --transport http deepl-docs https://developers.deepl.com/mcp
+```
+
+Then describe what you want to build. To get the same result as this tutorial, paste:
+
+```text wrap
+Write a script to stream my microphone to the DeepL Voice API and print the transcript and translations as each sentence concludes.
+```
+
+Setup instructions for Claude Desktop, Cursor, VS Code, and other MCP clients are on the [Docs MCP Server page](/docs/getting-started/docs-mcp-server).
+
+## Run the complete example
+
+Install the dependencies:
+
+```bash
+pip install requests sounddevice websockets
+```
+
+Then save this as `live_translation.py` and replace `YOUR_AUTH_KEY` with your DeepL API key:
+
+```python live_translation.py [expandable]
+import asyncio
+import base64
+import json
+import signal
+
+import requests
+import sounddevice
+import websockets
+
+AUTH_KEY = "YOUR_AUTH_KEY"
+SESSION_ENDPOINT = "https://api.deepl.com/v3/voice/realtime"
+TARGET_LANGUAGES = ["de", "fr"]
+SAMPLE_RATE = 16000 # Must match the rate declared in source_media_content_type
+CHUNK_FRAMES = 3200 # 200 ms per chunk at 16 kHz
+RECORD_SECONDS = 30 # Safety cap; Ctrl+C stops recording earlier
+
+
+def create_session() -> dict:
+ response = requests.post(
+ SESSION_ENDPOINT,
+ headers={"Authorization": f"DeepL-Auth-Key {AUTH_KEY}"},
+ json={
+ "source_media_content_type": "audio/pcm;encoding=s16le;rate=16000",
+ "target_languages": TARGET_LANGUAGES,
+ },
+ )
+ response.raise_for_status()
+ return response.json()
+
+
+async def send_microphone_audio(ws, stop: asyncio.Event) -> None:
+ stream = sounddevice.RawInputStream(
+ samplerate=SAMPLE_RATE, channels=1, dtype="int16"
+ )
+ stream.start()
+ try:
+ for _ in range(RECORD_SECONDS * SAMPLE_RATE // CHUNK_FRAMES):
+ if stop.is_set():
+ break
+ # Read in a worker thread so receiving continues while we block
+ data, _overflowed = await asyncio.to_thread(stream.read, CHUNK_FRAMES)
+ encoded = base64.b64encode(bytes(data)).decode("ascii")
+ await ws.send(json.dumps({"source_media_chunk": {"data": encoded}}))
+ finally:
+ stream.stop()
+ stream.close()
+ print("Finalizing transcripts...")
+ await ws.send(json.dumps({"end_of_source_media": {}}))
+
+
+async def receive_results(ws) -> None:
+ pending = {} # Concluded text per language, buffered until a sentence ends
+
+ def handle_update(label: str, segments: list) -> None:
+ text = pending.get(label, "") + "".join(s["text"] for s in segments)
+ if text.rstrip().endswith((".", "!", "?")):
+ print(f"[{label}] {text.strip()}")
+ text = ""
+ pending[label] = text
+
+ async for message in ws:
+ data = json.loads(message)
+ if "source_transcript_update" in data:
+ handle_update("source", data["source_transcript_update"]["concluded"])
+ elif "target_transcript_update" in data:
+ update = data["target_transcript_update"]
+ handle_update(update["language"], update["concluded"])
+ elif "end_of_stream" in data:
+ # The very last message: flush any unfinished sentences and exit
+ for label, text in pending.items():
+ if text.strip():
+ print(f"[{label}] {text.strip()}")
+ return
+ elif "error" in data:
+ raise RuntimeError(f"Voice API error: {data['error']['error_message']}")
+
+
+async def main() -> None:
+ stop = asyncio.Event()
+ try:
+ asyncio.get_running_loop().add_signal_handler(signal.SIGINT, stop.set)
+ except NotImplementedError:
+ pass # Windows: Ctrl+C raises KeyboardInterrupt instead
+
+ session = create_session()
+ url = f"{session['streaming_url']}?token={session['token']}"
+ async with websockets.connect(url) as ws:
+ print("Connected. Speak now (Ctrl+C to stop)...")
+ await asyncio.gather(send_microphone_audio(ws, stop), receive_results(ws))
+ print("Done. All transcripts are final.")
+
+
+if __name__ == "__main__":
+ try:
+ asyncio.run(main())
+ except KeyboardInterrupt:
+ pass
+```
+
+Run it and speak in any [supported source language](/docs/voice/supported-languages-formats-and-limits#supported-languages). Each sentence prints once it's final, first the transcript, then each translation. Press Ctrl+C when you're done: the script stops recording, waits for the remaining results, and exits cleanly.
+
+```text
+❯ python live_translation.py
+Connected. Speak now (Ctrl+C to stop)...
+[source] Hello everyone, welcome to today's demo.
+[de] Hallo zusammen, willkommen zur heutigen Demo.
+[fr] Bonjour à tous, bienvenue à la démonstration d'aujourd'hui.
+^CFinalizing transcripts...
+[source] We are testing real-time voice translation.
+[de] Wir testen die Sprachübersetzung in Echtzeit.
+[fr] Nous testons la traduction vocale en temps réel.
+Done. All transcripts are final.
+```
+
+## How it works
+
+The program does three things: it creates a session over HTTPS, streams audio to the WebSocket URL it gets back, and handles result messages until the server confirms everything is final.
+
+### The session request
+
+`create_session` sends a POST request with the audio format and target languages. The only required field is `source_media_content_type`; for raw microphone audio, that's PCM at 16 kHz. The response contains the WebSocket URL and a one-time token, and the program connects to `{streaming_url}?token={token}`:
+
+```json
+{
+ "session_id": "4f911080-cfe2-41d4-8269-0e6ec15a0354",
+ "streaming_url": "wss://api.deepl.com/v3/voice/realtime/connect",
+ "token": "VGhpcyBpcyBhIGZha2UgdG9rZW4K"
+}
+```
+
+If you know the speaker's language in advance, add `"source_language": "en"` and `"source_language_mode": "fixed"` to the request body. This skips language detection and reduces latency. Without them, the language is detected automatically. See the [Request Session reference](/api-reference/voice/request-session) for all parameters, including glossary and formality options.
+
+### Sending audio
+
+`send_microphone_audio` sends each 200-millisecond microphone chunk as a JSON text message with the raw audio base64-encoded:
+
+```json
+{"source_media_chunk": {"data": ""}}
+```
+
+Keep chunks between 50 and 250 milliseconds for the best latency. When the audio ends (Ctrl+C or the safety cap), the function sends one final message that tells the API to finalize all pending results:
+
+```json
+{"end_of_source_media": {}}
+```
+
+### Receiving transcripts and translations
+
+While audio is being sent, the server pushes `source_transcript_update` and `target_transcript_update` messages on the same connection:
+
+```json
+{
+ "target_transcript_update": {
+ "language": "de",
+ "concluded": [
+ {"text": " Hallo zusammen,", "start_time": 0, "end_time": 1500}
+ ],
+ "tentative": [
+ {"text": " willkommen zur heutigen Demo", "start_time": 1500, "end_time": 2000}
+ ]
+ }
+}
+```
+
+**Concluded** segments are final and sent only once; **tentative** segments are provisional and refined by later updates. `receive_results` appends concluded text to a per-language buffer and prints the buffer whenever a sentence completes, which keeps the terminal readable. A UI would also render the tentative text as a live preview that updates in place; see [Understanding Voice Sessions](/docs/voice/understanding-voice-sessions) for this delivery model.
+
+After `end_of_source_media`, the server sends the remaining updates, then `end_of_stream` as the very last message, at which point it's safe to close the connection. See the [WebSocket Streaming reference](/api-reference/voice/websocket-streaming) for the full message schema.
+
+### Reconnecting after a drop
+
+Networks drop, and the Voice API lets you resume a session instead of starting over. If the WebSocket closes unexpectedly, exchange your token for a fresh streaming URL and token, then reconnect. Session state, including configuration and translation context, is preserved.
+
+```python
+def reconnect(token: str) -> dict:
+ response = requests.get(
+ SESSION_ENDPOINT,
+ headers={"Authorization": f"DeepL-Auth-Key {AUTH_KEY}"},
+ params={"token": token},
+ )
+ response.raise_for_status()
+ return response.json()
+```
+
+The response has the same shape as the session response above. Always pass the token from your most recent session or reconnection response: each token is single-use, and presenting an outdated one invalidates the session (a 400-level error). In that case, create a new session with `create_session()`.
+
+To add this to the example, wrap the `websockets.connect` block in a `try`/`except websockets.exceptions.ConnectionClosed` loop that calls `reconnect()` and connects again with the new URL and token.
+
+## Simulate a live stream from a file
+
+If you don't have a microphone, or you want reproducible input while developing, stream a pre-recorded file at real-time pace instead. Set `"source_media_content_type": "audio/auto"` in the session request so the format is detected, and swap `send_microphone_audio` for a reader that paces itself:
+
+```python
+async def send_file_audio(ws, path: str, stop: asyncio.Event) -> None:
+ with open(path, "rb") as audio_file:
+ while chunk := audio_file.read(6400):
+ if stop.is_set():
+ break
+ encoded = base64.b64encode(chunk).decode("ascii")
+ await ws.send(json.dumps({"source_media_chunk": {"data": encoded}}))
+ # Pace the upload to simulate live audio
+ await asyncio.sleep(0.2)
+ print("Finalizing transcripts...")
+ await ws.send(json.dumps({"end_of_source_media": {}}))
+```
+
+Any recording of speech in a [supported format](/docs/voice/supported-languages-formats-and-limits#supported-audio-formats) works, for example an MP3 of a podcast episode.
+
+
+ Don't send audio faster than 2x real-time. Uploading a file as fast as the network allows triggers rate limits and terminates the session.
+
+
+## Next steps
+
+- See the [WebSocket Streaming reference](/api-reference/voice/websocket-streaming) for the complete message schema and all event types.
+- To understand the session flow and token lifecycle in depth, see [Understanding Voice Sessions](/docs/voice/understanding-voice-sessions).
+- To reduce bandwidth with MessagePack instead of JSON, see [Message Encoding](/docs/voice/message-encoding).
+- For a fuller command-line version of this program, including glossary and formality options, see the [DeepL Voice CLI example](https://github.com/DeepLcom/deepl-python/tree/main/examples/voice/cli).
+- To apply a custom glossary to your translations, see the [Glossaries API](/api-reference/multilingual-glossaries).
diff --git a/docs/voice/supported-languages-formats-and-limits.mdx b/docs/voice/supported-languages-formats-and-limits.mdx
new file mode 100644
index 00000000..65a855f0
--- /dev/null
+++ b/docs/voice/supported-languages-formats-and-limits.mdx
@@ -0,0 +1,90 @@
+---
+title: "Supported Languages, Formats, and Limits"
+description: "Reference for DeepL Voice API language availability, supported audio codecs and containers, and session limits."
+---
+
+## Supported languages
+
+Translation is always provided by DeepL. For some languages, transcription and translated speech are provided by external service partners. All source languages can be translated into any target language.
+
+
+| **Language** | **Transcription** | **Translation** | closed beta
Translated Speech |
+| :------------------------------------- | :---------------: | :-------------: | :------------------------------------------------------------: |
+| Arabic | ⎋ | ✓ | ⎋ |
+| Bengali | ⎋ | ✓ | — |
+| Bulgarian | ⎋ | ✓ | ⎋ |
+| Chinese (Simplified/Traditional) | ✓ | ✓ | ✓ |
+| Croatian | ⎋ | ✓ | — |
+| Czech | ✓ | ✓ | ⎋ |
+| Danish | ⎋ | ✓ | ⎋ |
+| Dutch | ✓ | ✓ | ✓ |
+| English (American/British) | ✓ | ✓ | ✓ |
+| Estonian | ⎋ | ✓ | — |
+| Finnish | ⎋ | ✓ | ⎋ |
+| French | ✓ | ✓ | ✓ |
+| German | ✓ | ✓ | ✓ |
+| Greek | ⎋ | ✓ | ⎋ |
+| Hebrew | ⎋ | ✓ | — |
+| Hindi beta | ⎋ | ✓ | ⎋ |
+| Hungarian | ⎋ | ✓ | ⎋ |
+| Indonesian | ✓ | ✓ | ⎋ |
+| Irish | ⎋ | ✓ | — |
+| Italian | ✓ | ✓ | ✓ |
+| Japanese | ✓ | ✓ | ✓ |
+| Korean | ✓ | ✓ | ✓ |
+| Latvian | ⎋ | ✓ | — |
+| Lithuanian | ⎋ | ✓ | — |
+| Malay beta | ⎋ | ✓ | ⎋ |
+| Maltese | ⎋ | ✓ | — |
+| Norwegian Bokmål | ⎋ | ✓ | ⎋ |
+| Polish | ✓ | ✓ | ✓ |
+| Portuguese (Brazil/Portugal) | ✓ | ✓ | ✓ |
+| Romanian | ✓ | ✓ | ⎋ |
+| Russian | ✓ | ✓ | ✓ |
+| Slovak | ⎋ | ✓ | ⎋ |
+| Slovenian | ⎋ | ✓ | — |
+| Spanish | ✓ | ✓ | ✓ |
+| Swedish | ✓ | ✓ | ✓ |
+| Thai | ⎋ | ✓ | — |
+| Tagalog | ⎋ | ✓ | — |
+| Tamil beta | ⎋ | ✓ | ⎋ |
+| Turkish | ✓ | ✓ | ✓ |
+| Ukrainian | ✓ | ✓ | ⎋ |
+| Vietnamese | ⎋ | ✓ | ⎋ |
+
+✓ provided by DeepL / ⎋ provided by an external service partner / — not available
+
+
+
+ Transcription provided by external service partners (marked with ⎋) cannot yet auto-detect the source language,
+ which you must therefore specify explicitly.
+
+
+To retrieve supported languages and feature availability programmatically, call [`GET /v3/languages?resource=voice`](/api-reference/languages/retrieve-supported-languages-by-resource) and check for the `transcription` and `translated_speech` feature keys. The `external` flag on these features indicates if they are provided by an external service partner.
+
+## Supported audio formats
+
+The API supports common combinations of streaming codecs and containers with a single-channel (mono) audio stream.
+
+| **Audio Codec** | **Audio Container** | **Recommended Bitrate** |
+| :--------------------------- | :---------------------------------- | :--------------------------------------------------- |
+| **PCM** | **-** | **256 kbps (16kHz), default recommendation** |
+| **OPUS** | **Matroska / MPEG-TS / Ogg / WebM** | **32 kbps, recommended for low bandwidth scenarios** |
+| AAC | Matroska / MPEG-TS | 96 kbps |
+| FLAC | FLAC / Matroska / Ogg | 256 kbps (16kHz) |
+| MP3 | MPEG / Matroska | 128 kbps |
+
+For the detailed list of supported input audio formats, see [Source Media Content Type](/api-reference/voice/request-session#body-source-media-content-type). For supported output audio formats, see [Target Media Content Type](/api-reference/voice/request-session#body-target-media-content-type).
+
+## Session limits
+
+* Maximum 5 translation targets per session (including translated speech targets)
+* Maximum 1 translated speech target per session
+* Audio chunk size: should not exceed 100 kilobytes or 1 second duration
+* Recommended chunk duration: 50-250 milliseconds for low latency
+* Audio stream speed: maximum 2x real-time
+* Timeout: if no data is received for 30 seconds, the session is terminated
+* Maximum connection duration: after 1 hour, the connection is closed. Establish a new connection by [reconnecting](/api-reference/voice/reconnect-session) to the session
+* Using any given token more than once to establish a WebSocket connection terminates the associated session immediately for security reasons
+
+If you need more translation targets or translated speech targets than these limits allow, open multiple concurrent sessions over the same source audio.
diff --git a/docs/voice/translate-an-audio-file.mdx b/docs/voice/translate-an-audio-file.mdx
new file mode 100644
index 00000000..0675a6a5
--- /dev/null
+++ b/docs/voice/translate-an-audio-file.mdx
@@ -0,0 +1,149 @@
+---
+title: "Translate an Audio File"
+description: "Submit a pre-recorded audio file for translation and download the results using the async Voice Translate Job API."
+covers: [Translate Audio Files]
+---
+
+
+ **Closed alpha.** This API may change without notice and is only available to select DeepL customers. See [alpha and beta features](/docs/resources/alpha-and-beta-features) for details. To request access, contact your customer success manager.
+
+
+The Voice Translate Job API translates pre-recorded audio files asynchronously. Because translation happens in the background, the workflow has three distinct phases: create a job and upload your file, poll until results are ready, then download them. This guide walks you through each phase with a concrete example.
+
+For a live audio stream, use the [real-time Voice API](/docs/voice/overview) instead.
+
+## Prerequisites
+
+- A DeepL API Pro account with access to the closed-alpha Voice Translate Job API
+- Your API authentication key
+- A pre-recorded audio file (see the [Reference](/api-reference/jobs-voice-translate/reference#supported-source-audio-formats) for supported formats and limits)
+
+## Step 1: Create a job
+
+Send a `POST /v1/jobs/voice/translate` request describing your source file and the outputs you want. The response returns a pre-signed `upload_url` for the source audio.
+
+This example translates an English podcast episode into German plain text and Spanish PCM audio:
+
+```bash
+curl -X POST https://api.deepl.com/v1/jobs/voice/translate \
+ -H "Authorization: DeepL-Auth-Key YOUR_AUTH_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" }
+ ]
+ }'
+```
+
+`content_length` must be the exact byte size of the file you will upload. The API uses this value to size the upload slot.
+
+Example response:
+
+```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"
+}
+```
+
+Save the `job_id` — you need it to check status and download results.
+
+## Step 2: Upload your audio file
+
+PUT the file directly to the `upload_url` from the previous response. Set `Content-Type` to match the value you declared in the create request.
+
+```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
+```
+
+You have 5 minutes to upload the file after creating the job. If the upload window expires, the job is abandoned and you must create a new one.
+
+
+ The upload URL is pre-signed and does not require your DeepL API key. Do not include an `Authorization` header in this request.
+
+
+## Step 3: Poll for results
+
+Poll `GET /v1/jobs/voice/translate/{job_id}` until each target's status is `complete` or `failed`. Targets are processed independently, so some may finish before others.
+
+```bash
+curl https://api.deepl.com/v1/jobs/voice/translate/a74d88fb-ed2a-4943-a664-a4512398b994 \
+ -H "Authorization: DeepL-Auth-Key YOUR_AUTH_KEY"
+```
+
+While processing, the response looks like this:
+
+```json
+{
+ "job_id": "a74d88fb-ed2a-4943-a664-a4512398b994",
+ "operation": "translate",
+ "product": "voice",
+ "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" }
+ ],
+ "results": [
+ { "status": "processing" },
+ { "status": "processing" }
+ ],
+ "created_at": "2026-10-01T01:03:03.444Z",
+ "updated_at": "2026-10-01T04:03:03.333Z"
+}
+```
+
+When at least one target completes, its result entry includes a `download_url`:
+
+```json
+{
+ "results": [
+ {
+ "status": "complete",
+ "download_url": "https://assets.deepl.com/collections/a74d88fb/assets/c3d4e5f6",
+ "signature": "eyJhbGciOiJIUzI1NiIs..."
+ },
+ {
+ "status": "failed",
+ "error": { "message": "processing failed" }
+ }
+ ]
+}
+```
+
+Results appear in the same order as the `targets` array in your create request. A `failed` result does not affect other targets — download any `complete` results regardless.
+
+Poll at a reasonable interval (every 10-30 seconds for short files, every 60 seconds for longer ones). Avoid polling faster than once every 5 seconds.
+
+## Step 4: Download results
+
+GET each `download_url` to retrieve the translated output. No authentication header is required.
+
+```bash
+curl -o translation-de.txt \
+ "https://assets.deepl.com/collections/a74d88fb/assets/c3d4e5f6"
+```
+
+Download results within 1 hour of upload. After all targets are downloaded (or the window expires), the job is deleted and the `job_id` returns `404`. Usage is billed based on the duration of the source audio.
+
+## Next steps
+
+- Check the [Reference](/api-reference/jobs-voice-translate/reference) for the full list of supported output formats, source audio formats, file size limits, and concurrent job limits
+- For the full request and response schemas, see the [Create Job](/api-reference/jobs-voice-translate/create-voice-translate-job) and [Get Job Status](/api-reference/jobs-voice-translate/get-voice-translate-job-status) endpoint references
+- To translate live audio instead of pre-recorded files, see the [real-time Voice API](/docs/voice/overview)
\ No newline at end of file
diff --git a/docs/voice/understanding-voice-sessions.mdx b/docs/voice/understanding-voice-sessions.mdx
new file mode 100644
index 00000000..f994ba45
--- /dev/null
+++ b/docs/voice/understanding-voice-sessions.mdx
@@ -0,0 +1,121 @@
+---
+title: "Understanding Voice Sessions"
+description: "Understand the lifecycle of a DeepL Voice API session: how connections are established, how tokens secure reconnection, and how audio and results flow."
+---
+
+This page explains the lifecycle of a Voice API session: how a connection is established, how tokens keep it secure and resumable, and how audio and results flow over the WebSocket. To run this flow end to end first, see the [Real-Time Voice Quickstart](/docs/voice/real-time-voice-quickstart).
+
+## The two-step connection flow
+
+Every Voice API session starts with two steps:
+
+1. [Request a session](/api-reference/voice/request-session) with a POST request to `/v3/voice/realtime`. This is where authentication happens and where you fix the session's configuration: audio formats, source and target languages, glossaries, spoken terms, and [message encoding](/docs/voice/message-encoding). The response contains an ephemeral streaming URL and a token, both valid for one-time use.
+2. [Open a WebSocket connection](/api-reference/voice/websocket-streaming) to the streaming URL, passing the token as a query parameter. All audio and results are exchanged as messages over this connection.
+
+Splitting setup from streaming keeps your API key out of the WebSocket handshake and settles all configuration before any audio flows. The WebSocket itself carries only audio and results.
+
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant Voice API
+
+ Note over Client,Voice API: Step 1: Request Session (POST)
+
+ Client->>Voice API: Configuration options
+ Voice API->>Client: Streaming URL and token
+
+ Note over Client,Voice API: Step 2: Start Streaming (WebSocket)
+
+ Client->>Voice API: Establish WebSocket connection
using the streaming URL
+
+ Note over Client,Voice API: WebSocket Connection Established
+
+ Client<<->>Voice API: Bidirectional message exchange:
Send audio, receive transcripts,
translations, and speech
+
+ Note over Client,Voice API: Stream Closed
+```
+
+
+## Tokens and reconnection
+
+Network connections are unreliable, so the Voice API is built around resumable sessions. A session is identified and secured by its token, which rotates over its lifetime: the initial session response and every reconnection response contain a new token, and your client should always keep the most recent one.
+
+If the connection drops, you exchange the latest token for a new streaming URL and token via [GET `/v3/voice/realtime`](/api-reference/voice/reconnect-session), then reconnect and pick up where you left off. Session state, including configuration and translation context, is preserved across reconnections.
+
+Two security properties follow from the token design:
+
+* Each token and streaming URL is valid for one-time use. Using a token more than once to open a WebSocket connection terminates the session immediately.
+* Only the latest token can request a reconnection. Presenting an outdated token invalidates the session.
+
+Requesting a reconnection token while a connection is still active disconnects that connection, so only reconnect after the existing connection has closed. Connections also have a maximum duration; when it's reached, reconnect the same way to continue the session. See [session limits](/docs/voice/supported-languages-formats-and-limits#session-limits) for the exact values.
+
+## How audio and results flow
+
+Once connected, you send audio continuously as [source media chunk](/api-reference/voice/websocket-streaming) messages. Smaller chunks mean lower latency, because the API can start processing sooner. When the audio ends, an [end of source media](/api-reference/voice/websocket-streaming) message tells the API to finalize all pending results. Keep audio flowing: a session with no incoming data times out and is terminated.
+
+As audio is processed, transcripts and translations arrive incrementally via [source transcript updates](/api-reference/voice/websocket-streaming) and [target transcript updates](/api-reference/voice/websocket-streaming). Each update distinguishes two kinds of segments:
+
+* **Concluded segments**: finalized text that will not change. These are sent once and remain fixed.
+* **Tentative segments**: preliminary text that may be refined as more audio context becomes available.
+
+Applications typically append concluded segments to the running transcript and display tentative segments as provisional text that gets replaced by later updates.
+
+### Translated speech (closed beta)
+
+When a translated speech target is configured, synthesized audio arrives incrementally as [target media chunks](/api-reference/voice/websocket-streaming). To save bandwidth, the stream contains only speech, without silence or padding, so there are gaps with no data whenever the speaker pauses. Each chunk carries text and audio duration information, which you can use to highlight the currently spoken text or to subtitle the audio output.
+
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant Voice API
+
+ Note over Client,Voice API: WebSocket Connection Established
+
+ par
+ loop Send audio data
+ Client->>Voice API: source_media_chunk
+ end
+ and
+ loop Receive updates
+ Voice API-->>Client: source_transcript_update
+ end
+ and Per target language
+ loop Receive updates
+ Voice API-->>Client: target_transcript_update
+ end
+ and Per target language
+ loop Receive translated speech
+ Voice API-->>Client: target_media_chunk
+ end
+ end
+
+ Client->>Voice API: end_of_source_media
+
+ par
+ loop Final updates
+ Voice API-->>Client: source_transcript_update
+ end
+ and Per target language
+ loop Final updates
+ Voice API-->>Client: target_transcript_update
+ end
+ and Per target language
+ loop Final audio chunks
+ Voice API-->>Client: target_media_chunk
+ end
+ end
+
+ Voice API-->>Client: end_of_source_transcript
+
+ Voice API-->>Client: end_of_target_transcript
(once per target language)
+
+ Voice API-->>Client: end_of_target_media
(once per target language)
+
+ Voice API-->>Client: end_of_stream
+
+ Note over Client,Voice API: Stream Closed
+```
+`par` means parallel execution and `loop` means looped execution.
+
diff --git a/docs/xml-and-html-handling/customized-xml-outline-detection.mdx b/docs/xml-and-html-handling/customized-xml-outline-detection.mdx
deleted file mode 100644
index f78d2328..00000000
--- a/docs/xml-and-html-handling/customized-xml-outline-detection.mdx
+++ /dev/null
@@ -1,41 +0,0 @@
----
-title: "Customized XML outline detection"
-description: "Learn how to customize XML outline detection with the DeepL API."
-mode: "wide"
----
-
-Automatic detection of the XML structure will not always yield the best results in all XML files. You can disable this automatic mechanism by setting the `outline_detection=0` and selecting the tags that should be considered structure tags. This will split sentences using the `splitting_tags` parameter.
-
-In the example below, we achieve the same results as the automatic engine by disabling automatic detection and setting the parameters manually:
-
-
- ```text Parameters
- tag_handling=xml, split_sentences=nonewlines, outline_detection=0, splitting_tags=par,title
- ```
-
- ```markup Example request
-
-
- A document's title
-
-
- This is the first sentence. Followed by a second one.
- This is the third sentence.
-
-
- ```
-
- ```markup Example response
-
-
- Der Titel eines Dokuments
-
-
- Das ist der erste Satz. Gefolgt von einem zweiten.
- Dies ist der dritte Satz.
-
-
- ```
-
-
-While this approach is slightly more complicated, it allows for greater control over the structure of the translation output.
\ No newline at end of file
diff --git a/docs/xml-and-html-handling/html.mdx b/docs/xml-and-html-handling/html.mdx
deleted file mode 100644
index 2699a7f3..00000000
--- a/docs/xml-and-html-handling/html.mdx
+++ /dev/null
@@ -1,49 +0,0 @@
----
-title: "HTML handling"
-description: "Learn how to translate HTML content with the DeepL API."
----
-
-
- We've released an **improved version** of XML and HTML tag handling. Check it out [here](/docs/xml-and-html-handling/tag-handling-v2)!
-
-
-By default, the translation engine does not take HTML tags into account. By setting the `tag_handling` parameter to `html`, the API will process HTML input by extracting the text out of the structure, splitting it into individual sentences, translating them, and placing them back into the HTML structure.
-
-
- For the translation of (non-HTML) XML content please see [XML Handling](/docs/xml-and-html-handling/xml)
-
-
-
-### Splitting of newlines
-
-The default value for the `split_sentences` parameter for all requests where `tag_handling=html` is `nonewlines`, meaning the translation engine splits on punctuation only, ignoring newlines.
-
-The default value `split_sentences` for text translations where `tag_handling` is not set to `html` is `1`, meaning the translation engine splits on punctuation and on newlines.
-
-Please note that when using HTML tag handling, the `split_sentences` parameter defaults to `nonewlines` for maximum translation quality.
-
-### Disable translation of elements
-
-To prevent the translation of elements in the HTML structure, the translation engine respects the `translate="no"` and `class="notranslate"` attributes. In the following example, the `translate="no"` attribute is used to prevent translation of the paragraph:
-
-
- ```markup Example request
-
-
-
- My First Heading
- My first paragraph.
-
-
- ```
-
- ```markup Example response
-
-
-
- Meine erste Überschrift
- My first paragraph.
-
-
- ```
-
diff --git a/docs/xml-and-html-handling/structured-content.mdx b/docs/xml-and-html-handling/structured-content.mdx
deleted file mode 100644
index 89cca58a..00000000
--- a/docs/xml-and-html-handling/structured-content.mdx
+++ /dev/null
@@ -1,113 +0,0 @@
----
-title: "Structured XML content"
-description: "Learn how to work with structured XML content with the DeepL API."
----
-
-When enabling `tag_handling` by setting it to `xml`, the DeepL API is able to process structured XML content. This includes whole XML files, as the following example shows.
-
-Please note that for XML structured content, the `split_sentences` parameter is set to `nonewlines` to ensure that newlines do not alter the results. The response is beautified for better readability.
-
-Parameters and corresponding results:
-
-
- ```text Parameters
- tag_handling=xml, split_sentences=nonewlines
- ```
-
- ```markup Example request
-
-
- A document's title
-
-
- This is the first sentence. Followed by a second one.
- This is the third sentence.
-
-
- ```
-
- ```markup Example response
-
-
- Der Titel eines Dokuments
-
-
- Das ist der erste Satz. Gefolgt von einem zweiten.
- Dies ist der dritte Satz.
-
-
- ```
-
-
-Before sentences are translated, the XML file is parsed, and tags containing textual content other than white space are identified, in order to reproduce the XML structure in the translation.
-
-In the example above, the `title` and the two `par` tags are found to contain text. These tags are considered sentence splitters. Therefore, each of the following three texts is treated separately:
-
-- _A document's title_
-- _This is the first sentence. Followed by a second one._
-- _This is the third sentence._
-
-The second text is further split, as it contains two separate sentences. Each sentence is then translated separately and tags within the sentences (used here for formatting) are applied to the corresponding words in the translation.
-
-### Splitting on New Lines
-
-Please note that newlines will split sentences. You should therefore clean files to avoid breaking sentences or set the parameter `split_sentences=nonewlines`.
-
-
- ```markup Request
- She bought oat
- biscuits.
- ```
-
- ```markup Response
- Sie kaufte Hafer
- Kekse.
- ```
-
-
- Here, the two parts of the sentence have been translated separately and resulted in an error: "oat biscuits" has been translated as "Hafer Kekse" instead of "Haferkekse".
-
-
-
-### Restricting Splitting
-
-For some XML files, finding tags with textual content and splitting sentences using those tags won't yield the best translation results. The following examples show the difference in results when the engine splits sentences on `par` tags and proceed to translate the parts separately, as opposed to translating the sentence as a whole.
-
-As this can lead to bad translations, this type of structure should either be avoided, or the `non_splitting_tags` parameter should be set.
-
-
-
- ```text Parameters
- tag_handling=xml, non_splitting_tags=par
- ```
-
- ```markup Request
- The firm said it had been conducting an internal investigation.
- ```
-
- ```markup Response
- Die Firma sagte, dass sie eine interne Untersuchung durchgeführt habe.
- ```
-
-
- This time, the sentence is translated as a whole. The XML tags are now considered markup and copied into the translated sentence. As the translation of the words "had been" has moved to another position in the German sentence, the two `par` tags are duplicated (which is expected here).
-
-
-
- ```text Parameters
- tag_handling=xml
- ```
-
- ```markup Request
- The firm said it had been conducting an internal investigation.
- ```
-
- ```markup Response
- Die Firma sagte, es sei eine gute Idee gewesen. Durchführung einer internen Untersuchung.
- ```
-
-
- Translating separately results in an incorrect translation. As this can lead to bad translations, this type of structure should either be avoided, or the `non_splitting_tags` parameter should be set.
-
-
-
\ No newline at end of file
diff --git a/docs/xml-and-html-handling/tag-handling-v2.mdx b/docs/xml-and-html-handling/tag-handling-v2.mdx
deleted file mode 100644
index 4a2fd366..00000000
--- a/docs/xml-and-html-handling/tag-handling-v2.mdx
+++ /dev/null
@@ -1,182 +0,0 @@
----
-title: "New: XML/HTML handling v2"
-description: "Learn about the benefits of tag handling v2 and how to migrate."
----
-
-## Overview
-
-Tag handling v2 is an improved algorithm for translating XML and HTML content. Set `tag_handling_version=v2` to enable it.
-
-## What's New in v2
-
-Tag handling v2 uses an algorithm that balances both translation quality and formatting. Sentences are now translated more naturally without being constrained by tag placement in the source text. It also handles edge cases around tag preservation, DOM hierarchy, and character escaping.
-
-V2 enforces strict XML parsing and will return an error if invalid XML is submitted.
-
-
- Customers who had not used tag handling prior to 2025-12-01 default to v2. All other customers default to v1.
-
-
-## Usage Examples
-
-### Translation with v2
-
-
-
- ```text Parameters
- tag_handling=html, tag_handling_version=v2
- ```
-
- ```markup Request
-
-
-
- Welcome to Our Service
- This is a premium feature.
-
-
- ```
-
- ```markup Response
-
-
-
- Willkommen bei unserem Service
- Dies ist eine Premium-Funktion.
-
-
- ```
-
-
- ```text Parameters
- tag_handling=xml, tag_handling_version=v2
- ```
-
- ```markup Request
- Press Continue to advance.
- ```
-
- ```markup Response
- Drücken Sie „Weiter", um fortzufahren.
- ```
-
-
- ```text Parameters
- tag_handling=xml, tag_handling_version=v2
- ```
-
- ```markup Request
- Please welcome the participants to today's meeting.
- ```
-
- ```markup Response
- Bitte begrüßen Sie die Teilnehmer an der heutigen Sitzung.
- ```
-
-
- ```text Parameters
- tag_handling=xml, tag_handling_version=v2
- ```
-
- ```markup Request
- The firm said it had been conducting an internal investigation for several months.
- ```
-
- ```markup Response
- Das Unternehmen gab an, dass es seit mehreren Monaten eine interne Untersuchung durchgeführt habe.
- ```
-
-
-
-### Strict XML Parsing
-
-Tag handling v2 enforces strict XML parsing. If invalid XML is submitted, the API will return an error:
-
-
- ```text Parameters
- tag_handling=xml, tag_handling_version=v2
- ```
-
- ```markup Request (Invalid XML)
- This tag is not closed properly
- ```
-
- ```json Response (Error)
- {
- "Message": "Tag handling parsing failed, please check input."
- }
- ```
-
-
-Only XML is strictly parsed. HTML is not strictly parsed.
-
-## Compatibility
-
-Tag handling v2 is compatible with all model types.
-
-| Model Type | v1 Support | v2 Support |
-|------------|:----------:|:----------:|
-| `quality_optimized` | ✅ | ✅ |
-| `latency_optimized` | ✅ | ✅ |
-
-## Migration Guide
-
-Tag handling is expected to give different results between v1 and v2. Thoroughly test your system and verify any differences in output before switching to v2 in production.
-
-### 1. Test Your Content
-
-Run v2 translations on representative samples of your content, especially:
-
-- Text with deep tag hierarchies
-- Text with inline markup, attributes, and special characters
-- Edge cases such as empty or self-closing tags
-
-### 2. Compare Outputs
-
-Compare v1 and v2 outputs, and make any updates needed to maintain your workflows.
-
-- Ensure that the tags are preserved correctly
-- Compare any differences in translation
-- Note any formatting changes
-
-### 3. Validate XML Syntax
-
-Since v2 enforces strict XML parsing:
-
-- Ensure all your XML input is well-formed
-- Add error handling for invalid XML responses
-- Update any XML generation logic if needed
-
-## Related Documentation
-
-For more information about XML and HTML tag handling:
-
-- [HTML Handling](/docs/xml-and-html-handling/html)
-- [XML Handling](/docs/xml-and-html-handling/xml)
-- [Structured XML Content](/docs/xml-and-html-handling/structured-content)
-
-## FAQ
-
-**Q: What is the default tag handling version?**
-
-A: Customers who had not used tag handling prior to 2025-12-01 default to v2. All other customers default to v1.
-
-**Q: Should I upgrade to v2?**
-
-A: Upgrading to v2 is strongly recommended and will provide improvements to both translation quality and structural correctness. Test thoroughly with your specific content before switching in production.
-
-**Q: What happens if my XML is invalid?**
-
-A: Tag handling v2 enforces strict XML parsing. Invalid XML will return an error response. Ensure your XML is well-formed before submission.
-
-**Q: Can I switch back to v1 if needed?**
-
-A: Yes, simply set `tag_handling_version: v1` in your API requests.
-
-**Q: Does v2 work with all DeepL API features?**
-
-A: Tag handling v2 works with all standard API features and `model_type`s.
-
-**Q: Is HTML also strictly parsed?**
-
-A: No, any HTML can be submitted for translation without throwing an error. Only XML is strictly parsed and requires valid XML.
diff --git a/docs/xml-and-html-handling/xml.mdx b/docs/xml-and-html-handling/xml.mdx
deleted file mode 100644
index 27dcf4d8..00000000
--- a/docs/xml-and-html-handling/xml.mdx
+++ /dev/null
@@ -1,80 +0,0 @@
----
-title: "XML handling"
-description: "Learn how to translate XML content with the DeepL API."
----
-
- We've released [tag handling v2](/docs/xml-and-html-handling/tag-handling-v2), providing major improvements to XML and HTML tag handling. Note that v2 enforces strict XML parsing.
-
-
-By default, the translation engine does not take tags into account. By setting the `tag_handling` parameter to `xml`, the API will process XML input by extracting the text out of the structure, splitting it into individual sentences, translating them, and placing them back into the XML structure.
-
-
-For best results, also set the [`tag_handling_version` parameter](/docs/xml-and-html-handling/tag-handling-v2) to `v2` in your request.
-
-
- For the translation of HTML content please see [HTML Handling](/docs/xml-and-html-handling/html)
-
-
-
-### Sentences with Markup
-
-If you want to translate text where individual parts are marked up, you can simply activate the XML engine by setting `tag_handling` to `xml`. The following examples show marked-up text and how it will be translated:
-
-
-
- ```markup Request
- Press Continue to advance to the next page.
- ```
-
- ```markup Response
- Drücken Sie Weiter, um zur nächsten Seite zu gelangen.
- ```
-
-
- ```markup Request
- Please welcome the participants to today's meeting.
- ```
-
- ```markup Response
- Bitte begrüßen Sie die Teilnehmer des heutigen Treffens.
- ```
-
-
- ```markup Request
- The firm said it had been conducting an internal investigation for several months.
- ```
-
- ```markup Response
- Das Unternehmen sagte, dass es seit mehreren Monaten eine interne Untersuchungdurchgeführt habe.
- ```
-
-
- ```markup Request
- Artificial intelligence is already shaping our everyday lives.
- ```
-
- ```markup Response
- Künstliche Intelligenz prägt bereits heute unseren Alltag.
- ```
-
-
-
-In general, placeholders are associated with the words preceding or following them in the source sentence and are then applied to their respective translations in the target sentence.
-
-### Ignored Tags
-
-Use the `ignore_tags` parameter to specify that content within specific tags should not be translated. The example below uses `ignore_tags=x` to tell DeepL to preserve text between ` `and `` tags as is.
-
-
- ```text Parameters
- tag_handling=xml, ignore_tags=x
- ```
-
- ```markup Request
- Please open the page Settings to configure your system.
- ```
-
- ```markup Response
- Bitte öffnen Sie die Seite Settings um Ihr System zu konfigurieren.
- ```
-
diff --git a/snippets/feature-maturity-callouts.mdx b/snippets/feature-maturity-callouts.mdx
new file mode 100644
index 00000000..129b0c59
--- /dev/null
+++ b/snippets/feature-maturity-callouts.mdx
@@ -0,0 +1,38 @@
+{/*
+ Feature maturity callouts — standard boilerplate for alpha/beta/GA labels.
+ Import the one that matches your feature's maturity stage.
+
+ Usage in any .mdx file:
+ import ClosedAlpha from '/snippets/feature-maturity-callouts.mdx#closed-alpha'
+
+ Or copy the relevant block directly if Mintlify snippet
+ imports don't support anchors.
+*/}
+
+{/* ===== CLOSED ALPHA ===== */}
+export const ClosedAlpha = () => (
+
+ **Closed alpha.** This API may change without notice and is only available to select DeepL customers. See [alpha and beta features](/docs/resources/alpha-and-beta-features) for details. To request access, contact your customer success manager.
+
+);
+
+{/* ===== OPEN ALPHA ===== */}
+export const OpenAlpha = () => (
+
+ **Open alpha.** This API may change without notice. See [alpha and beta features](/docs/resources/alpha-and-beta-features) for details. To request access, [submit a support request](https://support.deepl.com/hc/en-us/requests/new).
+
+);
+
+{/* ===== CLOSED BETA ===== */}
+export const ClosedBeta = () => (
+
+ **Closed beta.** This API is only available to select DeepL customers. See [alpha and beta features](/docs/resources/alpha-and-beta-features) for details. To request access, contact your customer success manager.
+
+);
+
+{/* ===== OPEN BETA ===== */}
+export const OpenBeta = () => (
+
+ **Beta.** This feature is available to all API users but may change based on feedback. See [alpha and beta features](/docs/resources/alpha-and-beta-features) for details.
+
+);