API reference

Tento dokument odpovídá chování Express aplikace v api/app.js a zpracovatelům tras v api/routes/.

Limity a chování

PoložkaHodnota
Velikost JSON těla2 MB (express.json({ limit: '2mb' }))
Cíle na požadavek1–36 jazykových kódů
Položky dávky1–100 položek na dávkový požadavek
Modelystandard (výchozí) nebo advanced (pouze placené úrovně; viz níže)

Měsíční limit tokenů (bezplatná úroveň): Před voláním modelu API odhaduje tokeny přibližně jako ceil(content_length / 4) × (number_of_targets + 1) a pouze pro free úroveň odmítne požadavek s 429 / token_limit_reached, pokud odhad překročí zbývající měsíční limit (FREE_TIER_MONTHLY_TOKENS, výchozí 100000). Placené úrovně nejsou tímto předběžným kontrolním bodem blokovány v enforceTokenCap; použití je stále zaznamenáváno.

Rychlostní limity: Pokud je nakonfigurován Upstash Redis (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN, a URL neobsahuje zástupný symbol your-instance), platí limity za minutu podle úrovně: free 5, starter 30, growth 60, scale 120, enterprise neomezeně. Při dosažení limitu je odpověď 429 s error: "rate_limit_reached". Pokud Redis není nakonfigurován, omezení rychlosti se přeskočí (viz rateLimit.js).

Úspěšné odpovědi s omezením rychlosti mohou obsahovat X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.


GET /health

Bez autentizace.

Odpověď 200

{
  "status": "ok",
  "timestamp": "2025-03-23T12:00:00.000Z"
}

GET /languages

Bez autentizace.

Vrací kanonický seznam podporovaných jazyků (kód, zobrazovaný název, RTL příznak). Je zde 36 položek; kódy jsou jedinými hodnotami akceptovanými v targets na překladových koncových bodech.

Odpověď 200

{
  "languages": [
    { "code": "en", "name": "English", "rtl": false },
    { "code": "ar", "name": "Arabic", "rtl": true }
  ]
}

Zdroj: api/utils/languages.js.


POST /translate

Vyžaduje Authorization: Bearer <api_key>.

Překládá jeden řetězec content do každého jazyka uvedeného v targets. Model vrací jeden JSON objekt, jehož klíče jsou přesně požadované jazykové kódy a hodnoty jsou přeložené řetězce (viz formatPrompts.js).

Tělo požadavku

PoleTypPovinnéPopis
contentstringAnoNeprazdný řetězec k překladu.
targetsstring[]AnoNeprazdné pole platných jazykových kódů (max 36).
formatstringNeJeden z plain, markdown, json, html. Pokud vynecháno, formát je automaticky detekován z content.
sourcestringNeNápověda zdrojového jazyka pro model; nepovinné.
modelstringNestandard (výchozí) nebo advanced. advanced vyžaduje placenou úroveň (403 na free).

Odpověď 200

{
  "translations": {
    "es": "...",
    "fr": "..."
  },
  "usage": {
    "input_tokens": 120,
    "output_tokens": 340,
    "total_tokens": 460,
    "model": "standard",
    "detected_format": "markdown",
    "detection_confidence": 0.95
  }
}

detected_format a detection_confidence se zobrazují pouze, pokud bylo format vynecháno a proběhla automatická detekce.

Příklad (cURL)

curl -sS -X POST "https://api.usepolylingo.com/v1/translate" \
  -H "Authorization: Bearer $POLYLINGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "{\"title\":\"Hello\"}",
    "format": "json",
    "targets": ["fr", "de"]
  }'

Příklad (Python 3)

pip install requests
import os, requests

url = "https://api.usepolylingo.com/v1/translate"
headers = {
    "Authorization": f"Bearer {os.environ['POLYLINGO_API_KEY']}",
    "Content-Type": "application/json",
}
r = requests.post(url, json={
    "content": "<p>Hello <strong>world</strong></p>",
    "format": "html",
    "targets": ["es"],
}, timeout=120)
r.raise_for_status()
print(r.json()["translations"]["es"])

