เอกสารอ้างอิง API
เอกสารนี้ตรงกับพฤติกรรมของแอป Express ใน api/app.js และตัวจัดการเส้นทางภายใต้ api/routes/
ขีดจำกัดและพฤติกรรม
| รายการ | ค่า |
|---|---|
| ขนาดเนื้อหา JSON | สูงสุด 2 MB (express.json({ limit: '2mb' })) |
| เป้าหมายต่อคำขอ | 1–36 รหัสภาษา |
| รายการในชุดคำขอ | 1–100 รายการต่อคำขอแบบชุด |
| โมเดล | standard (ค่าเริ่มต้น) หรือ advanced (เฉพาะระดับชำระเงิน; ดูด้านล่าง) |
โควต้าท็อกเค็นรายเดือน (ระดับฟรี): ก่อนเรียกโมเดล API จะประมาณจำนวนโทเค็นโดยประมาณเป็น ceil(content_length / 4) × (number_of_targets + 1) และสำหรับระดับ free เท่านั้น จะปฏิเสธคำขอด้วยรหัส 429 / token_limit_reached หากการประมาณเกินโควต้ารายเดือนที่เหลือ (FREE_TIER_MONTHLY_TOKENS, ค่าเริ่มต้น 100000) ระดับชำระเงินจะไม่ถูกบล็อกโดยการตรวจสอบล่วงหน้าใน enforceTokenCap; การใช้งานยังคงถูกบันทึกไว้
ข้อจำกัดอัตรา: เมื่อกำหนดค่า Upstash Redis (UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN และ URL ไม่มีตัวแทนที่เป็น your-instance) จะมีข้อจำกัดต่อหนึ่งนาทีตามระดับ: ฟรี 5, เริ่มต้น 30, เติบโต 60, ขยาย 120, องค์กรไม่จำกัด เมื่อถึงขีดจำกัด การตอบกลับจะเป็น 429 พร้อม error: "rate_limit_reached" หากไม่ได้กำหนดค่า Redis จะข้ามการจำกัดอัตรา (ดู rateLimit.js)
การตอบกลับที่จำกัดอัตราอย่างสำเร็จอาจรวมถึง X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
GET /health
ไม่ต้องการการตรวจสอบสิทธิ์
การตอบกลับ 200
{
"status": "ok",
"timestamp": "2025-03-23T12:00:00.000Z"
}
GET /languages
ไม่ต้องการการตรวจสอบสิทธิ์
ส่งคืนรายการภาษาที่รองรับอย่างเป็นทางการ (รหัส, ชื่อแสดง, ธง RTL) มีทั้งหมด 36 รายการ; รหัสเป็นค่าที่ยอมรับได้เพียงอย่างเดียวใน targets บนจุดสิ้นสุดการแปล
การตอบกลับ 200
{
"languages": [
{ "code": "en", "name": "English", "rtl": false },
{ "code": "ar", "name": "Arabic", "rtl": true }
]
}
ที่มา: api/utils/languages.js
POST /translate
ต้องการ Authorization: Bearer <api_key>
แปลสตริง content เดียวเป็นทุกภาษาที่ระบุใน targets โมเดลจะส่งคืน วัตถุ JSON เดียว ที่มีคีย์เป็นรหัสภาษาที่ร้องขอ อย่างแม่นยำ และค่าคือสตริงที่แปลแล้ว (ดู formatPrompts.js)
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
content | string | ใช่ | สตริงที่ไม่ว่างเปล่าสำหรับแปล |
targets | string[] | ใช่ | อาร์เรย์ที่ไม่ว่างเปล่าของรหัสภาษาที่ถูกต้อง (สูงสุด 36) |
format | string | ไม่ | หนึ่งใน plain, markdown, json, html หากละไว้ จะตรวจจับรูปแบบโดยอัตโนมัติจาก content |
source | string | ไม่ | คำใบ้ภาษาต้นทางสำหรับโมเดล; ไม่บังคับ |
model | string | ไม่ | standard (ค่าเริ่มต้น) หรือ advanced advanced ต้องใช้ระดับชำระเงิน (403 สำหรับฟรี) |
การตอบกลับ 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 และ detection_confidence จะปรากฏเฉพาะเมื่อ format ถูกละไว้และมีการตรวจจับอัตโนมัติ
ตัวอย่าง (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"]
}'
ตัวอย่าง (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
ต้องการ Authorization: Bearer <api_key>
ประมวลผลแต่ละรายการ ตามลำดับ (เรียกโมเดลหนึ่งครั้งต่อรายการ) หากรายการใดล้มเหลว API จะส่งคืน 500 และจะไม่ส่งคืนผลลัพธ์บางส่วนสำหรับคำขอนั้น
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
items | array | ใช่ | แต่ละรายการ: id (string), content (string), format เป็นทางเลือก |
targets | string[] | ใช่ | กฎเดียวกับ /translate |
source | string | ไม่ | คำใบ้ภาษาต้นทางเป็นทางเลือก |
model | string | ไม่ | standard หรือ advanced (กฎเดียวกับ /translate) |
การตอบกลับ 200
{
"results": [
{ "id": "welcome", "translations": { "fr": "...", "de": "..." } },
{ "id": "goodbye", "translations": { "fr": "...", "de": "..." } }
],
"usage": {
"total_tokens": 900,
"input_tokens": 400,
"output_tokens": 500,
"model": "standard"
}
}
ตัวอย่าง
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
ต้องการ Authorization: Bearer <api_key>
เพิ่มงานแปลในคิวและส่งคืนทันทีพร้อม job_id การแปลจะทำงานเบื้องหลัง — ไม่มีความเสี่ยงของการหมดเวลาของ HTTP ไม่ว่าขนาดเนื้อหาจะเป็นเท่าใด ตรวจสอบ GET /jobs/:id สำหรับผลลัพธ์
ใช้จุดสิ้นสุดนี้แทน POST /translate เมื่อแปลเอกสารขนาดใหญ่ (Markdown ยาว หลายภาษาเป้าหมาย) ที่ระยะเวลาคำขออาจเกินเวลาหมดอายุของไคลเอนต์ HTTP หรือพร็อกซีของคุณ
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
content | string | ใช่ | สตริงที่ไม่ว่างเปล่าสำหรับแปล |
targets | string[] | ใช่ | อาร์เรย์ที่ไม่ว่างเปล่าของรหัสภาษาที่ถูกต้อง (สูงสุด 36) |
format | string | ไม่ | หนึ่งใน plain, markdown, json, html ตรวจจับอัตโนมัติถ้าละไว้ |
source | string | ไม่ | คำใบ้ภาษาต้นทาง; เป็นทางเลือก |
model | string | ไม่ | standard (ค่าเริ่มต้น) หรือ advanced |
การตอบกลับ 202
{
"job_id": "a1b2c3d4-...",
"status": "pending",
"created_at": "2025-03-23T12:00:00.000Z"
}
GET /jobs/:id
ต้องการ Authorization: Bearer <api_key>
ตรวจสอบสถานะของงานที่ส่งผ่าน POST /jobs ตรวจสอบทุก 5–10 วินาที งานเป็นของผู้ใช้ที่ส่ง — ผู้ใช้อื่นจะได้รับ 404
การตอบกลับ (รอดำเนินการ / กำลังประมวลผล)
{
"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 คือ pending (รอผู้ปฏิบัติงาน) หรือ processing (ผู้ปฏิบัติงานรับงานแล้ว) queue_position (เริ่มนับที่ 1) คือจำนวนงานที่รอดำเนินการหรือกำลังประมวลผลที่สร้างก่อนหน้านี้ — ใช้สำหรับ UI แสดงความคืบหน้า ละไว้เมื่อการสอบถามนับล้มเหลว
การตอบกลับ (เสร็จสิ้น)
{
"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"
}
}
การตอบกลับ (ล้มเหลว)
{
"job_id": "a1b2c3d4-...",
"status": "failed",
"error": "Model returned invalid JSON"
}
ตัวอย่าง (JavaScript)
const API = 'https://api.usepolylingo.com/v1'
const headers = {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
}
// 1. ส่ง
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. ตรวจสอบ
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) }
// ตัวเลือก: แสดงความคืบหน้า (queue_position เริ่มนับที่ 1 ละไว้ถ้าไม่อยู่ในคิว)
if (job.queue_position != null) console.log(`ตำแหน่งคิว: ${job.queue_position}`)
}
GET /usage
ต้องการ Authorization: Bearer <api_key> (การค้นหาคีย์มาตรฐาน — ไม่ใช่ เส้นทาง bypass ภายใน)
ส่งคืนการใช้งานโทเค็นสำหรับ เดือนปฏิทินปัจจุบัน สำหรับผู้ใช้ที่ตรวจสอบสิทธิ์แล้ว
การตอบกลับ 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 และ tokens_remaining เป็น null สำหรับ enterprise (โควต้าที่ไม่จำกัดในการรายงาน)
รูปแบบเนื้อหา
ค่าที่รองรับของ format: plain, markdown, json, html
| รูปแบบ | รักษาไว้ | แปล |
|---|---|---|
plain | การขึ้นบรรทัดใหม่ / ย่อหน้า | ข้อความที่มองเห็นทั้งหมด |
markdown | ไวยากรณ์, ลิงก์ (URL ไม่เปลี่ยนแปลง), โค้ดที่ล้อมรอบ (คำตามตัวอักษร) | บทความและข้อความลิงก์ |
json | คีย์, โครงสร้าง, ประเภทที่ไม่ใช่สตริง | เฉพาะค่าที่เป็นสตริง |
html | แท็กและแอตทริบิวต์ | โหนดข้อความและแอตทริบิวต์ที่เหมาะสม (ดู prompts) |
RTL และทิศทางในแอปของคุณ
สำหรับผลลัพธ์ plain และ markdown API จะส่งคืนเฉพาะข้อความที่แปลแล้ว — จะไม่เพิ่ม dir="rtl" หรือองค์ประกอบห่อหุ้ม ตั้งค่าทิศทางข้อความใน UI ของคุณ (CSS direction, แอตทริบิวต์ dir ขององค์ประกอบแม่ หรือเลย์เอาต์ i18n ของเฟรมเวิร์กของคุณ) เมื่อแสดงภาษาอาหรับ, ฮีบรู หรือเปอร์เซีย
สำหรับรูปแบบ html มาร์กอัปที่แปลแล้วอาจรวมถึง dir="rtl" เมื่อเหมาะสมสำหรับเป้าหมาย RTL; ดู formatPrompts.js และการทดสอบ HTML ใน scripts/test-translation.js
การตอบกลับข้อผิดพลาด
ข้อผิดพลาดเป็น JSON เมื่อเป็นไปได้:
{
"error": "invalid_request",
"message": "รายละเอียดที่อ่านเข้าใจง่าย"
}
| HTTP | error | เมื่อใด |
|---|---|---|
| 400 | invalid_request | ฟิลด์ในเนื้อหาหายไป/ไม่ถูกต้อง (เช่น content ว่าง, targets ไม่ถูกต้อง) |
| 400 | invalid_format | format ไม่อยู่ในชุดที่รองรับ |
| 400 | invalid_language | รหัสไม่รู้จักใน targets |
| 401 | invalid_api_key | ขาด/รูปแบบ Authorization ไม่ถูกต้อง, คีย์ไม่รู้จัก, คีย์ถูกเพิกถอน |
| 403 | advanced_not_available | model: "advanced" ในระดับฟรี |
| 429 | token_limit_reached | ขีดจำกัดรายเดือนของระดับฟรีจะถูกเกิน (ตรวจสอบล่วงหน้า) |
| 429 | rate_limit_reached | ขีดจำกัด RPM ต่อหนึ่งนาที (เมื่อเปิดใช้ Redis) |
| 500 | translation_error | ข้อผิดพลาดของโมเดล/เครือข่าย; ปลอดภัยที่จะลองใหม่ |
| 404 | not_found | GET /jobs/:id — งานไม่มีอยู่หรือเป็นของผู้ใช้อื่น |
| 500 | server_error | POST /jobs — ล้มเหลวในการเข้าคิว; ปลอดภัยที่จะลองใหม่ |
GET /usage อาจส่งคืน 500 พร้อมข้อความทั่วไปหากการสืบค้น Supabase ล้มเหลว
โมเดลพื้นฐาน (ข้อมูล)
API เปิดเผยเฉพาะ standard และ advanced รหัสโมเดล OpenAI ที่แท้จริงถูกกำหนดค่าใน api/utils/modelRouter.js และ จะไม่ถูกส่งคืนในคำตอบของ API