Translate text
POST https://api.vizvuz.com/v1/translate
The only endpoint you need. It accepts JSON or form encoding and always answers JSON.
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string or array of strings | yes | 1 to 50 texts. A bare string is accepted and treated as an array of one. |
target_lang | string | yes | Target language code, for example DE, EN-GB, PT-BR. Case-insensitive. |
source_lang | string | no | Source language code. Omit it and the engine detects the language. |
formality | string | no | default, more, less, prefer_more or prefer_less. The prefer_ variants apply formality only where the target language supports it, instead of rejecting the request. |
glossary_id | string | no | A glossary you created earlier. Requires source_lang; its language pair must match the request. |
tag_handling | string | no | html or xml. Preserves markup and translates only text nodes. |
preserve_formatting | boolean | no | Keeps leading and trailing whitespace, punctuation and capitalisation as sent. |
context | string | no | Extra context for the engine, up to 2,000 characters. It is not translated and not billed. |
EN is normalised to EN-US and PT to PT-PT. If you care which variant you get, name it explicitly.
Example
curl -X POST https://api.vizvuz.com/v1/translate \
-H "Authorization: Bearer vz_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"text": ["Please confirm the invoice."],
"source_lang": "EN",
"target_lang": "DE",
"formality": "more",
"context": "Business e-mail to a long-standing customer."
}'
{
"translations": [
{ "detected_source_language": "EN", "text": "Bitte bestätigen Sie die Rechnung." }
],
"request_id": "01J8ZC4M9XK3P7QW2NRT5V6YAB",
"characters": 27
}
Response fields
| Field | Description |
|---|---|
translations[].text | The translated text. |
translations[].detected_source_language | The source language, whether you sent it or we detected it. |
request_id | A 26-character ULID. Also in the X-Request-Id header. Quote it in support requests. |
characters | Characters billed for this request. |
The order of translations always matches the order of text.
Response headers
| Header | Meaning |
|---|---|
X-Request-Id | Same value as request_id. |
X-Characters-Billed | Characters charged for this request. |
X-RateLimit-Limit | Requests per second allowed for your plan. |
X-RateLimit-Remaining | Requests left in the current second. |
X-RateLimit-Reset | Seconds until the window resets. |
Cache-Control | Always no-store. |
Form encoding
If JSON is inconvenient, post a form. Repeated text fields become the array:
curl -X POST https://api.vizvuz.com/v1/translate \
-H "Authorization: Bearer vz_live_xxxxxxxx" \
-d "text=Hello" -d "text=World" -d "target_lang=DE"
Limits
| Pay as you go | Starter | Business | |
|---|---|---|---|
| Texts per request | 50 | 50 | 50 |
| Characters per request | 50,000 | 100,000 | 200,000 |
| Requests per second | 10 | 25 | 100 |
Exceeding the character limit answers 400 with text_too_long; more than 50 texts answers 400 with too_many_texts.
How characters are counted
Every Unicode character you send in text counts: letters, spaces, line breaks, punctuation and every character of any HTML or XML markup. context does not count. Counting is done with the same function that bills you, so X-Characters-Billed and your invoice can never disagree.
Timeouts and retries
We retry once internally on a transport failure. If it still fails you get 503 with engine_unavailable and a Retry-After header. Retry with exponential backoff; the request was not billed.
Last updated Sep 1, 2026, 12:00 AM