Any language via REST API
No SDK for your stack yet? The same translation API the widget and the Apps SDK use is plain HTTPS + JSON. If your language can send a POST request, it can translate with Transable — Python, Go, Rust, Java, PHP, shell scripts, anything.
Authentication
Every request is authenticated with a project API key (tk_live_…) —
create one on your project page.
Pass it either in the JSON body as apiKey, as a
Authorization: Bearer header, or as an
X-Api-Key header. There are no cookies or OAuth flows.
Translate a batch of texts
POST /api/v1/translate/batch translates up to
500 texts per call into one target language. The source language is
detected automatically.
curl https://transable.to/api/v1/translate/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer tk_live_yourKeyHere" \
-d '{
"texts": ["Welcome back!", "Sign out"],
"targetLanguage": "de"
}'
The response echoes each source text with its translation:
{
"translations": [
{ "sourceText": "Welcome back!", "translatedText": "Willkommen zurück!", "served": "ai" },
{ "sourceText": "Sign out", "translatedText": "Abmelden", "served": "cache" }
]
}
The served field tells you how each text was produced:
ai— freshly translated (counts against your AI character quota);cache— served from the server phrase cache (free);original— returned untranslated: the echo path (target = source), the budget governor's cache-only mode, or a pass-through. This lets your client distinguish "refused by budget" from "the translation happens to equal the source".
List enabled languages
GET /api/v1/translate/languages returns your project's source language and every enabled target language (names, native names, flags) — ideal for building your own language picker:
curl "https://transable.to/api/v1/translate/languages?apiKey=tk_live_yourKeyHere"
{
"sourceLanguage": "en",
"languages": [
{ "code": "de", "name": "German", "nativeName": "Deutsch", "flag": "🇩🇪" },
{ "code": "es", "name": "Spanish", "nativeName": "Español", "flag": "🇪🇸" }
]
}
Size and rate limits
413 means one request was too big — the batch's total characters exceeded your plan's
per-request cap (the response includes the exact limit), so split the batch and retry.
429 means you are sending requests too fast or hit a quota — back off for the number of
seconds in the Retry-After header and resend; nothing is lost.
Protocol expectations
A well-behaved client follows the same rules the official SDK does:
- batch aggressively — up to 500 texts per
/batchcall instead of one request per string; - honor
Retry-Afteron 429 and pause the queue instead of hammering; - cache translations client-side and fall back to the original text on any error.
The Avalonia SDK's limits and error behavior documents the reference behavior these expectations come from.
Other status codes
- 400 — malformed request (missing
texts/targetLanguage, or more than 500 texts); - 401 — invalid or revoked API key;
- 402 — no active subscription on the account;
- 403 — target language not enabled for the project, or the request origin is not allowed;
- 502 — transient provider failure: keep the original text and retry later.
Building for Avalonia or WPF instead? The Apps SDK (Avalonia, WPF) handles all of the above for you — batching, caching, retries, and offline startup.