Complete developer guide and best practices to help you get started quickly.
Text translation
Walks through the full text translation flow: one-shot JSON, SSE streaming, and dictionary augmentation.
This tutorial centres on POST /api/v1/translations/text and walks through three scenarios: one-shot JSON translation, SSE streaming, and dictionary-augmented translation. Each scenario ships with a curl example and the gotchas to watch for.
Prepare your API key
Create a key in the developer console and pass it via the X-API-Key HTTP header. The key is displayed only once — keep it in environment variables rather than hard-coding it into source files or frontend bundles.
Store the key in an environment variable; the examples below all read $ABESTAR_API_KEY.
export ABESTAR_API_KEY="sk_live_..."Scenario 1: one-shot JSON translation
By default stream=false waits for the model to finish and returns the full result in one response, which suits short text and downstream processing. The input limit is 5000 characters; exceeding it returns 400 validation_error.
curl example in JSON mode.
curl -X POST "https://abemono.abestar.com.tw/api/v1/translations/text" \ -H "X-API-Key: $ABESTAR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "今天的會議改到下午三點。", "target_language": "en", "source_language": "auto" }'
The response includes the translated text, the auto-detected source language (null if you specified one), the cumulative quota usage percentage (usage.quota_percent.used, 0–100), and the number of forced replacements actually applied.
Successful response example (HTTP 200).
{
"translated_text": "Today's meeting is rescheduled to 3 PM.",
"detected_source_lang": "zh-TW",
"usage": {
"quota_percent": {
"used": 12
}
},
"forced_replacement_count": 0
}Optional feature parameters
All parameters below are optional and can be combined freely with either JSON or SSE mode; omitted fields fall back to their defaults. The speech recognition endpoint accepts the same shared parameters — both chapters deliberately use identical table columns and ordering so you can compare them side by side.
| Parameter | Type | Default | Description |
|---|---|---|---|
| model | string | "PSSC-V1-251215" | Translation model code. Use GET /translations/models to list what is currently available. |
| domain | string | "general" | Domain hint such as "legal", "medical", or "gaming", helping the model pick wording that fits the field. |
| context | { speech: string }[] | [] | Conversation context or prior turns in chronological order, so pronouns and omitted subjects translate more accurately. |
| harm_content_filter | boolean | false | Enables harmful-content filtering. Blocked input returns 400 content_policy_violation. |
| punctuation | boolean | false | Auto-completes punctuation in the translation. Note the speech endpoint defaults the same parameter to true — the two differ. |
| number_format | "spoken" | "arabic" | "spoken" | Number transcription: spoken writes numbers out in words, arabic uses digits (1234). |
| date_format | "natural" | "yyyy-MM-dd" | "yyyy/MM/dd" | "MM/dd/yyyy" | "dd-MM-yyyy" | "natural" | Date presentation: natural follows the target language's convention; the rest are fixed templates. |
| source_language | string | "auto" | Translation-only. Source language code, or leave as auto to let the model detect it. |
A complete example combining the domain hint, conversation context, auto punctuation, number transcription, and date format.
curl -X POST "https://abemono.abestar.com.tw/api/v1/translations/text" \ -H "X-API-Key: $ABESTAR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "上一季營收成長了一成二,下次會議訂在二〇二六年三月五日。", "target_language": "en", "domain": "finance", "context": [{ "speech": "我們今天先討論第一季的營收。" }], "punctuation": true, "number_format": "arabic", "date_format": "yyyy-MM-dd", "harm_content_filter": true }'
Scenario 2: SSE streaming
Conversational UIs and long inputs work better with stream=true, which streams partial output as it arrives. The response is text/event-stream and events flow as head (source language) → chunk* (text fragments, zero or more) → tail (end marker) → meta (usage stats). On failure, an error event replaces remaining events and closes the stream.
curl example in SSE mode. -N disables curl buffering so events stream out immediately.
curl -N -X POST "https://abemono.abestar.com.tw/api/v1/translations/text" \ -H "X-API-Key: $ABESTAR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "今天的會議改到下午三點。", "target_language": "en", "stream": true }'
SSE parser example using fetch + ReadableStream + TextDecoder. Events are separated by a blank line.
const res = await fetch("https://abemono.abestar.com.tw/api/v1/translations/text", { method: "POST", headers: { "X-API-Key": process.env.ABESTAR_API_KEY, "Content-Type": "application/json", Accept: "text/event-stream", }, body: JSON.stringify({ text: "今天的會議改到下午三點。", target_language: "en", stream: true, }), }); const reader = res.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; let output = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const events = buffer.split("\n\n"); buffer = events.pop() ?? ""; for (const evt of events) { const line = evt.split("\n").find((l) => l.startsWith("data: ")); if (!line) continue; const payload = JSON.parse(line.slice(6)); switch (payload.type) { case "head": console.log("source:", payload.data.source_lang); break; case "chunk": output += payload.data; break; case "tail": console.log("done:", output); break; case "meta": console.log("usage:", payload.data.usage); break; case "error": console.error(payload.data.code, payload.data.message); break; } } }
SSE business errors still come back with HTTP 200
Scenario 3: with dictionaries
The translation endpoint accepts two dictionary kinds: vocabulary acts as soft guidance — matching terms are passed to the model as preferred wording — while forced_replacement performs string substitutions on the final output after translation. Both are referenced by UUID via vocabulary_dictionary_id / forced_replacement_dictionary_id.
Both dictionaries can be attached in JSON mode.
curl -X POST "https://abemono.abestar.com.tw/api/v1/translations/text" \ -H "X-API-Key: $ABESTAR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "請把這份合約交給法務組長確認。", "target_language": "en", "vocabulary_dictionary_id": "f3c1e9a2-9c2b-4f7a-9d3a-7e2b8a1c4d5e", "forced_replacement_dictionary_id": "1d2e3f4a-5b6c-7d8e-9f0a-1b2c3d4e5f6a" }'

