Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions api-reference/admin-api/get-custom-tag-usage-analytics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,22 @@ The response contains a `custom_tag_usage_report` object with the following fiel
Each entry in `usage` includes:
- `custom_tag`: the tag identifier
- `usage_date`: the day the usage was recorded (ISO 8601 datetime). Only returned when `aggregate_by` is `day`
- `breakdown`: character counts split by service type
- `breakdown`: usage split by service type

### Usage breakdown

| **Field** | **Description** |
|:---|:---|
| `total_characters` | Combined character usage across all services |
| `total_characters` | Combined character usage across character-based services |
| `text_translation_characters` | Characters used for text translation |
| `text_improvement_characters` | Characters used for text improvement (rephrasing) |
| `speech_to_text_minutes` | Minutes of speech-to-text usage. Fractional values are returned, for example `12.5` |
| `speech_to_speech_minutes` | Minutes of speech-to-speech usage. Fractional values are returned, for example `4.2` |

Voice usage is reported in minutes and is not included in `total_characters`, which covers character-based services only.

<Warning>
Custom tag data is supported only for text translation. Support for other request types will be added in a future update.
Custom tag data is recorded only for text translation and Voice API requests. Support for other request types will be added in a future update.
</Warning>

## Pagination
Expand Down
53 changes: 46 additions & 7 deletions api-reference/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"name": "DeepL - Contact us",
"url": "https://www.deepl.com/contact-us"
},
"version": "3.12.0"
"version": "3.13.0"
},
"externalDocs": {
"description": "DeepL Pro - Plans and pricing",
Expand Down Expand Up @@ -333,15 +333,19 @@
"breakdown": {
"total_characters": 380,
"text_translation_characters": 380,
"text_improvement_characters": 0
"text_improvement_characters": 0,
"speech_to_text_minutes": 12.5,
"speech_to_speech_minutes": 4.2
}
},
{
"custom_tag": "example-custom-tag-2",
"breakdown": {
"total_characters": 475,
"text_translation_characters": 475,
"text_improvement_characters": 0
"text_improvement_characters": 0,
"speech_to_text_minutes": 0,
"speech_to_speech_minutes": 0
}
}
]
Expand All @@ -363,7 +367,9 @@
"breakdown": {
"total_characters": 380,
"text_translation_characters": 380,
"text_improvement_characters": 0
"text_improvement_characters": 0,
"speech_to_text_minutes": 12.5,
"speech_to_speech_minutes": 4.2
}
},
{
Expand All @@ -372,7 +378,9 @@
"breakdown": {
"total_characters": 595,
"text_translation_characters": 595,
"text_improvement_characters": 0
"text_improvement_characters": 0,
"speech_to_text_minutes": 0,
"speech_to_speech_minutes": 0
}
}
]
Expand Down Expand Up @@ -739,6 +747,11 @@
],
"summary": "Request Translation",
"operationId": "translateText",
"parameters": [
{
"$ref": "#/components/parameters/CustomReportingTag"
}
],
"requestBody": {
"required": true,
"content": {
Expand Down Expand Up @@ -5959,6 +5972,11 @@
],
"summary": "Get Streaming URL",
"operationId": "getVoiceStreamingUrl",
"parameters": [
{
"$ref": "#/components/parameters/CustomReportingTag"
}
],
"requestBody": {
"required": true,
"content": {
Expand Down Expand Up @@ -6720,6 +6738,17 @@
}
},
"parameters": {
"CustomReportingTag": {
"name": "X-DeepL-Reporting-Tag",
"in": "header",
"required": false,
"description": "An optional custom reporting tag used to attribute this request's usage to a team, project, customer, or other category of your choosing. Values are limited to 100 characters. See [How to use custom reporting tags](/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags) for validation rules, naming guidance, and how to retrieve usage by tag.\n",
"schema": {
"type": "string",
"maxLength": 100
},
"example": "team-billing"
},
"DocumentID": {
"name": "document_id",
"description": "The document ID that was sent to the client when the document was uploaded to the API.",
Expand Down Expand Up @@ -10385,11 +10414,11 @@
},
"CustomTagBreakdown": {
"type": "object",
"description": "Breakdown of character usage by category for a custom tag.",
"description": "Breakdown of usage by category for a custom tag.",
"properties": {
"total_characters": {
"type": "integer",
"description": "Total number of characters used.",
"description": "Total number of characters used across character-based services. Voice usage is reported in minutes and is not included in this total.\n",
"example": 380
},
"text_translation_characters": {
Expand All @@ -10401,6 +10430,16 @@
"type": "integer",
"description": "Number of characters used for text improvement.",
"example": 0
},
"speech_to_text_minutes": {
"type": "number",
"description": "Duration of speech-to-text usage in minutes.",
"example": 12.5
},
"speech_to_speech_minutes": {
"type": "number",
"description": "Duration of speech-to-speech usage in minutes.",
"example": 4.2
}
}
},
Expand Down
42 changes: 39 additions & 3 deletions api-reference/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ info:
contact:
name: DeepL - Contact us
url: https://www.deepl.com/contact-us
version: 3.12.0
version: 3.13.0
externalDocs:
description: DeepL Pro - Plans and pricing
url: https://www.deepl.com/pro#developer
Expand Down Expand Up @@ -310,11 +310,15 @@ paths:
total_characters: 380
text_translation_characters: 380
text_improvement_characters: 0
speech_to_text_minutes: 12.5
speech_to_speech_minutes: 4.2
- custom_tag: "example-custom-tag-2"
breakdown:
total_characters: 475
text_translation_characters: 475
text_improvement_characters: 0
speech_to_text_minutes: 0
speech_to_speech_minutes: 0
aggregateByDay:
summary: Usage report aggregated by day
value:
Expand All @@ -330,12 +334,16 @@ paths:
total_characters: 380
text_translation_characters: 380
text_improvement_characters: 0
speech_to_text_minutes: 12.5
speech_to_speech_minutes: 4.2
- custom_tag: "example-custom-tag"
usage_date: "2026-05-11T00:00:00Z"
breakdown:
total_characters: 595
text_translation_characters: 595
text_improvement_characters: 0
speech_to_text_minutes: 0
speech_to_speech_minutes: 0
400:
description: Bad request. Please check error message and your parameters.
headers:
Expand Down Expand Up @@ -554,6 +562,8 @@ paths:
- TranslateText
summary: Request Translation
operationId: translateText
parameters:
- $ref: '#/components/parameters/CustomReportingTag'
requestBody:
required: true
content:
Expand Down Expand Up @@ -4166,6 +4176,8 @@ paths:
- VoiceAPI
summary: Get Streaming URL
operationId: getVoiceStreamingUrl
parameters:
- $ref: '#/components/parameters/CustomReportingTag'
requestBody:
required: true
content:
Expand Down Expand Up @@ -4644,6 +4656,20 @@ components:
type: string
example: 501c3d93cc0c4f11ae2f60a226c2f0f0
parameters:
CustomReportingTag:
name: X-DeepL-Reporting-Tag
in: header
required: false
description: >
An optional custom reporting tag used to attribute this request's usage to a
team, project, customer, or other category of your choosing. Values are
limited to 100 characters. See [How to use custom reporting
tags](/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags)
for validation rules, naming guidance, and how to retrieve usage by tag.
schema:
type: string
maxLength: 100
example: team-billing
DocumentID:
name: document_id
description: The document ID that was sent to the client when the document was
Expand Down Expand Up @@ -7749,11 +7775,13 @@ components:
$ref: '#/components/schemas/CustomTagBreakdown'
CustomTagBreakdown:
type: object
description: Breakdown of character usage by category for a custom tag.
description: Breakdown of usage by category for a custom tag.
properties:
total_characters:
type: integer
description: Total number of characters used.
description: >
Total number of characters used across character-based services. Voice
usage is reported in minutes and is not included in this total.
example: 380
text_translation_characters:
type: integer
Expand All @@ -7763,6 +7791,14 @@ components:
type: integer
description: Number of characters used for text improvement.
example: 0
speech_to_text_minutes:
type: number
description: Duration of speech-to-text usage in minutes.
example: 12.5
speech_to_speech_minutes:
type: number
description: Duration of speech-to-speech usage in minutes.
example: 4.2
ErrorResponse:
type: object
required:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
title: "How to Use Custom Reporting Tags"
description: "Learn how to attach reporting tags to translate requests so you can break down usage by team, project, or category."
description: "Learn how to attach reporting tags to text translation and Voice API requests so you can break down usage by team, project, or category."
public: true
---

**This guide shows you:**
- When to use custom reporting tags
- How to attach a tag to a translate request via the `X-DeepL-Reporting-Tag` header
- How to attach a tag to a text translation or Voice API request via the `X-DeepL-Reporting-Tag` header
- Tag naming guidance and current limitations

---

## What custom reporting tags are for

Custom reporting tags let your organization attribute API usage to a team, project, customer, or any other category you care about. You attach a tag to each translate request, and you can then retrieve usage broken down by those tags in two ways: programmatically via the [Get custom tag usage analytics](/api-reference/admin-api/get-custom-tag-usage-analytics) endpoint, or as a [custom tag-level CSV export](/docs/admin/retrieving-usage-data#csv-export) from the account UI.
Custom reporting tags let your organization attribute API usage to a team, project, customer, or any other category you care about. You attach a tag to each request, and you can then retrieve usage broken down by those tags in two ways: programmatically via the [Get custom tag usage analytics](/api-reference/admin-api/get-custom-tag-usage-analytics) endpoint, or as a [custom tag-level CSV export](/docs/admin/retrieving-usage-data#csv-export) from the account UI.

Common use cases:

Expand All @@ -23,7 +23,7 @@ Common use cases:
Only tagged requests appear in custom-tag reports, so tag every request you want to track.

<Warning>
Custom tag data is currently supported for text translation. Support for additional request types will be added in a future update.
Custom tag data is recorded only for text translation and Voice API requests. Support for additional request types will be added in a future update.
</Warning>

---
Expand Down Expand Up @@ -60,6 +60,38 @@ The translate response is unchanged by tagging. The tag is recorded server-side

---

## How to tag a Voice API session

Set the same header on the [session request](/api-reference/voice/request-session). The tag applies to the whole session, so all audio streamed over the resulting WebSocket connection is attributed to it.

```sh
curl --request POST 'https://api.deepl.com/v3/voice/realtime' \
--header 'Authorization: DeepL-Auth-Key [your key]' \
--header 'X-DeepL-Reporting-Tag: team-billing' \
--header 'Content-Type: application/json' \
--data '{
"source_media_content_type": "audio/ogg;codecs=opus",
"source_language_mode": "auto",
"target_languages": ["de"]
}'
```

**Sample response:**

```json
{
"streaming_url": "wss://api.deepl.com/v3/voice/realtime/connect",
"token": "VGhpcyBpcyBhIGZha2UgdG9rZW4K",
"session_id": "4f911080-cfe2-41d4-8269-0e6ec15a0354"
}
```

The WebSocket connection itself carries no headers, so the session request is the only place a tag can be set. You cannot change or add a tag once a session is running, and you cannot tag individual audio chunks within a session. To attribute audio to more than one tag, open a separate session per tag.

The tag survives [reconnection](/api-reference/voice/reconnect-session): audio streamed after you exchange a token for a new streaming URL is still attributed to the tag set on the original session request, and you do not resend the header.

---

## Tag naming guidance

A few practices keep your reports clean:
Expand All @@ -86,6 +118,7 @@ Tags are a reporting feature only. You cannot use them to enforce limits, quotas
- Tag values are limited to 100 characters. Requests with longer values are rejected with a 400 response.
- Tag values must use ASCII characters only, with no internal whitespace and no control characters. Values like `sample tag`, `sample-tág`, or `sample\ntag` are rejected with a 400 response. Leading and trailing whitespace is trimmed before validation (see [Tag naming guidance](#tag-naming-guidance)).
- Each request accepts one tag. Sending multiple values in the header is not supported.
- For the Voice API, a tag covers a whole session and can only be set on the session request. See [How to tag a Voice API session](#how-to-tag-a-voice-api-session).
- Untagged requests are not included in custom-tag analytics. They still count toward your overall usage, which you can retrieve through the [Get usage analytics](/api-reference/admin-api/get-usage-analytics) endpoint.

---
Expand Down
5 changes: 5 additions & 0 deletions docs/resources/roadmap-and-release-notes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ rss: true
</Update>

<Update label="August 2026">
## August 18 - Custom Reporting Tags for the Voice API
- [Custom reporting tags](/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags), which attribute API usage to a team, project, or other category via the `X-DeepL-Reporting-Tag` request header, now work for the [Voice API](/docs/voice/overview) in addition to text translation. Send the header on the [session request](/api-reference/voice/request-session) and the whole session's usage is attributed to that tag.
- The [custom tag usage analytics endpoint](/api-reference/admin-api/get-custom-tag-usage-analytics) reports voice usage as `speech_to_text_minutes` and `speech_to_speech_minutes` alongside the existing character fields. Voice minutes are not included in `total_characters`.
- A tag can only be set on the session request, since the WebSocket connection carries no headers. To attribute audio to more than one tag, open a separate session per tag.

## August 11 - Translation Memory Management API
- You can now create, inspect, export, and delete [translation memories](/docs/customize/using-translation-memories) through the API. Translation memories store previously translated segments so the same source text produces consistent output across projects. Previously, the API could only list the translation memories on your account, and everything else had to be done in the DeepL UI.
- [`POST /v3/translation_memories/import`](/api-reference/translation-memory/import-a-translation-memory) creates a translation memory from a TMX file. The request declares the file and returns a signed upload URL plus a `job_id`; you upload the file to that URL and poll the job for the new `translation_memory_id`.
Expand Down
2 changes: 1 addition & 1 deletion docs/voice/understanding-voice-sessions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This page explains the lifecycle of a Voice API session: how a connection is est

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.
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, [message encoding](/docs/voice/message-encoding), and an optional [custom reporting tag](/docs/learning-how-tos/examples-and-guides/how-to-use-custom-reporting-tags). 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.
Expand Down
Loading