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 プランのみ、推定値が残りの月間割当(FREE_TIER_MONTHLY_TOKENS、デフォルト 100000)を超える場合は 429 / token_limit_reached でリクエストを拒否します。有料プランはenforceTokenCapの事前チェックでブロックされませんが、使用状況はログに記録されます。
レート制限: Upstash Redisが設定されている場合(UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN、URLにプレースホルダー your-instance が含まれていない)、プランごとに1分あたりの制限が適用されます:無料 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 }
]
}
POST /translate
Authorization: Bearer <api_key> が必要です。
単一の content 文字列を targets にリストされたすべての言語に翻訳します。モデルは、要求された言語コードを正確にキーとし、翻訳された文字列を値とする単一のJSONオブジェクトを返します(formatPrompts.js参照)。
リクエストボディ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
content | 文字列 | はい | 翻訳対象の空でない文字列。 |
targets | 文字列[] | はい | 有効な言語コードの空でない配列(最大36)。 |
format | 文字列 | いいえ | plain、markdown、json、html のいずれか。省略時は content から自動検出されます。 |
source | 文字列 | いいえ | モデルへのソース言語のヒント;任意。 |
model | 文字列 | いいえ | 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> が必要です。
各アイテムを逐次的に処理します(アイテムごとに1回のモデル呼び出し)。いずれかのアイテムが失敗した場合、APIは 500 を返し、そのリクエストの部分的な結果は返しません。
リクエストボディ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
items | 配列 | はい | 各要素:id(文字列)、content(文字列)、任意の format。 |
targets | 文字列[] | はい | /translate と同じルール。 |
source | 文字列 | いいえ | 任意のソース言語ヒント。 |
model | 文字列 | いいえ | 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 でポーリングしてください。
長いMarkdownや多くのターゲット言語など、大きなドキュメントを翻訳する場合で、リクエスト時間がHTTPクライアントやプロキシのタイムアウトを超える可能性がある場合は、このエンドポイントを POST /translate の代わりに使用してください。
リクエストボディ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
content | 文字列 | はい | 翻訳対象の空でない文字列。 |
targets | 文字列[] | はい | 有効な言語コードの空でない配列(最大36)。 |
format | 文字列 | いいえ | plain、markdown、json、html のいずれか。省略時は自動検出。 |
source | 文字列 | いいえ | ソース言語のヒント;任意。 |
model | 文字列 | いいえ | 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(`Queue position: ${job.queue_position}`)
}
GET /usage
Authorization: Bearer <api_key> が必要です(標準のキー検索 — 内部バイパス専用パスではありません)。
認証ユーザーの現在の暦月のトークン使用量を返します。
レスポンス 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 は enterprise では null です(レポートでの無制限割当)。
コンテンツフォーマット
サポートされている format の値:plain、markdown、json、html。
| フォーマット | 保持されるもの | 翻訳されるもの |
|---|---|---|
plain | 改行 / 段落 | すべての可視テキスト |
markdown | 構文、リンク(URLは変更なし)、フェンスコード(逐語的) | 散文およびリンクテキスト |
json | キー、構造、非文字列型 | 文字列値のみ |
html | タグと属性 | テキストノードおよび適切な属性(プロンプト参照) |
RTLとアプリでの方向設定
plain と markdown の出力では、APIは翻訳テキストのみを返し、dir="rtl" やラッパー要素は追加しません。アラビア語、ヘブライ語、ペルシャ語を表示する際は、UIでテキスト方向(CSSの direction、親要素の dir 属性、またはフレームワークのi18nレイアウト)を設定してください。
html フォーマットでは、翻訳されたマークアップにRTLターゲットに適した場所で dir="rtl" が含まれる場合があります。詳細はformatPrompts.jsおよびscripts/test-translation.jsのHTMLテストを参照してください。
エラー応答
可能な場合、エラーは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 | 1分あたりのRPM制限(Redis有効時) |
| 500 | translation_error | モデル/ネットワーク障害;再試行可能 |
| 404 | not_found | GET /jobs/:id — ジョブが存在しないか他ユーザーのもの |
| 500 | server_error | POST /jobs — キュー登録失敗;再試行可能 |
GET /usage はSupabaseクエリ失敗時に一般的なメッセージで 500 を返すことがあります。
基盤モデル(参考情報)
APIは standard と advanced のみを公開しています。実際のOpenAIモデルIDはapi/utils/modelRouter.jsで設定されており、APIレスポンスには返されません。