Tham khảo API

Tài liệu này khớp với hành vi của ứng dụng Express trong api/app.js và các bộ xử lý tuyến đường dưới api/routes/.

Giới hạn và hành vi

MụcGiá trị
Kích thước thân JSONTối đa 2 MB (express.json({ limit: '2mb' }))
Mục tiêu mỗi yêu cầu1–36 mã ngôn ngữ
Mục lô1–100 mục mỗi yêu cầu lô
Mô hìnhstandard (mặc định) hoặc advanced (chỉ các cấp trả phí; xem bên dưới)

Hạn mức token hàng tháng (cấp miễn phí): Trước khi gọi mô hình, API ước tính token xấp xỉ ceil(content_length / 4) × (number_of_targets + 1) và, chỉ với cấp free, từ chối yêu cầu với mã 429 / token_limit_reached nếu ước tính vượt quá hạn mức hàng tháng còn lại (FREE_TIER_MONTHLY_TOKENS, mặc định 100000). Các cấp trả phí không bị chặn bởi kiểm tra trước này trong enforceTokenCap; việc sử dụng vẫn được ghi lại.

Giới hạn tốc độ: Khi cấu hình Upstash Redis (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN, và URL không chứa chỗ giữ chỗ your-instance), giới hạn theo phút áp dụng theo cấp: miễn phí 5, khởi đầu 30, phát triển 60, mở rộng 120, doanh nghiệp không giới hạn. Khi vượt giới hạn, phản hồi là 429 với error: "rate_limit_reached". Nếu Redis không được cấu hình, giới hạn tốc độ bị bỏ qua (xem rateLimit.js).

Phản hồi giới hạn tốc độ thành công có thể bao gồm X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.


GET /health

Không cần xác thực.

Phản hồi 200

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

GET /languages

Không cần xác thực.

Trả về danh sách chuẩn các ngôn ngữ được hỗ trợ (mã, tên hiển thị, cờ RTL). Có 36 mục; mã là giá trị duy nhất được chấp nhận trong targets tại các điểm cuối dịch.

Phản hồi 200

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

Nguồn: api/utils/languages.js.


POST /translate

Yêu cầu Authorization: Bearer <api_key>.

Dịch một chuỗi content duy nhất sang mọi ngôn ngữ được liệt kê trong targets. Mô hình trả về một đối tượng JSON duy nhất với các khóa chính xác là các mã ngôn ngữ yêu cầu và giá trị là các chuỗi đã dịch (xem formatPrompts.js).

Thân yêu cầu

TrườngLoạiBắt buộcMô tả
contentstringChuỗi không rỗng để dịch.
targetsstring[]Mảng không rỗng các mã ngôn ngữ hợp lệ (tối đa 36).
formatstringKhôngMột trong plain, markdown, json, html. Nếu bỏ qua, định dạng được tự động phát hiện từ content.
sourcestringKhôngGợi ý ngôn ngữ nguồn cho mô hình; tùy chọn.
modelstringKhôngstandard (mặc định) hoặc advanced. advanced yêu cầu cấp trả phí (403 với cấp miễn phí).

Phản hồi 200

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

detected_formatdetection_confidence chỉ xuất hiện khi format bị bỏ qua và tự động phát hiện được thực hiện.

Ví dụ (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"]
  }'

