Skip to content
NHWe are part of the NETWORKERS HOME Group — Enterprise AI InfrastructurePart of the NETWORKERS HOME GroupVisit Networkers Home →
Ollalink
Get started

Translation and text tools

Which languages are available: GET https://ai.ollalink.com/v1/languages lists them, with what each supports (all hosts).

Base: https://ai.ollalink.com · Auth: X-NH-GPU-Key: <your GPU API key>

POST /v1/translate — send the text and the target language; you get the translation back. The service writes its own translation instructions, so the text is always treated as content to translate — it is a translation endpoint, not a general chat model, and instructions inside the text are translated, not followed. It is always on: a sentence typically comes back in about 1.5–3 s.

Terminal window
curl https://ai.ollalink.com/v1/translate \
-H "X-NH-GPU-Key: $YOUR_GPU_KEY" -H "Content-Type: application/json" \
-d '{"text": "Do not open port 443 before Friday.", "target": "es"}'
{"translation": "No abras el puerto 443 antes del viernes.", "source": null, "target": "es",
"numbers_verified": true, "characters": 35}
Field Required Values
text yes the text to translate, up to 5,000 characters per request
target yes language code: en, hi, es, fr, zh, de, ar, pt (Brazilian Portuguese), ru, ja, ko, it, nl, vi, ta (Tamil — text translation only); any other code (including tr) returns 400 unsupported_language
source no the source language code (same list as target), when you know it; omit it to let the translator work it out (Tamil text is recognised by its script)
stream no true to receive the translation piece by piece while it is written (see Streaming); default false

No other fields are accepted (400). Use your GPU API key from the dashboard — the same key as the Speech GPU services — in X-NH-GPU-Key.

Field Meaning
translation the translated text
numbers_verified true when every number and placeholder in the source also appears in the translation; false means review them
source, target echo of the request (source is null when you omitted it)
characters length of the source text; usage is counted in characters (also in the X-Translate-Chars header)
  • Meaning: negations, commands, questions and conditions are kept as they are (“Do not open port 443” stays a prohibition).
  • Numbers: spoken numbers in the source (“port four forty three”) are turned into digits before translation, and values are kept exactly, written with the target language’s decimal separator.
  • Technical tokens: names, product names, protocol names such as BGP, commands, IP addresses and placeholders ({name}, %d, {{x}}) are kept as written; placeholders are protected during translation.
  • Check: after translating, the service checks that every number and placeholder survived and retries once if one is missing; numbers_verified reports the result.

A successful response and numbers_verified: true do not certify meaning or grammar; review critical text.

For live captions, or anywhere the first words matter more than the whole text: add "stream": true and the translation arrives as Server-Sent Events while it is being written. The first words usually arrive within a second; without streaming you wait for the whole translation.

Terminal window
curl -N https://ai.ollalink.com/v1/translate \
-H "X-NH-GPU-Key: $YOUR_GPU_KEY" -H "Content-Type: application/json" \
-d '{"text": "Open port 443 on VLAN 10 and save the configuration.", "target": "hi", "stream": true}'
data: {"delta": "V"}
data: {"delta": "LAN 10 पर पोर्ट 443"}
data: {"delta": " खोलें और कॉन्फ़िगरेशन सहेजें।"}
data: {"done": true, "translation": "VLAN 10 पर पोर्ट 443 खोलें और कॉन्फ़िगरेशन सहेजें।", "source": null, "target": "hi", "numbers_verified": true, "characters": 52}

The response is Content-Type: text/event-stream. Each event is one data: line holding JSON, followed by a blank line:

Event Meaning
{"delta": "…"} the next piece of the translation; append the pieces in order to show it as it grows
{"done": true, "translation", "numbers_verified", "source", "target", "characters"} the last event: the complete translation (use it as the final text) and the number check
{"error": {"code": "translation_unavailable", "message"}} the translation stopped part-way; discard the pieces and send the request again
import json, requests
with requests.post("https://ai.ollalink.com/v1/translate",
headers={"X-NH-GPU-Key": YOUR_GPU_KEY},
json={"text": "Open port 443 on VLAN 10 and save the configuration.", "target": "hi", "stream": True},
stream=True, timeout=60) as r:
r.raise_for_status()
for line in r.iter_lines(decode_unicode=True):
if not line.startswith("data:"):
continue
event = json.loads(line[5:])
if "delta" in event:
print(event["delta"], end="", flush=True) # show the translation as it grows
elif event.get("done"):
final, verified = event["translation"], event["numbers_verified"]
elif "error" in event:
raise RuntimeError(event["error"]["message"]) # send the request again

How streaming differs from the normal call:

  • No automatic retry. Without streaming, a translation that lost a number or placeholder is retried once before it is returned. With streaming the text is already on its way, so numbers_verified in the done event only reports the check. On false, review the numbers, or send the text again without stream to get the retry.
  • Errors before the stream starts (missing key, bad request, unsupported language, text too long) come back as ordinary JSON responses with the usual status codes. Only failures during translation arrive as an error event.
  • Usage is counted the same way, in source characters (header X-Translate-Chars).
  • Captions: send each caption final as soon as it arrives, and do not wait for the previous translation; requests run in parallel. Show the delta pieces as they come, then replace them with translation from the done event.

