API-referanse
Dette dokumentet samsvarer med oppførselen til Express-appen i api/app.js og rutehåndtererne under api/routes/.
Begrensninger og oppførsel
| Element | Verdi |
|---|---|
| JSON-kroppsstørrelse | Opptil 2 MB (express.json({ limit: '2mb' })) |
| Mål per forespørsel | 1–36 språk-koder |
| Batch-elementer | 1–100 elementer per batch-forespørsel |
| Modeller | standard (standard) eller advanced (kun betalte nivåer; se nedenfor) |
Månedlig token-tillatelse (gratis nivå): Før modellkall estimerer API tokens omtrent som ceil(content_length / 4) × (number_of_targets + 1) og for free nivået alene avviser forespørselen med 429 / token_limit_reached hvis estimatet overstiger gjenværende månedlig tildeling (FREE_TIER_MONTHLY_TOKENS, standard 100000). Betalte nivåer blokkeres ikke av denne forhåndssjekken i enforceTokenCap; bruk logges fortsatt.
Ratelimiter: Når Upstash Redis er konfigurert (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN, og URL-en ikke inneholder plassholderen your-instance), gjelder minuttvise grenser per nivå: gratis 5, starter 30, vekst 60, skala 120, enterprise ubegrenset. Ved grense er responsen 429 med error: "rate_limit_reached". Hvis Redis ikke er konfigurert, hoppes ratelimiting over (se rateLimit.js).
Vellykede ratelimiterte responser kan inkludere X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
GET /health
Ingen autentisering.
Respons 200
{
"status": "ok",
"timestamp": "2025-03-23T12:00:00.000Z"
}
GET /languages
Ingen autentisering.
Returnerer den kanoniske listen over støttede språk (kode, visningsnavn, RTL-flag). Det er 36 oppføringer; koder er de eneste verdiene som aksepteres i targets på oversettelsesendepunkter.
Respons 200
{
"languages": [
{ "code": "en", "name": "English", "rtl": false },
{ "code": "ar", "name": "Arabic", "rtl": true }
]
}
Kilde: api/utils/languages.js.
POST /translate
Krever Authorization: Bearer <api_key>.
Oversetter en enkelt content-streng til hvert språk oppført i targets. Modellen returnerer et enkelt JSON-objekt hvor nøklene er nøyaktig de forespurte språk-kodene og verdiene er oversatte strenger (se formatPrompts.js).
Forespørselskropp
| Felt | Type | Obligatorisk | Beskrivelse |
|---|---|---|---|
content | string | Ja | Ikke-tom streng som skal oversettes |
targets | string[] | Ja | Ikke-tom liste med gyldige språk-koder (maks 36) |
format | string | Nei | En av plain, markdown, json, html. Hvis utelatt, blir formatet automatisk oppdaget fra content. |
source | string | Nei | Kilde-språktips for modellen; valgfritt |
model | string | Nei | standard (standard) eller advanced. advanced krever betalt nivå (403 på gratis). |
Respons 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 og detection_confidence vises bare når format ble utelatt og automatisk deteksjon ble kjørt.
Eksempel (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"]
}'
Eksempel (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
Krever Authorization: Bearer <api_key>.
Behandler hvert element sekvensielt (ett modellkall per element). Hvis noe element feiler, returnerer API 500 og returnerer ikke delvise resultater for den forespørselen.
Forespørselskropp
| Felt | Type | Obligatorisk | Beskrivelse |
|---|---|---|---|
items | array | Ja | Hvert element: id (string), content (string), valgfri format. |
targets | string[] | Ja | Samme regler som /translate. |
source | string | Nei | Valgfritt kilde-språktips. |
model | string | Nei | standard eller advanced (samme regler som /translate). |
Respons 200
{
"results": [
{ "id": "welcome", "translations": { "fr": "...", "de": "..." } },
{ "id": "goodbye", "translations": { "fr": "...", "de": "..." } }
],
"usage": {
"total_tokens": 900,
"input_tokens": 400,
"output_tokens": 500,
"model": "standard"
}
}
Eksempel
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
Krever Authorization: Bearer <api_key>.
Setter en oversettelsesjobb i kø og returnerer umiddelbart med en job_id. Oversettelsen kjører i bakgrunnen — ingen risiko for HTTP-timeout uansett innholdsstørrelse. Poll GET /jobs/:id for resultatet.
Bruk dette endepunktet i stedet for POST /translate når du oversetter store dokumenter (lang Markdown, mange mål-språk) der forespørselstiden kan overstige HTTP-klientens eller proxyens timeout.
Forespørselskropp
| Felt | Type | Obligatorisk | Beskrivelse |
|---|---|---|---|
content | string | Ja | Ikke-tom streng som skal oversettes |
targets | string[] | Ja | Ikke-tom liste med gyldige språk-koder (maks 36) |
format | string | Nei | En av plain, markdown, json, html. Automatisk oppdaget hvis utelatt. |
source | string | Nei | Kilde-språktips; valgfritt. |
model | string | Nei | standard (standard) eller advanced. |
Respons 202
{
"job_id": "a1b2c3d4-...",
"status": "pending",
"created_at": "2025-03-23T12:00:00.000Z"
}
GET /jobs/:id
Krever Authorization: Bearer <api_key>.
Poller status for en jobb sendt via POST /jobs. Poll hvert 5–10 sekund. Jobber eies av den som sendte inn — andre brukere får 404.
Respons (ventende / behandlende)
{
"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 er pending (venter på en arbeider) eller processing (arbeider har tatt den). queue_position (1-basert) er hvor mange ventende eller behandlende jobber som ble opprettet strengt før denne — bruk den for fremdrifts-UI. Utelatt når telleforespørselen feiler.
Respons (fullført)
{
"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"
}
}
Respons (feilet)
{
"job_id": "a1b2c3d4-...",
"status": "failed",
"error": "Model returned invalid JSON"
}
Eksempel (JavaScript)
const API = 'https://api.usepolylingo.com/v1'
const headers = {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
}
// 1. Send inn
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) }
// Valgfritt: vis fremdrift (queue_position er 1-basert, utelatt når ikke i kø)
if (job.queue_position != null) console.log(`Queue position: ${job.queue_position}`)
}
GET /usage
Krever Authorization: Bearer <api_key> (standard nøkkelsøk — ikke den interne omgåelsesbanen).
Returnerer tokenbruk for den gjeldende kalender-måneden for den autentiserte brukeren.
Respons 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 og tokens_remaining er null for enterprise (ubegrenset tildeling i rapportering).
Innholdsformater
Støttede format-verdier: plain, markdown, json, html.
| Format | Bevart | Oversatt |
|---|---|---|
plain | Linjeskift / avsnitt | All synlig tekst |
markdown | Syntaks, lenker (URL uendret), fenced code (verbatim) | Prosa og lenketekst |
json | Nøkler, struktur, ikke-streng-typer | Kun strengverdier |
html | Tagger og attributter | Tekstnoder og passende attributter (se prompts) |
RTL og retning i appen din
For plain og markdown output returnerer API kun oversatt tekst — det legger ikke til dir="rtl" eller wrapper-elementer. Sett tekstretning i UI-en din (CSS direction, et overordnet elements dir-attributt, eller i18n-layouten til rammeverket ditt) når du viser arabisk, hebraisk eller persisk.
For html format kan oversatt markup inkludere dir="rtl" der det er passende for RTL-mål; se formatPrompts.js og HTML-testene i scripts/test-translation.js.
Feilresponser
Feil er JSON når mulig:
{
"error": "invalid_request",
"message": "Menneskelesbar detalj"
}
| HTTP | error | Når |
|---|---|---|
| 400 | invalid_request | Manglende/ugyldige kropps-felt (f.eks. tom content, dårlige targets) |
| 400 | invalid_format | format ikke i støttet sett |
| 400 | invalid_language | Ukjent kode i targets |
| 401 | invalid_api_key | Manglende/feil Authorization, ukjent nøkkel, tilbakekalt nøkkel |
| 403 | advanced_not_available | model: "advanced" på gratis nivå |
| 429 | token_limit_reached | Gratis nivå månedlig grense ville blitt overskredet (forhåndssjekk) |
| 429 | rate_limit_reached | RPM-grense per minutt (når Redis er aktivert) |
| 500 | translation_error | Modell-/nettverksfeil; trygt å prøve på nytt |
| 404 | not_found | GET /jobs/:id — jobb eksisterer ikke eller tilhører en annen bruker |
| 500 | server_error | POST /jobs — mislyktes i å sette i kø; trygt å prøve på nytt |
GET /usage kan returnere 500 med en generell melding hvis Supabase-spørring mislykkes.
Underliggende modeller (informativt)
API-en eksponerer kun standard og advanced. Faktiske OpenAI-modell-ID-er er konfigurert i api/utils/modelRouter.js og returneres ikke i API-responser.