diff --git a/api-reference/admin-api/get-custom-tag-usage-analytics.mdx b/api-reference/admin-api/get-custom-tag-usage-analytics.mdx
new file mode 100644
index 00000000..e93b5cc2
--- /dev/null
+++ b/api-reference/admin-api/get-custom-tag-usage-analytics.mdx
@@ -0,0 +1,51 @@
+---
+openapi: get /v2/admin/analytics/custom-tags
+title: "Get custom tag usage analytics"
+---
+
+## Date range
+
+Specify the reporting window using the required `start_date` and `end_date` parameters in ISO 8601 date format (e.g., `2026-05-01`). The maximum date range is 366 days.
+
+## Aggregation
+
+The optional `aggregate_by` parameter controls how usage is grouped:
+
+| **Value** | **Description** |
+|:---|:---|
+| `period` (default) | Returns total usage per custom tag over the entire date range |
+| `day` | Returns usage per custom tag broken down by individual day |
+
+Use `period` when you need a summary for billing or reporting. Use `day` when you need to analyze usage trends over time.
+
+## Response structure
+
+The response contains a `custom_tag_usage_report` object with the following fields:
+
+| **Field** | **Description** |
+|:---|:---|
+| `aggregate_by` | The aggregation method used (`period` or `day`) |
+| `start_date` | Start of the reporting period (ISO 8601 datetime) |
+| `end_date` | End of the reporting period (ISO 8601 datetime) |
+| `next_page` | Integer cursor for the next page of results. `null` if there are no further pages |
+| `usage` | Array of usage entries, one per custom tag |
+
+Each entry in `usage` includes:
+- `custom_tag`: the tag identifier
+- `breakdown`: character counts split by service type
+
+### Usage breakdown
+
+| **Field** | **Description** |
+|:---|:---|
+| `total_characters` | Combined character usage across all services |
+| `text_translation_characters` | Characters used for text translation |
+| `text_improvement_characters` | Characters used for text improvement (rephrasing) |
+
+
+Custom tag data is supported only for text translation. Support for other request types will be added in a future update.
+
+
+## Pagination
+
+Results are paginated. If the response includes a non-null `next_page` value, pass it as the `page` parameter in your next request to retrieve the following page. Continue until `next_page` is `null`.
diff --git a/api-reference/admin-api/get-usage-analytics.mdx b/api-reference/admin-api/get-usage-analytics.mdx
index e844752e..d4027f86 100644
--- a/api-reference/admin-api/get-usage-analytics.mdx
+++ b/api-reference/admin-api/get-usage-analytics.mdx
@@ -3,3 +3,35 @@ openapi: get /v2/admin/analytics
title: "Get usage analytics"
---
+## Date range
+
+Specify the reporting window using the required `start_date` and `end_date` parameters. Both support the following formats (all in UTC):
+
+| **Format** | **Example** |
+|:---|:---|
+| `YYYY-MM-DD` | `2025-09-29` |
+| `YYYY-MM-DDTHH:MM:SS` | `2025-09-29T14:30:00` |
+
+The maximum date range is 366 days.
+
+## Grouping
+
+The optional `group_by` parameter controls how results are organized:
+
+| **Value** | **Description** |
+|:---|:---|
+| (default) | Returns total usage for the entire date range across all API keys |
+| `key` | Groups usage by individual API key, showing totals for each key over the date range |
+| `key_and_day` | Groups usage by both API key and day, providing daily breakdowns per key |
+
+## Response structure
+
+All responses include a breakdown of usage by service type:
+
+| **Field** | **Description** |
+|:---|:---|
+| `total_characters` | Combined character usage across all services |
+| `text_translation_characters` | Characters used for text translation |
+| `document_translation_characters` | Characters used for document translation |
+| `text_improvement_characters` | Characters used for text improvement (rephrasing) |
+| `speech_to_text_minutes` | Duration of speech-to-text usage in minutes |
diff --git a/api-reference/admin-api/organization-usage-analytics.mdx b/api-reference/admin-api/organization-usage-analytics.mdx
index 869f5f4d..7ea9514e 100644
--- a/api-reference/admin-api/organization-usage-analytics.mdx
+++ b/api-reference/admin-api/organization-usage-analytics.mdx
@@ -1,54 +1,38 @@
---
-title: "Accessing organization usage analytics"
+title: "Accessing usage analytics"
description: "Learn how admins can retrieve and analyze usage data across their organization."
public: true
---
-The Admin API allows admins to retrieve detailed usage statistics for their organization through the [Get usage analytics](/api-reference/admin-api/get-usage-analytics) endpoint.
+The Admin API provides two endpoints for monitoring usage across your organization:
-This analytics functionality enables you to:
-* Track character usage across your entire organization
-* Monitor usage by individual API keys
-* Analyze usage patterns over time
-* Generate reports for specific date ranges
-* Break down usage by service type (text translation, document translation, text improvement)
+- [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
-## Usage statistics endpoint
+## Organization usage
-The analytics endpoint provides detailed usage information for a specified date range with flexible grouping options.
+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.
-### Date range queries
+## Custom tag usage
-Retrieve usage statistics by specifying a start and end date. Both `start_date` and `end_date` parameters are required and support the following formats (all in UTC):
-* `YYYY-MM-DD` - Simple date format (e.g., `2025-09-29`)
-* `YYYY-MM-DDTHH:MM:SS` - Full datetime format (e.g., `2025-09-29T14:30:00`)
+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 maximum date range is 366 days.
+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.
-### Grouping options
+```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"
+ }'
+```
-The optional `group_by` parameter allows you to organize usage data in different ways:
-
-* **No grouping** (default): Returns total usage for the entire date range across all API keys
-* **`key`**: Groups usage by individual API key, showing totals for each key over the entire date range
-* **`key_and_day`**: Groups usage by both API key and day, providing daily breakdowns for each key
-
-### Usage breakdown
-
-All responses include a breakdown of usage by service type:
-* **Total characters**: Combined usage across all services
-* **Text translation characters**: Characters used for text translation
-* **Document translation characters**: Characters used for document translation
-* **Text improvement characters**: Characters used for text improvement (rephrasing)
-* **Speech-to-text minutes**: Duration of speech-to-text usage in minutes
-
-## Use cases
-
-The account-level analytics endpoint is particularly useful for:
-
-* **Cost monitoring**: Track usage to stay within budget limits and forecast costs
-* **Resource allocation**: Identify which teams or projects (represented by API keys) are using the most resources
-* **Usage trends**: Analyze daily or weekly usage patterns to optimize resource planning
-* **Compliance and auditing**: Generate detailed usage reports for compliance requirements
-* **Performance tracking**: Monitor adoption and usage of different DeepL services within your organization
+
+Custom tag data is currently supported for text translation. Support for additional request types will be added in a future update.
+
+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/openapi.json b/api-reference/openapi.json
index 8eb9b5ad..b2deb4df 100644
--- a/api-reference/openapi.json
+++ b/api-reference/openapi.json
@@ -8,7 +8,7 @@
"name": "DeepL - Contact us",
"url": "https://www.deepl.com/contact-us"
},
- "version": "3.9.0"
+ "version": "3.10.0"
},
"externalDocs": {
"description": "DeepL Pro - Plans and pricing",
@@ -64,6 +64,10 @@
{
"name": "VoiceTranslateJob",
"description": "**Alpha.** Async voice translation jobs. This API may change without notice."
+ },
+ {
+ "name": "AdminApi",
+ "description": "Endpoints for organization administrators to manage API keys and retrieve usage analytics."
}
],
"x-hideTryItPanel": true,
@@ -232,6 +236,183 @@
]
}
},
+ "/v2/admin/analytics/custom-tags": {
+ "get": {
+ "tags": [
+ "AdminApi"
+ ],
+ "summary": "Get custom tag usage statistics as an admin",
+ "operationId": "adminGetCustomTagAnalytics",
+ "description": "Retrieve usage statistics broken down by custom tags within a specified date range.\nOptionally aggregate results by day or over the entire period.\nResults are paginated; use the `page` parameter with the `next_page` value from\na previous response to retrieve subsequent pages.",
+ "parameters": [
+ {
+ "name": "start_date",
+ "in": "query",
+ "required": true,
+ "description": "Start date for the usage report (ISO 8601 date format).",
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "example": "2026-05-17"
+ },
+ {
+ "name": "end_date",
+ "in": "query",
+ "required": true,
+ "description": "End date for the usage report (ISO 8601 date format).",
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "example": "2026-05-18"
+ },
+ {
+ "name": "aggregate_by",
+ "in": "query",
+ "required": false,
+ "description": "Optional parameter to control aggregation of usage statistics. Possible values:\n * `period` - Aggregate usage over the entire date range (default)\n * `day` - Group usage by individual day",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "period",
+ "day"
+ ],
+ "default": "period"
+ },
+ "example": "day"
+ },
+ {
+ "name": "page",
+ "in": "query",
+ "required": false,
+ "description": "Page number for pagination. Use the integer value returned in `next_page` from\na previous response to retrieve the next page of results.",
+ "schema": {
+ "type": "integer"
+ },
+ "example": 2
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The custom tag usage statistics for the specified date range.",
+ "headers": {
+ "X-Trace-ID": {
+ "$ref": "#/components/headers/X-Trace-ID"
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/CustomTagUsageReport"
+ },
+ "examples": {
+ "aggregateByPeriod": {
+ "summary": "Usage report aggregated over the full period",
+ "value": {
+ "custom_tag_usage_report": {
+ "aggregate_by": "period",
+ "start_date": "2026-05-03T00:00:00",
+ "end_date": "2026-05-05T00:00:00",
+ "next_page": null,
+ "usage": [
+ {
+ "custom_tag": "example-custom-tag",
+ "breakdown": {
+ "total_characters": 380,
+ "text_translation_characters": 380,
+ "text_improvement_characters": 0
+ }
+ },
+ {
+ "custom_tag": "example-custom-tag-2",
+ "breakdown": {
+ "total_characters": 475,
+ "text_translation_characters": 475,
+ "text_improvement_characters": 0
+ }
+ }
+ ]
+ }
+ }
+ },
+ "aggregateByDay": {
+ "summary": "Usage report aggregated by day",
+ "value": {
+ "custom_tag_usage_report": {
+ "aggregate_by": "day",
+ "start_date": "2026-05-17T00:00:00",
+ "end_date": "2026-05-18T00:00:00",
+ "next_page": 2,
+ "usage": [
+ {
+ "custom_tag": "example-custom-tag",
+ "breakdown": {
+ "total_characters": 190,
+ "text_translation_characters": 190,
+ "text_improvement_characters": 0
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad request. Please check error message and your parameters.",
+ "headers": {
+ "X-Trace-ID": {
+ "$ref": "#/components/headers/X-Trace-ID"
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "description": "Error message describing the issue."
+ }
+ }
+ },
+ "examples": {
+ "dateRangeExceeded": {
+ "summary": "Date range exceeds maximum allowed",
+ "value": {
+ "message": "Bad request. Reason: Date range cannot exceed 366 days"
+ }
+ },
+ "invalidAggregateBy": {
+ "summary": "Invalid aggregate_by parameter value",
+ "value": {
+ "message": "Value for 'aggregate_by' not supported. Allowed: '', 'period', 'day'."
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "$ref": "#/components/responses/Forbidden"
+ },
+ "404": {
+ "$ref": "#/components/responses/NotFound"
+ },
+ "500": {
+ "$ref": "#/components/responses/InternalServerError"
+ }
+ },
+ "security": [
+ {
+ "auth_header": []
+ }
+ ]
+ }
+ },
"/v2/admin/developer-keys": {
"post": {
"tags": [
@@ -7625,6 +7806,90 @@
}
}
},
+ "CustomTagUsageReport": {
+ "type": "object",
+ "description": "The response for admin custom tag usage statistics.",
+ "properties": {
+ "custom_tag_usage_report": {
+ "$ref": "#/components/schemas/CustomTagUsageReportData"
+ }
+ }
+ },
+ "CustomTagUsageReportData": {
+ "type": "object",
+ "description": "Contains the detailed custom tag usage statistics for the specified date range.",
+ "properties": {
+ "aggregate_by": {
+ "type": "string",
+ "description": "The aggregation method used.",
+ "enum": [
+ "period",
+ "day"
+ ],
+ "example": "period"
+ },
+ "start_date": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Start date of the usage report period.",
+ "example": "2026-05-03T00:00:00"
+ },
+ "end_date": {
+ "type": "string",
+ "format": "date-time",
+ "description": "End date of the usage report period.",
+ "example": "2026-05-05T00:00:00"
+ },
+ "next_page": {
+ "type": "integer",
+ "nullable": true,
+ "description": "Cursor for the next page of results. Null if there are no further pages.",
+ "example": 2
+ },
+ "usage": {
+ "type": "array",
+ "description": "List of custom tag usage entries.",
+ "items": {
+ "$ref": "#/components/schemas/CustomTagUsageItem"
+ }
+ }
+ }
+ },
+ "CustomTagUsageItem": {
+ "type": "object",
+ "description": "Usage statistics for a specific custom tag.",
+ "properties": {
+ "custom_tag": {
+ "type": "string",
+ "description": "The custom tag identifier.",
+ "example": "example-custom-tag"
+ },
+ "breakdown": {
+ "$ref": "#/components/schemas/CustomTagBreakdown"
+ }
+ }
+ },
+ "CustomTagBreakdown": {
+ "type": "object",
+ "description": "Breakdown of character usage by category for a custom tag.",
+ "properties": {
+ "total_characters": {
+ "type": "integer",
+ "description": "Total number of characters used.",
+ "example": 380
+ },
+ "text_translation_characters": {
+ "type": "integer",
+ "description": "Number of characters used for text translation.",
+ "example": 380
+ },
+ "text_improvement_characters": {
+ "type": "integer",
+ "description": "Number of characters used for text improvement.",
+ "example": 0
+ }
+ }
+ },
"ErrorResponse": {
"type": "object",
"required": [
diff --git a/api-reference/openapi.yaml b/api-reference/openapi.yaml
index 675f7446..107b8561 100644
--- a/api-reference/openapi.yaml
+++ b/api-reference/openapi.yaml
@@ -9,7 +9,7 @@ info:
contact:
name: DeepL - Contact us
url: https://www.deepl.com/contact-us
- version: 3.9.0
+ version: 3.10.0
externalDocs:
description: DeepL Pro - Plans and pricing
url: https://www.deepl.com/pro#developer
@@ -87,6 +87,8 @@ tags:
Use a two-step flow: first request a streaming URL via REST, then establish a WebSocket connection for streaming audio and receiving transcriptions.
- name: VoiceTranslateJob
description: "**Alpha.** Async voice translation jobs. This API may change without notice."
+- name: AdminApi
+ description: Endpoints for organization administrators to manage API keys and retrieve usage analytics.
x-hideTryItPanel: true
x-codeSamples: false
paths:
@@ -205,6 +207,131 @@ paths:
$ref: '#/components/responses/InternalServerError'
security:
- auth_header: [ ]
+ /v2/admin/analytics/custom-tags:
+ get:
+ tags:
+ - AdminApi
+ summary: Get custom tag usage statistics as an admin
+ operationId: adminGetCustomTagAnalytics
+ description: |-
+ Retrieve usage statistics broken down by custom tags within a specified date range.
+ Optionally aggregate results by day or over the entire period.
+ Results are paginated; use the `page` parameter with the `next_page` value from
+ a previous response to retrieve subsequent pages.
+ parameters:
+ - name: start_date
+ in: query
+ required: true
+ description: Start date for the usage report (ISO 8601 date format).
+ schema:
+ type: string
+ format: date
+ example: "2026-05-17"
+ - name: end_date
+ in: query
+ required: true
+ description: End date for the usage report (ISO 8601 date format).
+ schema:
+ type: string
+ format: date
+ example: "2026-05-18"
+ - name: aggregate_by
+ in: query
+ required: false
+ description: |-
+ Optional parameter to control aggregation of usage statistics. Possible values:
+ * `period` - Aggregate usage over the entire date range (default)
+ * `day` - Group usage by individual day
+ schema:
+ type: string
+ enum:
+ - period
+ - day
+ default: period
+ example: "day"
+ - name: page
+ in: query
+ required: false
+ description: |-
+ Page number for pagination. Use the integer value returned in `next_page` from
+ a previous response to retrieve the next page of results.
+ schema:
+ type: integer
+ example: 2
+ responses:
+ 200:
+ description: The custom tag usage statistics for the specified date range.
+ headers:
+ X-Trace-ID:
+ $ref: '#/components/headers/X-Trace-ID'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CustomTagUsageReport'
+ examples:
+ aggregateByPeriod:
+ summary: Usage report aggregated over the full period
+ value:
+ custom_tag_usage_report:
+ aggregate_by: "period"
+ start_date: "2026-05-03T00:00:00"
+ end_date: "2026-05-05T00:00:00"
+ next_page: null
+ usage:
+ - custom_tag: "example-custom-tag"
+ breakdown:
+ total_characters: 380
+ text_translation_characters: 380
+ text_improvement_characters: 0
+ - custom_tag: "example-custom-tag-2"
+ breakdown:
+ total_characters: 475
+ text_translation_characters: 475
+ text_improvement_characters: 0
+ aggregateByDay:
+ summary: Usage report aggregated by day
+ value:
+ custom_tag_usage_report:
+ aggregate_by: "day"
+ start_date: "2026-05-17T00:00:00"
+ end_date: "2026-05-18T00:00:00"
+ next_page: 2
+ usage:
+ - custom_tag: "example-custom-tag"
+ breakdown:
+ total_characters: 190
+ text_translation_characters: 190
+ text_improvement_characters: 0
+ 400:
+ description: Bad request. Please check error message and your parameters.
+ headers:
+ X-Trace-ID:
+ $ref: '#/components/headers/X-Trace-ID'
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ description: Error message describing the issue.
+ examples:
+ dateRangeExceeded:
+ summary: Date range exceeds maximum allowed
+ value:
+ message: "Bad request. Reason: Date range cannot exceed 366 days"
+ invalidAggregateBy:
+ summary: Invalid aggregate_by parameter value
+ value:
+ message: "Value for 'aggregate_by' not supported. Allowed: '', 'period', 'day'."
+ 403:
+ $ref: '#/components/responses/Forbidden'
+ 404:
+ $ref: '#/components/responses/NotFound'
+ 500:
+ $ref: '#/components/responses/InternalServerError'
+ security:
+ - auth_header: [ ]
/v2/admin/developer-keys:
post:
tags:
@@ -5711,6 +5838,69 @@ components:
example: "DeepL API Key Prod"
usage:
$ref: '#/components/schemas/UsageBreakdown'
+ CustomTagUsageReport:
+ type: object
+ description: The response for admin custom tag usage statistics.
+ properties:
+ custom_tag_usage_report:
+ $ref: '#/components/schemas/CustomTagUsageReportData'
+ CustomTagUsageReportData:
+ type: object
+ description: Contains the detailed custom tag usage statistics for the specified date range.
+ properties:
+ aggregate_by:
+ type: string
+ description: The aggregation method used.
+ enum:
+ - period
+ - day
+ example: "period"
+ start_date:
+ type: string
+ format: date-time
+ description: Start date of the usage report period.
+ example: "2026-05-03T00:00:00"
+ end_date:
+ type: string
+ format: date-time
+ description: End date of the usage report period.
+ example: "2026-05-05T00:00:00"
+ next_page:
+ type: integer
+ nullable: true
+ description: Cursor for the next page of results. Null if there are no further pages.
+ example: 2
+ usage:
+ type: array
+ description: List of custom tag usage entries.
+ items:
+ $ref: '#/components/schemas/CustomTagUsageItem'
+ CustomTagUsageItem:
+ type: object
+ description: Usage statistics for a specific custom tag.
+ properties:
+ custom_tag:
+ type: string
+ description: The custom tag identifier.
+ example: "example-custom-tag"
+ breakdown:
+ $ref: '#/components/schemas/CustomTagBreakdown'
+ CustomTagBreakdown:
+ type: object
+ description: Breakdown of character usage by category for a custom tag.
+ properties:
+ total_characters:
+ type: integer
+ description: Total number of characters used.
+ example: 380
+ text_translation_characters:
+ type: integer
+ description: Number of characters used for text translation.
+ example: 380
+ text_improvement_characters:
+ type: integer
+ description: Number of characters used for text improvement.
+ example: 0
ErrorResponse:
type: object
required:
diff --git a/docs.json b/docs.json
index cf0925d2..ab042cb6 100644
--- a/docs.json
+++ b/docs.json
@@ -303,7 +303,8 @@
"group": "Organization Usage Analytics",
"pages": [
"api-reference/admin-api/organization-usage-analytics",
- "api-reference/admin-api/get-usage-analytics"
+ "api-reference/admin-api/get-usage-analytics",
+ "api-reference/admin-api/get-custom-tag-usage-analytics"
],
"drilldown": false
}
diff --git a/docs/resources/roadmap-and-release-notes.mdx b/docs/resources/roadmap-and-release-notes.mdx
index 0480de87..895b8f2a 100644
--- a/docs/resources/roadmap-and-release-notes.mdx
+++ b/docs/resources/roadmap-and-release-notes.mdx
@@ -7,10 +7,15 @@ rss: true
- Support for uploading, modifying, and deleting [translation memories](/docs/learning-how-tos/examples-and-guides/how-to-use-translation-memories) via API
- API key-level endpoint restrictions
-- Usage reporting by custom tag and language pair
+- Usage reporting by language pair
+## 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.
+- 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.
+
## 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.
- **`/v2/languages` and `/v2/glossary-language-pairs` are now deprecated.** Migrate to `/v3/languages`. See the [migration guide](/api-reference/languages/migrate-from-v2-languages) for details.