POST /translate/batch

Vyžaduje Authorization: Bearer <api_key>.

Zpracovává každou položku sekvenčně (jeden modelový hovor na položku). Pokud některá položka selže, API vrátí 500 a nevrátí částečné výsledky pro tento požadavek.

Tělo požadavku

PoleTypPovinnéPopis
itemspoleAnoKaždý prvek: id (string), content (string), nepovinný format.
targetsstring[]AnoStejná pravidla jako u /translate.
sourcestringNeNepovinná nápověda zdrojového jazyka.
modelstringNestandard nebo advanced (stejná pravidla jako u /translate).

Odpověď 200

{
  "results": [
    { "id": "welcome", "translations": { "fr": "...", "de": "..." } },
    { "id": "goodbye", "translations": { "fr": "...", "de": "..." } }
  ],
  "usage": {
    "total_tokens": 900,
    "input_tokens": 400,
    "output_tokens": 500,
    "model": "standard"
  }
}

Příklad

curl -sS -X POST "https://api.usepolylingo.com/v1/translate/batch" \
  -H "Authorization: Bearer $POLYLINGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "id": "a", "content": "Hello", "format": "plain" },
      { "id": "b", "content": "## Title", "format": "markdown" }
    ],
    "targets": ["es", "it"]
  }'

POST /jobs

Vyžaduje Authorization: Bearer <api_key>.

Zařadí překladatelský úkol do fronty a okamžitě vrátí job_id. Překlad běží na pozadí — nehrozí HTTP timeout bez ohledu na velikost obsahu. Výsledek získáte dotazováním GET /jobs/:id.

Použijte tento endpoint místo POST /translate při překladu velkých dokumentů (dlouhý Markdown, mnoho cílových jazyků), kde by doba požadavku mohla překročit timeout HTTP klienta nebo proxy.

Tělo požadavku

PoleTypPovinnéPopis
contentstringAnoNeprazdný řetězec k překladu.
targetsstring[]AnoNeprazné pole platných jazykových kódů (max 36).
formatstringNeJeden z plain, markdown, json, html. Automaticky detekováno, pokud vynecháno.
sourcestringNeNápověda zdrojového jazyka; nepovinné.
modelstringNestandard (výchozí) nebo advanced.

Odpověď 202

{
  "job_id": "a1b2c3d4-...",
  "status": "pending",
  "created_at": "2025-03-23T12:00:00.000Z"
}

GET /jobs/:id

Vyžaduje Authorization: Bearer <api_key>.

Dotazuje stav úkolu odeslaného přes POST /jobs. Dotazujte každých 5–10 sekund. Úkoly vlastní uživatel, který je odeslal — ostatní uživatelé dostanou 404.

Odpověď (čekající / zpracovává se)

{
  "job_id": "a1b2c3d4-...",
  "status": "pending",
  "created_at": "2025-03-23T12:00:00.000Z",
  "updated_at": "2025-03-23T12:00:00.000Z",
  "completed_at": null,
  "queue_position": 3
}

status je pending (čeká na pracovníka) nebo processing (pracovník ji převzal). queue_position (index od 1) udává, kolik čekajících nebo zpracovávaných úkolů bylo vytvořeno přísně před tímto — použijte pro UI indikaci postupu. Vynecháno, pokud dotaz na počet selže.

Odpověď (dokončeno)

{
  "job_id": "a1b2c3d4-...",
  "status": "completed",
  "created_at": "2025-03-23T12:00:00.000Z",
  "updated_at": "2025-03-23T12:00:02.000Z",
  "completed_at": "2025-03-23T12:00:02.000Z",
  "translations": {
    "es": "...",
    "fr": "..."
  },
  "usage": {
    "input_tokens": 120,
    "output_tokens": 340,
    "total_tokens": 460,
    "model": "standard"
  }
}

Odpověď (selhalo)

