MXO APIDashboard

MXO Translation API v1

Translate plain text, HTML and Markdown. Every completed translation is charged to your organization's balance. Failed translations are never charged.

Authentication

Create a key in the dashboard under API keys and send it with every request. Keep keys on your server.

Authorization: Bearer mxo_…

Models and prices

ModelBest forUSD per million characters
t3-flashFastest$10
t3Lowest price, good quality$4
t3-proBest quality$100

Only translatable characters count: HTML tags, Markdown syntax, link targets and placeholders such as {name} are free. Each request is billed at least 20 characters. The Free plan can use t3 into zh, hi, es, ar, en, bn, pt, ur, ru and ja.

POST /v1/translate

curl https://api.mxo.ai/v1/translate \
  -H "Authorization: Bearer $MXO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1234-fi" \
  -d '{"text": "Save your work before clicking <b>Restart</b>.", "to": "fi", "model": "t3"}'
FieldTypeNotes
textstringRequired. Plain text, HTML or Markdown; the layout is kept exactly.
tostringRequired. ISO code: fi, de, pt-br, zh-tw. Names such as “Finnish” are not accepted.
fromstringSource ISO code. Detected when omitted.
modelstringt3 (default), t3-flash or t3-pro. Flash and Pro need a paid plan.
tone1–101 = casual, 5 = neutral (default), 7 = formal, 10 = legal.
contextstringUp to 300 characters of facts that clarify meaning, e.g. “The person is Liisa, a woman.” Not translated.
glossaryobjectFixed term translations, e.g. {"dashboard": "kojelauta"}.
content_typestringplain, html, markdown, or ui/legal for single short strings. Detected when omitted.

Response:

{
  "id": "5b1e…",
  "text": "Tallenna työsi ennen kuin napsautat <b>Käynnistä uudelleen</b>.",
  "model": "t3", "from": null, "to": "fi", "content_type": "html",
  "characters": 37, "billable_characters": 37, "charged_usd": 0.000148,
  "warnings": [],
  "balance": { "plan": "free", "available_usd": 0.099852, "advance_usd": 0, … }
}

Idempotency: send an Idempotency-Key header to retry safely. A repeated key returns the first result for 24 hours and is never charged twice.

POST /v1/quote

Same body as /v1/translate. Returns the billable characters and price without translating or charging.

GET /v1/balance · GET /v1/usage

Your current balance, and this month's usage by model.

POST /v1/documents

Translate a PDF, Word (.docx), Markdown, text or HTML file (up to 20 MB). PDFs keep their original page layout, images and links. The job runs in the background; you are charged once, when the translated file is ready.

curl https://account.mxo.ai/v1/documents \
  -H "Authorization: Bearer $MXO_KEY" \
  -F file=@guide.pdf -F to=fi -F model=t3

# → 202 {"id": "…", "status": "queued", …}
curl https://account.mxo.ai/v1/documents/ID -H "Authorization: Bearer $MXO_KEY"
curl -o guide.fi.pdf https://account.mxo.ai/v1/documents/ID/download -H "Authorization: Bearer $MXO_KEY"

Status goes queued → extracting → translating → completed (or failed, never charged). Optional fields: from, tone, context, glossary (JSON).

Websites

GET/POST /v1/websites, GET/PATCH/DELETE /v1/websites/{id}. Fields: name, mode (proxy or self_hosted), origin, proxy_host, source_locale, target_locales (in rollout order), model, rollout (all or gradual: 3 new languages every week). Pages are translated automatically when they are first seen or change, and served under /{language}/….

Data retention: ZDR or cached

Every /v1/translate request and document upload can set "retention": "zdr" or "cache". Without it, the organization default applies (Settings → Data retention; ZDR unless changed).

Website translation always uses cached state, because published pages, links and sitemaps must be stored.

Balance rules

Errors

StatusCodeMeaning
400invalid_request, unknown_model, no_translatable_textFix the request.
401unauthorizedMissing or revoked API key.
402insufficient_balance, advance_limitNot enough balance. The error includes price_usd and balance.
403model_not_in_plan, language_not_in_plan, account_blockedYour plan doesn't allow this request.
409 / 422request_in_progress, idempotency_key_reusedIdempotency-Key conflicts.
413text_too_largeSplit the text into smaller requests.
429rate_limitedSlow down and retry.
502translation_failedThe translation failed quality checks. You were not charged; retry.
{ "error": { "code": "insufficient_balance", "message": "Not enough balance for this translation.", "price_usd": 0.12, "balance": { … } } }