Skip to content

Commit eadb036

Browse files
shirgoldbirdclaude
authored andcommitted
docs: redirect /pricing and close the remaining agentic-readiness gaps
Adds the /pricing redirect to deepl.com/pricing and works through the Is Agentic audit findings, keeping only the ones this repo can actually change. Two of the previous round's fixes turned out to be dead config. `head` is not a property of Mintlify's docs.json (the schema sets additionalProperties: false), so the Organization JSON-LD it carried never reached the rendered HTML: the live page has no contactPoint and no address anywhere in it. The root .css and .js files it referenced are auto-injected by Mintlify from the repo root, so they are unaffected. Removed `head` and enriched seo.organization instead, which is the only structured-data hook Mintlify exposes. It has no field for contactPoint or address, so that gap now needs Mintlify, not this repo. - New /AGENTS.md, served at /AGENTS.md and /AGENTS, with the when-to-use guidance the audit asked for: which job maps to which endpoint, when to reach for something else, base URLs, auth, the spec URLs, the error contract, and throttling. Also linked from the 404 page and from the markdown instructions - markdown.instructions, which Mintlify prepends to every page served as markdown, gains a "do not use it for" line, the RFC 9727 catalog, and the rate-limit conventions - Documented the response headers the API actually sends on errors: X-Trace-ID on all 22 error response components, Retry-After on the rate-limit response that every 429 and 529 uses, plus a table on the error handling page. Verified against api.deepl.com, which returns X-Trace-ID and a JSON body with a resolution link on a 403 - Surfaced docs/getting-started/auth in the navigation. Every DeepL API auth error links to it, but with seo.indexing "navigable" a page outside the navigation is left out of the sitemap and llms.txt, so agents could not discover the page the error told them to read - Short /openapi, /asyncapi and /agents redirects. The existing /openapi.json and /api/openapi.yaml redirects 404 in production because Mintlify routes any path with a file extension as an asset and never applies redirects to it - Flattened the two redirect chains, so no redirect points at another redirect Tests: scripts/agentic-readiness.test.mjs guards docs.json against unrecognized properties, redirect chains and dead destinations, the AGENTS.md sections and links, and the OpenAPI tool-definition and error-header invariants. The test workflow now runs on docs.json, AGENTS.md and the spec, not just scripts/. Verified: 28 tests pass, docs.json validates against mintlify.com/docs.json except two pre-existing deviations, openapi.json regenerates from the YAML byte-identically, /pricing and /openapi redirect correctly under `mint dev`, the custom CSS and JS are still injected, and `mint broken-links --check-anchors` reports the same 44 findings as main, all in pipeline/drafts or pre-existing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a1c2cd9 commit eadb036

7 files changed

Lines changed: 615 additions & 37 deletions

File tree

‎.github/workflows/test-scripts.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ on:
55
paths:
66
- "scripts/**"
77
- "pipeline/**"
8+
- "docs.json"
9+
- "AGENTS.md"
10+
- "api-reference/openapi.yaml"
11+
- "api-reference/openapi.json"
812
push:
913
branches:
1014
- main
1115
paths:
1216
- "scripts/**"
1317
- "pipeline/**"
18+
- "docs.json"
19+
- "AGENTS.md"
20+
- "api-reference/openapi.yaml"
21+
- "api-reference/openapi.json"
1422

1523
jobs:
1624
test:

