REST API
Three calls: send a file, wait, download a ZIP. The key goes in the X-API-Key header and is optional.
1. Send the file
curl -X POST https://kaeris.dev/api/translate \ -H "X-API-Key: $KAERIS_API_KEY" \ -F "[email protected]" \ -F "languages=de,ja"
Response
{ "job_id": "3f8a2c1d-…", "edit_token": "…" }
2. Ask until it is done
curl https://kaeris.dev/api/status/3f8a2c1d-…
Response
{ "status": "done", "progress": 2, "total": 2, "error": "",
"current_lang": "ja", "failed_langs": [] }
3. Download
curl -o translations.zip https://kaeris.dev/api/download/3f8a2c1d-…
Result
translations.zip with de.json and ja.json. The download stays available for about an hour after the job finishes.
Fields of POST /api/translate
| Field | Meaning |
|---|---|
file | The language file. Any of the formats listed under the command line. |
languages | Comma-separated codes, for example de,ja. |
verify | true translates every result back, to check the meaning. |
glossary | Comma-separated words to keep as written. |
tone | formal or casual. Empty is neutral. |
icu | true if the strings use ICU plurals like {count, plural, …}. |
app_context | One line about the app, up to 300 characters. |
webhook_url | Team/API plan: an https address we call when the job finishes. Below. |
All endpoints
| Endpoint | What it does |
|---|---|
POST /api/translate | Starts a job, returns job_id. |
GET /api/status/{job_id} | pending, running, done or error, with progress. |
GET /api/preview/{job_id} | The translations and the check results as JSON. |
GET /api/download/{job_id} | The ZIP with one file per language. |
POST /api/v1/keys/request | Issues a free key. No body, no account. |
Webhook when a job finishes
On the Team/API plan, send webhook_url with the job. When it finishes we POST this JSON to it. Your translated text is never in it.
Body
{
"event": "translation.completed",
"job_id": "3f8a2c1d-…",
"status": "done",
"languages": ["de", "ja"],
"failed_languages": [],
"source_chars": 1840,
"download_url": "https://kaeris.dev/api/download/3f8a2c1d-…"
}
Check that it came from us
import hashlib, hmac
# secret: "webhook_secret" from GET /api/key/info (X-API-Key: your key)
def is_from_kaeris(raw_body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body,
hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header or "")
The header X-Kaeris-Signature: sha256=<hex> is an HMAC-SHA256 of the raw body, made with your key's own webhook secret, which is not your API key. Get it as webhook_secret from GET /api/key/info with your key in X-API-Key; it is also in your key email. The address must be https and public; private and local addresses are refused.