Skip to main content

Translation API

The translate endpoint translates text into a target language you name — as an ISO 639 code ("fr", "zh-TW") or an English language name ("French") — using a large language model. Line breaks, markup and placeholders (HTML tags, {braces}, URLs, email addresses, code) are preserved in place, so translated content drops back into your templates and documents unchanged.

The response reports the language the text was actually written in (detected from the text, never assumed from your hint) alongside the translation, and an optional formality parameter picks a formal or informal register where the target language distinguishes them (vous/tu, Sie/du, usted/tú).

Around 170 languages are supported as source and target, plus region variants as targets: zh-CN / zh-TW / zh-HK, pt-BR / pt-PT, en-GB / en-US, fr-CA and es-419. To only identify a language, see the language detection endpoint.

Sample Code​

curl -X POST https://api.sapling.ai/api/v1/translate \
-H "Content-Type: application/json" \
-d '{"key":"<api-key>", "text":"Hello world.\nSee you at 5pm — bring the report.", "target_lang": "fr"}'

Sample Response​

{
"translation": "Bonjour le monde.\nÀ 17h — apportez le rapport.",
"source_lang": "en",
"source_lang_name": "English",
"target_lang": "fr",
"target_lang_name": "French"
}

Batch Requests​

To translate many short, independent strings in one request, such as UI labels, product titles or a queue of support replies, send texts (a list of 1–10 strings) instead of text.

  • The same target_lang, source_lang and formality apply to every item.
  • The combined length of all items may be up to 5,000 characters, the same cap as a single text.
  • Provide exactly one of text and texts.
curl -X POST https://api.sapling.ai/api/v1/translate \
-H "Content-Type: application/json" \
-d '{"key":"<api-key>", "texts": ["Add to cart", "Your order has shipped."], "target_lang": "de", "formality": "formal"}'

The batch response is {"results": [...]} with one entry per input, in input order. Each entry has exactly the single-response shape above, including its own detected source_lang, so a batch may mix source languages:

{
"results": [
{
"translation": "In den Warenkorb",
"source_lang": "en",
"source_lang_name": "English",
"target_lang": "de",
"target_lang_name": "German"
},
{
"translation": "Ihre Bestellung wurde versandt.",
"source_lang": "en",
"source_lang_name": "English",
"target_lang": "de",
"target_lang_name": "German"
}
]
}

Context. Each item is translated independently, with no shared context between items. Send related sentences of one document as a single text so the model can use the surrounding context.

Billing and caching. Items are billed individually, so a batch of N costs the same as N single requests. Repeated identical items in one batch are translated and billed once, though each repeat still counts toward a free trial's daily character cap. Each item is cached the same way as a single request, so batches and single calls share the cache.

Failures. An empty or whitespace-only item returns a 400 naming its index. If any item fails to translate, the whole request returns a 502 and nothing is billed. The items that did succeed are already cached, so a retry only re-runs the failures.

The Sapling JavaScript client's translate() accepts an array of strings for the batch form.

Request Parameters​

POST to https://api.sapling.ai/api/v1/translate

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

text: String
The text to translate, up to 5,000 characters. Unlike Sapling's analysis endpoints, the text is not HTML-stripped or whitespace-normalized — the translation is the product, so markup and line structure are sent to the model and preserved in place. Text that is empty or whitespace-only returns a 400. The text is treated as untrusted data: instructions inside it are translated, not followed. Provide exactly one of text and texts.

texts: List[String]
Batch form (see Batch Requests): 1–10 texts to translate in one request. Each is treated exactly like text above, and their combined length may be up to 5,000 characters. The response becomes {"results": [...]}, one entry per item in input order.

target_lang: String
The language to translate into: an ISO 639 code ("fr", "de", "ja"; ISO 639-2/3 codes such as "ceb" for languages without a two-letter code) or an English language name ("French"). Case and _/- separators are tolerated ("pt_BR" works). Region variants supported as targets: zh-CN (Simplified Chinese), zh-TW (Traditional Chinese), zh-HK (Traditional Chinese, Hong Kong), pt-BR / pt-PT, en-GB / en-US, fr-CA and es-419 (Latin American Spanish). An unrecognized language returns a 400 naming the accepted forms.

source_lang: String, optional
A hint for the language the text is written in, same forms as target_lang. It steers ambiguous, very short inputs but never overrides the text: the response's source_lang is what was detected.

formality: String, optional
"formal" (polite address forms: vous / Sie / usted, formal honorifics) or "informal" (familiar forms: tu / du / tú). Omit for the model's default register. Other values return a 400.

Response Parameters​

translation: String
The complete translated text, with line breaks, markup and placeholders preserved in place. Content already in the target language is kept as written.

source_lang: String
Detected source language code, normalized to the same vocabulary the request accepts. "und" (undetermined) in the rare case the detection cannot be mapped — the translation itself is still returned.

source_lang_name: String | null
English name of the detected source language; null when source_lang is "und".

target_lang / target_lang_name: String
The normalized target: {"target_lang": "fr", "target_lang_name": "French"} whether you sent "fr", "FR" or "French". Match your application logic on these normalized values.

Errors​

StatusMeaning
400Validation error — missing/oversized/empty text (or an empty texts item, named by index, or a combined texts length over 5,000 characters), both or neither of text/texts, an unrecognized target_lang/source_lang (e.g. {"msg": "Invalid target_lang: Unknown language: \"Klingon\". Send an ISO 639 code (\"fr\", \"zh-TW\") or an English language name (\"French\")."}) or a bad formality. The body is {"msg": "..."}.
401 / 403Missing or invalid API key.
429Rate limit exceeded or key over capacity.
502{"msg": "Unexpected error translating text."} — the translation model failed; safe to retry. Not billed, and the failed text is not cached. In a batch, any items that did translate are still cached, so a retry only re-runs the failures.

Tips​

  • Send as much context as fits, not fragments. The model uses surrounding sentences to resolve pronouns, terminology and register, so translating whole paragraphs beats sentence-by-sentence. Stay within the 5,000-character text limit — for longer documents, split on paragraph or section boundaries and translate each chunk, rather than sending isolated sentences.
  • Name the variant when it matters. zh lets the model pick a script; zh-TW pins Traditional Chinese. Likewise pt-BR vs pt-PT and en-GB vs en-US for spelling conventions.
  • Set formality for customer-facing content in languages with a T–V distinction (French, German, Spanish, Japanese honorifics) — the default register is the model's judgment call.
  • Mixed-language input is fine: the detected source_lang is the dominant language, and content already in the target language is left as written.
  • Results are cached on Sapling's side for about three days, keyed on the text, target, source hint and formality — repeat requests are fast and not double-billed within the usage dedup window.