Ví dụ (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

Yêu cầu Authorization: Bearer <api_key>.

Xử lý từng mục tuần tự (mỗi mục gọi mô hình một lần). Nếu bất kỳ mục nào thất bại, API trả về 500 và không trả kết quả một phần cho yêu cầu đó.

Thân yêu cầu

TrườngLoạiBắt buộcMô tả
itemsmảngMỗi phần tử: id (chuỗi), content (chuỗi), tùy chọn format.
targetsstring[]Quy tắc giống /translate.
sourcestringKhôngGợi ý ngôn ngữ nguồn tùy chọn.
modelstringKhôngstandard hoặc advanced (quy tắc giống /translate).

Phản hồi 200

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

Ví dụ

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

Yêu cầu Authorization: Bearer <api_key>.

Đưa một công việc dịch vào hàng đợi và trả về ngay với job_id. Việc dịch chạy nền — không có rủi ro hết thời gian HTTP bất kể kích thước nội dung. Kiểm tra GET /jobs/:id để lấy kết quả.

Sử dụng điểm cuối này thay cho POST /translate khi dịch tài liệu lớn (Markdown dài, nhiều ngôn ngữ mục tiêu) mà thời gian yêu cầu có thể vượt quá thời gian chờ của client hoặc proxy HTTP của bạn.

Thân yêu cầu

TrườngLoạiBắt buộcMô tả
contentstringChuỗi không rỗng để dịch.
targetsstring[]Mảng không rỗng các mã ngôn ngữ hợp lệ (tối đa 36).
formatstringKhôngMột trong plain, markdown, json, html. Tự động phát hiện nếu bỏ qua.
sourcestringKhôngGợi ý ngôn ngữ nguồn; tùy chọn.
modelstringKhôngstandard (mặc định) hoặc advanced.

Phản hồi 202

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

GET /jobs/:id

Yêu cầu Authorization: Bearer <api_key>.

Kiểm tra trạng thái công việc gửi qua POST /jobs. Kiểm tra mỗi 5–10 giây. Công việc thuộc về người dùng gửi — người dùng khác nhận 404.

Phản hồi (đang chờ / xử lý)

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

statuspending (đang chờ công nhân) hoặc processing (công nhân đã nhận). queue_position (bắt đầu từ 1) là số công việc đang chờ hoặc xử lý được tạo trước công việc này — dùng cho giao diện tiến trình. Bỏ qua nếu truy vấn đếm thất bại.

Phản hồi (hoàn thành)

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

Phản hồi (thất bại)

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

Ví dụ (JavaScript)

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

// 1. Gửi
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. Kiểm tra
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) }
  // Tùy chọn: hiển thị tiến trình (queue_position bắt đầu từ 1, bỏ qua khi không trong hàng)
  if (job.queue_position != null) console.log(`Vị trí hàng đợi: ${job.queue_position}`)
}

GET /usage

Yêu cầu Authorization: Bearer <api_key> (tra cứu khóa tiêu chuẩn — không phải đường dẫn bỏ qua nội bộ).

Trả về việc sử dụng token cho tháng lịch hiện tại của người dùng đã xác thực.

Phản hồi 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_includedtokens_remainingnull cho enterprise (hạn mức không giới hạn trong báo cáo).


Định dạng nội dung

Các giá trị format được hỗ trợ: plain, markdown, json, html.

Định dạngGiữ nguyênDịch
plainNgắt dòng / đoạn vănTất cả văn bản hiển thị
markdownCú pháp, liên kết (URL không đổi), khối mã (nguyên văn)Văn bản và văn bản liên kết
jsonKhóa, cấu trúc, kiểu không phải chuỗiChỉ giá trị chuỗi
htmlThẻ và thuộc tínhNút văn bản và thuộc tính thích hợp (xem lời nhắc)

RTL và hướng trong ứng dụng của bạn

Với đầu ra plainmarkdown, API chỉ trả về văn bản đã dịch — không thêm dir="rtl" hoặc phần tử bao bọc. Đặt hướng văn bản trong UI của bạn (CSS direction, thuộc tính dir của phần tử cha hoặc bố cục i18n của framework) khi hiển thị tiếng Ả Rập, Do Thái hoặc Ba Tư.

Với định dạng html, đánh dấu đã dịch có thể bao gồm dir="rtl" khi thích hợp cho các mục tiêu RTL; xem formatPrompts.js và các bài kiểm tra HTML trong scripts/test-translation.js.


Phản hồi lỗi

Lỗi ở dạng JSON khi có thể:

{
  "error": "invalid_request",
  "message": "Chi tiết dễ hiểu cho người dùng"
}
HTTPerrorKhi nào
400invalid_requestThiếu/trường thân không hợp lệ (ví dụ: content rỗng, targets sai)
400invalid_formatformat không thuộc tập hợp được hỗ trợ
400invalid_languageMã không xác định trong targets
401invalid_api_keyThiếu/hỏng Authorization, khóa không biết, khóa bị thu hồi
403advanced_not_availablemodel: "advanced" trên cấp miễn phí
429token_limit_reachedVượt hạn mức token hàng tháng cấp miễn phí (kiểm tra trước)
429rate_limit_reachedGiới hạn RPM theo phút (khi Redis bật)
500translation_errorLỗi mô hình/mạng; có thể thử lại
404not_foundGET /jobs/:id — công việc không tồn tại hoặc thuộc người dùng khác
500server_errorPOST /jobs — không thể xếp hàng; có thể thử lại

GET /usage có thể trả về 500 với thông báo chung nếu truy vấn Supabase thất bại.


Mô hình nền tảng (thông tin)

API chỉ cung cấp standardadvanced. ID mô hình OpenAI thực tế được cấu hình trong api/utils/modelRouter.jskhông được trả về trong phản hồi API.

Tham chiếu API | PolyLingo | PolyLingo