API-referens

Detta dokument matchar beteendet hos Express-appen i api/app.js och routhanterarna under api/routes/.

Gränser och beteende

ObjektVärde
JSON-kroppsstorlekUpp till 2 MB (express.json({ limit: '2mb' }))
Mål per förfrågan1–36 språkkoder
Batchobjekt1–100 objekt per batchförfrågan
Modellerstandard (standard) eller advanced (endast betalda nivåer; se nedan)

Månatlig tokenkvot (gratisnivå): Innan modellen anropas uppskattar API antalet tokens ungefär som ceil(content_length / 4) × (number_of_targets + 1) och för free-nivån avvisas förfrågan med 429 / token_limit_reached om uppskattningen överstiger kvarvarande månatlig kvot (FREE_TIER_MONTHLY_TOKENS, standard 100000). Betalda nivåer blockeras inte av denna förhandskontroll i enforceTokenCap; användningen loggas ändå.

Hastighetsbegränsningar: När Upstash Redis är konfigurerat (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN, och URL:en innehåller inte platshållaren your-instance), gäller minutbegränsningar per nivå: gratis 5, start 30, tillväxt 60, skala 120, företag obegränsat. Vid gräns är svaret 429 med error: "rate_limit_reached". Om Redis inte är konfigurerat hoppas hastighetsbegränsningen över (se rateLimit.js).

Lyckade svar med hastighetsbegränsning kan inkludera X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.


GET /health

Ingen autentisering.

Svar 200

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

GET /languages

Ingen autentisering.

Returnerar den kanoniska listan över stödda språk (kod, visningsnamn, RTL-flagga). Det finns 36 poster; koder är de enda värden som accepteras i targets på översättningsendpoints.

Svar 200

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

Källa: api/utils/languages.js.


POST /translate

Kräver Authorization: Bearer <api_key>.

Översätter en enda content-sträng till varje språk som listas i targets. Modellen returnerar ett enda JSON-objekt vars nycklar är exakt de begärda språkkoderna och vars värden är översatta strängar (se formatPrompts.js).

Begärans kropp

FältTypObligatorisktBeskrivning
contentstringJaIcke-tom sträng att översätta.
targetsstring[]JaIcke-tom array av giltiga språkkoder (max 36).
formatstringNejEn av plain, markdown, json, html. Om utelämnat, formateras automatiskt från content.
sourcestringNejKällspråksledtråd för modellen; valfritt.
modelstringNejstandard (standard) eller advanced. advanced kräver betald nivå (403 på gratisnivå).

Svar 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 och detection_confidence visas endast när format utelämnades och automatisk detektion kördes.

Exempel (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"]
  }'

Exempel (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

Kräver Authorization: Bearer <api_key>.

Bearbetar varje objekt sekventiellt (ett modellanrop per objekt). Om något objekt misslyckas returnerar API 500 och returnerar inga delresultat för den förfrågan.

Begärans kropp

FältTypObligatorisktBeskrivning
itemsarrayJaVarje element: id (string), content (string), valfri format.
targetsstring[]JaSamma regler som /translate.
sourcestringNejValfri källspråksledtråd.
modelstringNejstandard eller advanced (samma regler som /translate).

Svar 200

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

Exempel

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

Kräver Authorization: Bearer <api_key>.

Lägger till ett översättningsjobb i kön och returnerar omedelbart med ett job_id. Översättningen körs i bakgrunden — ingen risk för HTTP-timeout oavsett innehållets storlek. Polling via GET /jobs/:id för resultatet.

Använd denna endpoint istället för POST /translate när du översätter stora dokument (lång Markdown, många mål språk) där förfrågningslängden kan överstiga timeout för din HTTP-klient eller proxy.

Begärans kropp

FältTypObligatorisktBeskrivning
contentstringJaIcke-tom sträng att översätta.
targetsstring[]JaIcke-tom array av giltiga språkkoder (max 36).
formatstringNejEn av plain, markdown, json, html. Automatiskt upptäckt om utelämnad.
sourcestringNejKällspråksledtråd; valfritt.
modelstringNejstandard (standard) eller advanced.

Svar 202

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

GET /jobs/:id

Kräver Authorization: Bearer <api_key>.

Pollar status för ett jobb som skickats via POST /jobs. Polling var 5–10 sekund. Jobb ägs av den användare som skickade dem — andra användare får 404.

Svar (väntande / bearbetar)

{
  "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 är pending (väntar på arbetare) eller processing (arbetare har tagit det). queue_position (1-baserad) visar hur många väntande eller bearbetande jobb som skapades strikt före detta — använd för progress UI. Utesluts om räknefrågan misslyckas.

Svar (avslutat)

{
  "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"
  }
}

Svar (misslyckat)

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

Exempel (JavaScript)

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

// 1. Skicka
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. Poll
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) }
  // Valfritt: visa framsteg (queue_position är 1-baserad, utelämnas om ej i kö)
  if (job.queue_position != null) console.log(`Köposition: ${job.queue_position}`)
}

GET /usage

Kräver Authorization: Bearer <api_key> (standard nyckelsökning — inte intern bypass-väg).

Returnerar tokenanvändning för nuvarande kalendermånad för den autentiserade användaren.

Svar 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 och tokens_remaining är null för enterprise (obegränsad kvot i rapportering).


Innehållsformat

Stödda format-värden: plain, markdown, json, html.

FormatBevarasÖversätts
plainRadbrytningar / styckenAll synlig text
markdownSyntax, länkar (URL oförändrad), innesluten kod (verbatim)Prosa och länktext
jsonNycklar, struktur, icke-strängtyperEndast strängvärden
htmlTaggar och attributTextnoder och lämpliga attribut (se prompts)

RTL och riktning i din app

För plain och markdown output returnerar API endast översatt text — lägger inte till dir="rtl" eller wrapper-element. Ställ in textriktning i din UI (CSS direction, en föräldraelements dir-attribut eller ditt ramverks i18n-layout) när du visar arabiska, hebreiska eller persiska.

För html-format kan översatt markup inkludera dir="rtl" där det är lämpligt för RTL-mål; se formatPrompts.js och HTML-tester i scripts/test-translation.js.


Felresponser

Fel är JSON när möjligt:

{
  "error": "invalid_request",
  "message": "Mänskligt läsbar detalj"
}
HTTPerrorNär
400invalid_requestSaknade/ogiltiga kroppsfält (t.ex. tom content, dåliga targets)
400invalid_formatformat inte i det stödda setet
400invalid_languageOkänd kod i targets
401invalid_api_keySaknad/felaktig Authorization, okänd nyckel, återkallad nyckel
403advanced_not_availablemodel: "advanced" på gratisnivå
429token_limit_reachedMånatlig gräns för gratisnivå skulle överskridas (förhandskontroll)
429rate_limit_reachedRPM-gräns per minut (när Redis är aktiverat)
500translation_errorModell-/nätverksfel; säkert att försöka igen
404not_foundGET /jobs/:id — jobb finns inte eller tillhör annan användare
500server_errorPOST /jobs — misslyckades att köa; säkert att försöka igen

GET /usage kan returnera 500 med ett generiskt meddelande om Supabase-frågan misslyckas.


Underliggande modeller (informativt)

API exponerar endast standard och advanced. Faktiska OpenAI-modell-ID:n konfigureras i api/utils/modelRouter.js och returneras inte i API-svar.

API-referens | PolyLingo | PolyLingo