‎AGENTS.md‎

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
title: "DeepL API instructions for AI agents"
3+
description: "When to call the DeepL API, which endpoint does which job, how to authenticate, and how to handle its errors and rate limiting."
4+
---
5+
6+
DeepL SE builds Language AI products. This file tells an agent when to call the DeepL API, how to
7+
authenticate, where the machine-readable specs are, and how to handle errors and throttling.
8+
9+
- Documentation: https://developers.deepl.com
10+
- Page index for agents: [/llms.txt](https://developers.deepl.com/llms.txt), or
11+
[/llms-full.txt](https://developers.deepl.com/llms-full.txt) for the full text of every page
12+
- Any documentation page is available as Markdown: append `.md` to its path, or request it with
13+
`Accept: text/markdown`
14+
15+
## When to use the DeepL API
16+
17+
Call the DeepL API when a task needs one of these jobs.
18+
19+
| **Job** | **Endpoint** | **Reference** |
20+
| --- | --- | --- |
21+
| Translate text strings between languages | `POST /v2/translate` | [Request translation](https://developers.deepl.com/api-reference/translate/request-translation) |
22+
| Translate a whole document and keep its formatting (`.docx`, `.pptx`, `.xlsx`, `.pdf`, `.html`, `.xliff`, `.srt`, and more) | `POST /v2/document` | [Document translation](https://developers.deepl.com/api-reference/document/upload-and-translate-a-document) |
23+
| Transcribe speech and translate it while someone is speaking | `POST /v3/voice/realtime`, then stream over the returned WebSocket URL | [Voice API](https://developers.deepl.com/docs/voice/overview) |
24+
| Transcribe and translate a recorded audio file | `POST /v1/jobs/voice/translate` | [Translate an audio file](https://developers.deepl.com/api-reference/jobs-voice-translate/create-voice-translate-job) |
25+
| Rewrite text in the same language: fix grammar, change tone, shorten or expand it | `POST /v2/write/rephrase`, `POST /v2/write/correct` | [Write API](https://developers.deepl.com/api-reference/improve-text/request-text-improvement) |
26+
| Enforce specific terminology in a translation | `POST /v3/glossaries`, then pass the glossary ID | [Glossaries](https://developers.deepl.com/docs/customize/managing-glossaries) |
27+
| Apply a house style, tone, or writing convention | `POST /v3/style_rules`, then pass the style ID | [Style rules](https://developers.deepl.com/docs/customize/using-style-rules) |
28+
| Reuse translations a human has already approved | `POST /v3/translation_memories/import` | [Translation memories](https://developers.deepl.com/docs/customize/using-translation-memories) |
29+
| Find out which languages and features are available before translating | `GET /v3/languages` | [Using the Languages API](https://developers.deepl.com/docs/languages/using-the-languages-api) |
30+
| Check how much of an account's quota is used | `GET /v2/usage` | [Usage and quota](https://developers.deepl.com/api-reference/usage-and-quota/check-usage-and-limits) |
31+
| Create, label, or limit API keys across an organization | `/v2/admin/*` | [Admin API](https://developers.deepl.com/docs/admin/overview) |
32+
33+
Retrieve the list of supported languages from `/v3/languages` rather than hard-coding it. Language
34+
support changes, and it differs per resource: a language available for text translation is not
35+
necessarily available for speech.
36+
37+
### When to use something else
38+
39+
The DeepL API transforms text you supply. It does not generate new content, so send a request
40+
somewhere else when the task is to write, summarize, answer, or classify.
41+
42+
To translate inside a chat session rather than from code, use an MCP server instead of writing HTTP
43+
calls yourself:
44+
45+
- [DeepL MCP Server](https://developers.deepl.com/docs/getting-started/deepl-mcp-server) exposes
46+
translation, text improvement, and glossaries as tools
47+
- [Docs MCP Server](https://developers.deepl.com/docs/getting-started/docs-mcp-server) at
48+
`https://developers.deepl.com/mcp` (Streamable HTTP, no authentication) searches and reads this
49+
documentation
50+
51+
## Base URLs and authentication
52+
53+
| **Plan** | **Base URL** |
54+
| --- | --- |
55+
| DeepL API Pro | `https://api.deepl.com` |
56+
| DeepL API Free | `https://api-free.deepl.com` |
57+
58+
Free API keys end in `:fx`. Use the base URL that matches the key, since a Pro key does not work
59+
against the Free host or the other way around. [Regional
60+
endpoints](https://developers.deepl.com/docs/getting-started/regional-endpoints) are available for
61+
accounts that need data residency in a specific region.
62+
63+
Authenticate every request with a header:
64+
65+
```http
66+
Authorization: DeepL-Auth-Key <api-key>
67+
```
68+
69+
Never fabricate or guess an API key. Ask the user for one, or point them at the
70+
[Quickstart](https://developers.deepl.com/docs/getting-started/quickstart). Keys belong in an
71+
environment variable or a secret store, never in client-side code or a committed file.
72+
73+
## Machine-readable API surface
74+
75+
Read the specification instead of inferring request shapes from prose.
76+
77+
| **Artifact** | **URL** |
78+
| --- | --- |
79+
| OpenAPI 3.0 specification (REST), YAML | https://developers.deepl.com/api-reference/openapi.yaml |
80+
| OpenAPI 3.0 specification (REST), JSON | https://developers.deepl.com/api-reference/openapi.json |
81+
| AsyncAPI specification (Voice WebSocket), YAML | https://developers.deepl.com/api-reference/voice/voice.asyncapi.yaml |
82+
| AsyncAPI specification (Voice WebSocket), JSON | https://developers.deepl.com/api-reference/voice/voice.asyncapi.json |
83+
| API catalog ([RFC 9727](https://www.rfc-editor.org/rfc/rfc9727.html)) | https://developers.deepl.com/.well-known/api-catalog |
84+
85+
Every operation in the OpenAPI specification carries a unique `operationId`, a summary, a
86+
description, typed request and response schemas, and typed error responses, so it can be converted
87+
into function or tool definitions without hand-editing.
88+
89+
## Error handling
90+
91+
Every error carries a standard HTTP status code and a JSON body. Branch on the status code first,
92+
then read the body. Full detail is in [Error
93+
handling](https://developers.deepl.com/docs/best-practices/error-handling).
94+
95+
Application errors put the message at the top level, and add a machine-readable `code` where one is
96+
available:
97+
98+
```json
99+
{
100+
"message": "Value for 'target_lang' not supported."
101+
}
102+
```
103+
104+
Failures in DeepL's edge infrastructure, before a request reaches the API, nest the message under
105+
`error` instead:
106+
107+
```json
108+
{
109+
"error": {
110+
"message": "Bad Gateway."
111+
}
112+
}
113+
```
114+
115+
Reading `body.message ?? body.error?.message` covers both shapes. Match on `code` or the status
116+
code, never on `message`, which is written for humans and can change wording.
117+
118+
| **Status** | **Meaning** | **What to do** |
119+
| --- | --- | --- |
120+
| `400` | The request itself is invalid | Fix the request. Do not retry |
121+
| `403` | Authentication failed, or the key lacks the permission scope for this endpoint | Check the key and its scopes. Do not retry |
122+
| `404` | The resource does not exist, or a document was already downloaded | Do not retry |
123+
| `413` | The request is over the size limit | Split the payload. Do not retry |
124+
| `429`, `529` | Too many requests in a short period | Retry with exponential backoff |
125+
| `456` | The account quota is exhausted | Stop. Retrying cannot succeed until the quota is raised or the period resets |
126+
| `500`, `503`, `504` | Temporary error in DeepL services | Retry with exponential backoff |
127+
128+
Every response, including every error, carries an `X-Trace-ID` header that identifies the request in
129+
DeepL's logs. Log it by default and include it in support requests.
130+
131+
## Rate limits and throttling
132+
133+
The service adjusts to the load on the system, so there is no fixed requests-per-second figure to
134+
code against, and no `RateLimit` response headers to read. Throttle from the responses you get:
135+
136+
- Retry `429` and `529` with exponential backoff and jitter
137+
- Honor the `Retry-After` header, in seconds, when a response includes one, in preference to your own
138+
backoff interval
139+
- Cap how many requests you have in flight, and lower that cap while `429` responses continue
140+
- Batch multiple strings into one `POST /v2/translate` call instead of one request per string,
141+
staying inside the 128 KiB request size limit
142+
- Treat `456` as a stop condition, and poll `GET /v2/usage` to see how close an account is to its
143+
quota before you get there
144+
145+
## Contact
146+
147+
| **Purpose** | **Where** |
148+
| --- | --- |
149+
| API support and contact options | [Contact](https://developers.deepl.com/docs/resources/contact) |
150+
| API status and incidents | https://status.deepl.com/?tab=api |
151+
| Security reports | security@deepl.com ([policy](https://developers.deepl.com/SECURITY.md)) |
152+
| Privacy and data handling | [Privacy](https://developers.deepl.com/docs/resources/privacy) |
153+
| Plans and pricing | https://www.deepl.com/pricing |
154+
155+
DeepL SE, Maarweg 165, 50825 Cologne, Germany.

0 commit comments

Comments
 (0)