Hindi with English numbers and technical terms

Section titled “Hindi with English numbers and technical terms”

Hindi and Hindi–English mixed (Hinglish) text can be translated directly with "target": "en" — for example, a Hinglish instruction comes back as “Do not open port 179 until the configuration is verified.” For live translation of Hindi speech, translate each caption’s final text here. See Hindi with English numbers.

Captions and recordings in another language

Section titled “Captions and recordings in another language”

Transcribe the audio (speech-to-text or live captions — captions arrive in the speaker’s language only), translate the text here, then optionally synthesize it (text-to-speech). Keep the original transcript next to the translation.

Three more routes on https://ai.ollalink.com, same key, usage counted in characters (header X-Translate-Chars), rate limit 600 requests / 60 s per key.

Spoken numbers to digits — POST /v1/normalize {"text", "language": "en" (default) | "hi"} → {"text", "normalized", "changed", "language", "characters"}. For recogniser output: “open port four forty three” → “open port 443”, “two point five seconds” → “2.5 seconds”, “one ninety two dot zero dot two dot one” → “192.0.2.1”, “at two thirty” → “2:30”, “one hundred and five” → “105”; a lone “one” or “two” stays a word (“one of the reasons”). Hindi converts cardinal numbers (“पोर्ट चार सौ तैंतालीस खोलो” → “पोर्ट 443 खोलो”, “उन्नीस सौ तिरसठ” → 1963) and English numbers spelled in Devanagari (“वन सेवेंटी नाइन” → 179); a lone एक or दो stays a word. Up to 5,000 characters. Realtime speech-to-text, live captions and file transcription already apply this to their English text.

Terminal window
curl https://ai.ollalink.com/v1/normalize \
-H "X-NH-GPU-Key: $YOUR_GPU_KEY" -H "Content-Type: application/json" \
-d '{"text": "open port four forty three", "language": "en"}'

Text embeddings — POST /v1/embeddings {"input": "text" | ["text", …] (1–256), "dimensions": 1024 (default and only size; shorter vectors lose accuracy), "mode": "document" (default; what you store and search) | "query" (the search text)} → {"object": "list", "data": [{"index", "embedding": [...]}], "dimensions", "mode", "characters"}. Vectors are unit length, so a dot product is the cosine similarity. 1024-dimension vectors since 17 October 2026 (previously 768 by default): vectors made before that date are not compatible — re-embed stored documents. At most 5,000 characters per text and 50,000 per request.

Classification — POST /v1/classify {"text", "questions": {<id>: …}} with up to 20 questions of three kinds:

Kind Question shape Answer
choice (pick one — the reliable kind) {"type": "choice", "question": "…", "options": {"name": "short description", … (2–10)}} {"type": "choice", "answer": name, "confidence", "probabilities"} — confidence is the probability of the chosen option
yes_no (experimental) {"type": "yes_no", "question": "…"} {"type": "yes_no", "answer": true/false, "probability_yes", "experimental": true}
score (experimental) {"type": "score", "question": "…", "levels": ["lowest", …, "highest"] (2–10)} {"type": "score", "answer": level index, "level", "confidence", "probabilities", "experimental": true} — the most likely level, never an average

The response is {"answers": {<id>: …}, "characters"}. Pick-one is the reliable kind; yes_no and score are experimental. For a yes/no decision, ask a choice with two named options and one-line criteria (“question: it asks something” / “statement: it tells or instructs”). score is best read with its confidence. Up to 5,000 characters. Classification is always on; a busy period answers 503, retry shortly.

Example request:

{"text": "My invoice for October charged me twice. Please refund one payment.",
"questions": {
"team": {"type": "choice", "question": "Which team should handle this?",
"options": {"billing": "money, invoices, refunds", "support": "technical problems", "sales": "buying or upgrading"}},
"refund": {"type": "choice", "question": "Is the customer asking for a refund?",
"options": {"yes": "asks for money back", "no": "does not ask for money back"}},
"urgency": {"type": "score", "question": "How urgent is it?", "levels": ["not urgent", "low", "medium", "high", "critical"]}}}

Answer: {"answers": {"team": {"type": "choice", "answer": "billing", "confidence": 0.89, "probabilities": {…}}, "refund": {…}, "urgency": {"type": "score", "answer": 2, "level": "medium", …, "experimental": true}}, "characters": 66}.

Status error.code Meaning
400 bad_request / unsupported_language missing text, unknown field, body not JSON, a language code not in the list on /v1/translate, or a language other than en / hi on /v1/normalize
401 / 403 unauthorized / not_approved / forbidden unknown key, key not yet approved, or a key without GPU access; a missing key is blocked at the edge with 403
410 gone a route switched off on this host
413 too_long text over the limit (5,000 characters) — split it at sentence ends
503 translation_unavailable / embeddings_unavailable / classification_unavailable translation, embeddings or classification briefly unavailable (or loading); retry shortly

Use Playground → Translate for text, or Live speech → Translate finalized captions for live caption text. The latter composes two documented APIs: caption finals followed by text translation. Original captions remain visible.