{
  "job_id": "a1b2c3d4-...",
  "status": "failed",
  "error": "Model returned invalid JSON"
}

Příklad (JavaScript)

const API = 'https://api.usepolylingo.com/v1'
const headers = {
  'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
  'Content-Type': 'application/json',
}

// 1. Odeslat
const submit = await fetch(`${API}/jobs`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ content: longMarkdown, format: 'markdown', targets: ['de', 'fr'] }),
})
const { job_id } = await submit.json()

// 2. Dotazovat
while (true) {
  await new Promise(r => setTimeout(r, 10_000))
  const poll = await fetch(`${API}/jobs/${job_id}`, { headers })
  const job = await poll.json()
  if (job.status === 'completed') { console.log(job.translations); break }
  if (job.status === 'failed')    { throw new Error(job.error) }
  // Volitelné: zobrazit průběh (queue_position je 1-založené, vynecháno pokud není ve frontě)
  if (job.queue_position != null) console.log(`Queue position: ${job.queue_position}`)
}

GET /usage

Vyžaduje Authorization: Bearer <api_key> (standardní vyhledávání klíče — ne interní cesta pouze pro obcházení).

Vrací využití tokenů za aktuální kalendářní měsíc pro autentizovaného uživatele.

Odpověď 200

{
  "period_start": "2025-03-01T00:00:00.000Z",
  "period_end": "2025-03-31T23:59:59.000Z",
  "tokens_used": 12000,
  "tokens_included": 100000,
  "tokens_remaining": 88000,
  "overage_tokens": 0,
  "tier": "free"
}

tokens_included a tokens_remaining jsou null pro enterprise (neomezený grant v reportingu).


Formáty obsahu

Podporované hodnoty format: plain, markdown, json, html.

FormátZachovánoPřeloženo
plainZalomení řádků / odstavceVeškerý viditelný text
markdownSyntaxe, odkazy (URL beze změny), ohraničený kód (doslovný)Próza a text odkazu
jsonKlíče, struktura, netextové typyPouze textové hodnoty
htmlTagy a atributyTextové uzly a vhodné atributy (viz prompt)

RTL a směr ve vaší aplikaci

Pro výstupy plain a markdown API vrací pouze přeložený text — nepřidává dir="rtl" ani obalové prvky. Nastavte směr textu ve vašem UI (CSS direction, atribut dir rodičovského prvku nebo i18n rozvržení vašeho frameworku) při zobrazování arabštiny, hebrejštiny nebo perštiny.

Pro formát html může přeložený markup obsahovat dir="rtl" tam, kde je to vhodné pro RTL cíle; viz formatPrompts.js a HTML testy v scripts/test-translation.js.


Chybové odpovědi

Chyby jsou JSON, pokud je to možné:

{
  "error": "invalid_request",
  "message": "Čitelný detail"
}
HTTPerrorKdy
400invalid_requestChybějící/neplatná pole v těle (např. prázdný content, špatné targets)
400invalid_formatformat není v podporované sadě
400invalid_languageNeznámý kód v targets
401invalid_api_keyChybějící/poškozený Authorization, neznámý klíč, zrušený klíč
403advanced_not_availablemodel: "advanced" na free úrovni
429token_limit_reachedPřekročení měsíčního limitu free úrovně (předběžná kontrola)
429rate_limit_reachedLimit RPM za minutu (když je Redis povolen)
500translation_errorSelhání modelu/sítě; bezpečné opakovat
404not_foundGET /jobs/:id — úkol neexistuje nebo patří jinému uživateli
500server_errorPOST /jobs — nepodařilo se zařadit do fronty; bezpečné opakovat

GET /usage může vrátit 500 s obecnou zprávou, pokud dotaz Supabase selže.


Základní modely (informativní)

API vystavuje pouze standard a advanced. Skutečné OpenAI model ID jsou nakonfigurovány v api/utils/modelRouter.js a nejsou vráceny v odpovědích API.

Reference API | PolyLingo | PolyLingo