Translating Text and Subtitles
This guide translates text and WebVTT subtitles with the translation API. It runs on GPUs, supports 200 languages and costs $1 per million characters per target language. Only finished translations are charged.
Base URL: https://api.mamutecloud.com. Every call uses your organization API key in the Authorization header, without Bearer:
Authorization: mamute-...
Before you start
- Create an API key (see Authentication) and store it as
MAMUTECLOUD_API_KEY. - Translation is paid from your paid balance or with auto-recharge. The free signup credit does not apply. Check what is available with
GET /v1/translations/balance.
1. Translate text
curl -X POST https://api.mamutecloud.com/v1/translations \
-H "Authorization: $MAMUTECLOUD_API_KEY" \
-H "content-type: application/json" \
-d '{"text": "Olá, tudo bem? Hoje vamos falar de vendas.", "source": "pt", "targets": ["en", "es"]}'The call waits up to about 20 seconds:
- 200 with
"status": "done": the translations are already in the response. - 202 with
"status": "queued"or"processing": keep theidand read the result later (step 4), or use a webhook (step 5).
Add ?wait=false to always answer at once.
Line breaks are kept: each line comes back as one line, translated sentence by sentence. Up to 500,000 characters per request.
2. Translate subtitles
Send a WebVTT file as vtt. The result is WebVTT with the same cues and the same timings:
curl -X POST https://api.mamutecloud.com/v1/translations \
-H "Authorization: $MAMUTECLOUD_API_KEY" \
-H "content-type: application/json" \
-d "$(jq -n --rawfile vtt class-01.vtt '{vtt: $vtt, source: "pt", targets: ["en"]}')"- Cues that split a sentence are translated together, and the translated text is spread back over them in proportion to the original, cutting between words.
- Voice and style tags (
<v Ana>,<i>) are not kept; translated cues are plain text. - Up to 1,000,000 characters of WebVTT per request.
3. Or translate a transcript you already made
Pass the id of a finished transcript from the transcription API. The source language comes from the transcript and the result is WebVTT:
curl -X POST https://api.mamutecloud.com/v1/translations \
-H "Authorization: $MAMUTECLOUD_API_KEY" \
-H "content-type: application/json" \
-d '{"transcriptId": "6c0338e1-4d91-41ae-9735-e678d0df36a4", "targets": ["en", "es"]}'The transcript must belong to your organization and still be available (7 days after it ended).
4. Read the result
curl https://api.mamutecloud.com/v1/translations/$TRANSLATION_ID \
-H "Authorization: $MAMUTECLOUD_API_KEY"{
"data": {
"id": "b1a50bd9-e409-4874-8882-f26f57a51fb7",
"status": "done",
"format": "text",
"source": "pt",
"targets": ["en", "es"],
"characters": 102,
"billedCharacters": 204,
"translations": [
{ "language": "en", "format": "text", "content": "Hey, you all right? Today we're going to talk about sales.", "url": "https://..." },
{ "language": "es", "format": "text", "content": "¿Qué pasa? Hoy hablaremos de ventas.", "url": "https://..." }
],
"expiresAt": "2026-10-21T19:16:24.023Z"
}
}contentcomes inline while all translations together are up to 4 MB;urlis always there.urlis signed for 1 hour. Ask again for fresh links.- Results are deleted 7 days after the translation ends (
expiresAt). Text is never used to train models.
5. Get notified with a webhook
Send webhookUrl when you create the translation. When it ends, MamuteCloud sends a POST to it:
{ "data": { "id": "b1a50bd9-...", "status": "done" } }A delivery that fails is retried up to 7 more times over about 7 hours and 40 minutes. Each request carries the attempt number in the X-Mamute-Webhook-Attempt header. Fetch the full result with GET /v1/translations/{id} when it arrives.
Languages
Use ISO 639-1 codes such as pt, en or es (pt-BR is read as pt, zh-TW as Traditional Chinese), or any of the 202 FLORES-200 codes of the model, such as por_Latn. GET /v1/translations/languages lists every accepted code.
sourceis required fortextandvtt.- Up to 10
targetsper request, none equal to the source.
Quality is measured on a public test set, on Portuguese, English and Spanish among others. See Translation Quality for the numbers and the method.
Pricing and balance
| Price | $1 per million characters ($0.000001 per character) |
| Unit | each character of the source text, once per target language |
| Charged when | the translation is done; failed translations cost nothing |
| Pays with | paid balance or auto-recharge (not the signup credit) |
Characters are counted on the source: spaces count, and in WebVTT only the cue text counts, not timings or tags. billedCharacters is characters times the number of targets. An hour of speech has about 54,000 characters, so subtitling it into one language costs about $0.05.
Before the translation runs, its price is held from your balance. If the balance cannot cover it, the translation ends in error with a message starting with insufficient_balance: and nothing is charged. Without any paid balance or auto-recharge, POST /v1/translations answers 402.
curl https://api.mamutecloud.com/v1/translations/balance -H "Authorization: $MAMUTECLOUD_API_KEY"
# -> { "data": { "totalUsd": 27.98, "reservedUsd": 0.0002, "availableUsd": 27.9798, "autoRecharge": true } }List and monitor
# Newest first; page with ?before=<nextBefore>
curl "https://api.mamutecloud.com/v1/translations?status=failed&limit=50" -H "Authorization: $MAMUTECLOUD_API_KEY"
# This month's characters, requests and spend, characters per day, and health
curl "https://api.mamutecloud.com/v1/translations/analytics?days=30" -H "Authorization: $MAMUTECLOUD_API_KEY"Errors
| Status | When |
|---|---|
| 400 | invalid body: none or more than one of text/vtt/transcriptId, missing source, unknown language, a target equal to the source, more than 10 targets, input over the limit |
| 401 | missing or invalid API key (remember: no Bearer before mamute-) |
| 402 | no paid balance and no auto-recharge |
| 404 | the translation (or the transcript) does not belong to your organization |
Timing
A short text comes back in a few seconds, and an hour of subtitles in about 10 seconds per target language. When nobody has translated anything for an hour the GPUs are turned off, so the first request after a quiet period waits about 5 extra minutes while they start.
Known limits
- No glossary. Names and terms that must not be translated cannot be pinned yet.
- Japanese and Chinese are weaker than the European languages (see Translation Quality).
Full reference: Translation API.
Updated 2 days ago
