API-referentie
Dit document komt overeen met het gedrag van de Express-app in api/app.js en de routehandlers onder api/routes/.
Limieten en gedrag
| Item | Waarde |
|---|---|
| JSON-bodygrootte | Tot 2 MB (express.json({ limit: '2mb' })) |
| Doelen per verzoek | 1–36 taalcodes |
| Batch-items | 1–100 items per batchverzoek |
| Modellen | standard (standaard) of advanced (alleen betaalde niveaus; zie hieronder) |
Maandelijkse token-toewijzing (gratis niveau): Voordat het model wordt aangeroepen, schat de API tokens ruwweg als ceil(content_length / 4) × (number_of_targets + 1) en voor het free niveau alleen, weigert het verzoek met 429 / token_limit_reached als de schatting de resterende maandelijkse toewijzing (FREE_TIER_MONTHLY_TOKENS, standaard 100000) zou overschrijden. Betaalde niveaus worden niet geblokkeerd door deze voorcontrole in enforceTokenCap; het gebruik wordt nog steeds gelogd.
Snelheidslimieten: Wanneer Upstash Redis is geconfigureerd (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN, en de URL bevat niet de tijdelijke aanduiding your-instance), gelden per minuut limieten per niveau: gratis 5, starter 30, groei 60, schaal 120, enterprise onbeperkt. Bij limiet is de respons 429 met error: "rate_limit_reached". Als Redis niet is geconfigureerd, wordt snelheidslimitering overgeslagen (zie rateLimit.js).
Succesvolle snelheidsbeperkte reacties kunnen X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset bevatten.
GET /health
Geen authenticatie.
Respons 200
{
"status": "ok",
"timestamp": "2025-03-23T12:00:00.000Z"
}
GET /languages
Geen authenticatie.
Geeft de canonieke lijst van ondersteunde talen terug (code, weergavenaam, RTL-vlag). Er zijn 36 vermeldingen; codes zijn de enige waarden die worden geaccepteerd in targets op vertaal-eindpunten.
Respons 200
{
"languages": [
{ "code": "en", "name": "English", "rtl": false },
{ "code": "ar", "name": "Arabic", "rtl": true }
]
}
Bron: api/utils/languages.js.
POST /translate
Vereist Authorization: Bearer <api_key>.
Vertaal een enkele content-string naar elke taal die in targets is vermeld. Het model retourneert een enkel JSON-object waarvan de sleutels exact de gevraagde taalcodes zijn en waarvan de waarden vertaalde strings zijn (zie formatPrompts.js).
Verzoekbody
| Veld | Type | Verplicht | Beschrijving |
|---|---|---|---|
content | string | Ja | Niet-lege string om te vertalen |
targets | string[] | Ja | Niet-lege array van geldige taalcodes (maximaal 36) |
format | string | Nee | Eén van plain, markdown, json, html. Indien weggelaten, wordt het formaat automatisch gedetecteerd uit content. |
source | string | Nee | Bron taalhint voor het model; optioneel |
model | string | Nee | standard (standaard) of advanced. advanced vereist een betaald niveau (403 bij 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 en detection_confidence verschijnen alleen wanneer format is weggelaten en automatische detectie is uitgevoerd.
Voorbeeld (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"]
}'
Voorbeeld (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
Vereist Authorization: Bearer <api_key>.
Verwerkt elk item sequentieel (één modelaanroep per item). Als een item faalt, retourneert de API 500 en geeft geen gedeeltelijke resultaten terug voor dat verzoek.
Verzoekbody
| Veld | Type | Verplicht | Beschrijving |
|---|---|---|---|
items | array | Ja | Elk element: id (string), content (string), optioneel format. |
targets | string[] | Ja | Zelfde regels als /translate. |
source | string | Nee | Optionele bron taalhint. |
model | string | Nee | standard of advanced (zelfde regels als /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"
}
}
Voorbeeld
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
Vereist Authorization: Bearer <api_key>.
Zet een vertaaltaak in de wachtrij en retourneert onmiddellijk een job_id. De vertaling wordt op de achtergrond uitgevoerd — geen risico op HTTP-timeout ongeacht de inhoudsgrootte. Poll GET /jobs/:id voor het resultaat.
Gebruik dit eindpunt in plaats van POST /translate bij het vertalen van grote documenten (lange Markdown, veel doeltalen) waarbij de verzoekduur mogelijk de HTTP-client- of proxy-timeout overschrijdt.
Verzoekbody
| Veld | Type | Verplicht | Beschrijving |
|---|---|---|---|
content | string | Ja | Niet-lege string om te vertalen |
targets | string[] | Ja | Niet-lege array van geldige taalcodes (maximaal 36) |
format | string | Nee | Eén van plain, markdown, json, html. Automatisch gedetecteerd als weggelaten. |
source | string | Nee | Bron taalhint; optioneel. |
model | string | Nee | standard (standaard) of advanced. |
Respons 202
{
"job_id": "a1b2c3d4-...",
"status": "pending",
"created_at": "2025-03-23T12:00:00.000Z"
}
GET /jobs/:id
Vereist Authorization: Bearer <api_key>.
Pollt de status van een taak die is ingediend via POST /jobs. Poll elke 5–10 seconden. Taken zijn eigendom van de indienende gebruiker — andere gebruikers ontvangen 404.
Respons (in afwachting / verwerking)
{
"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 is pending (wacht op een worker) of processing (worker heeft het opgepakt). queue_position (1-gebaseerd) is hoeveel in afwachting of verwerkte taken strikt vóór deze zijn gemaakt — gebruik dit voor voortgangs-UI. Wordt weggelaten als de telling mislukt.
Respons (voltooid)
{
"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 (mislukt)
{
"job_id": "a1b2c3d4-...",
"status": "failed",
"error": "Model returned invalid JSON"
}
Voorbeeld (JavaScript)
const API = 'https://api.usepolylingo.com/v1'
const headers = {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
}
// 1. Indienen
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) }
// Optioneel: voortgang tonen (queue_position is 1-gebaseerd, weggelaten als niet in wachtrij)
if (job.queue_position != null) console.log(`Queue position: ${job.queue_position}`)
}
GET /usage
Vereist Authorization: Bearer <api_key> (standaard sleutelopzoeking — niet het interne bypass-pad).
Geeft tokengebruik terug voor de huidige kalendermaand voor de geauthenticeerde gebruiker.
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 en tokens_remaining zijn null voor enterprise (onbeperkte toewijzing in rapportage).
Inhoudsformaten
Ondersteunde format-waarden: plain, markdown, json, html.
| Formaat | Behouden | Vertaald |
|---|---|---|
plain | Regelscheidingen / paragrafen | Alle zichtbare tekst |
markdown | Syntax, links (URL ongewijzigd), fenced code (verbatim) | Proza en linktekst |
json | Sleutels, structuur, niet-string types | Alleen stringwaarden |
html | Tags en attributen | Tekstknopen en geschikte attributen (zie prompts) |
RTL en richting in uw app
Voor plain en markdown output retourneert de API alleen vertaalde tekst — het voegt geen dir="rtl" of wrapper-elementen toe. Stel tekstrichting in uw UI in (CSS direction, een bovenliggend element’s dir-attribuut, of de i18n-layout van uw framework) bij het weergeven van Arabisch, Hebreeuws of Perzisch.
Voor html formaat kan vertaalde markup dir="rtl" bevatten waar passend voor RTL-doelen; zie formatPrompts.js en de HTML-tests in scripts/test-translation.js.
Foutresponsen
Fouten zijn JSON indien mogelijk:
{
"error": "invalid_request",
"message": "Menselijk leesbare details"
}
| HTTP | error | Wanneer |
|---|---|---|
| 400 | invalid_request | Ontbrekende/ongeldige bodyvelden (bijv. lege content, slechte targets) |
| 400 | invalid_format | format niet in de ondersteunde set |
| 400 | invalid_language | Onbekende code in targets |
| 401 | invalid_api_key | Ontbrekende/verkeerde Authorization, onbekende sleutel, ingetrokken sleutel |
| 403 | advanced_not_available | model: "advanced" op gratis niveau |
| 429 | token_limit_reached | Maandelijkse limiet gratis niveau zou worden overschreden (voorcontrole) |
| 429 | rate_limit_reached | RPM-limiet per minuut (wanneer Redis ingeschakeld) |
| 500 | translation_error | Model-/netwerkfout; veilig om opnieuw te proberen |
| 404 | not_found | GET /jobs/:id — taak bestaat niet of behoort tot een andere gebruiker |
| 500 | server_error | POST /jobs — toevoegen aan wachtrij mislukt; veilig om opnieuw te proberen |
GET /usage kan 500 retourneren met een generiek bericht als Supabase-query mislukt.
Onderliggende modellen (informatief)
De API toont alleen standard en advanced. Werkelijke OpenAI-model-ID's zijn geconfigureerd in api/utils/modelRouter.js en worden niet geretourneerd in API-responses.