提供条件

1. 概要と認証方式

Advanced TTS API は 感情表現や読み上げスタイル指定に対応した、より自然な音声合成エンドポイントです。非同期ジョブ方式で、POST してジョブ ID を受け取り → ポーリングで結果を取得します。

現在の提供形態: Advanced TTS API は Beta 版として提供しています。公開エンドポイントは POST /api/advanced-tts/(ジョブ作成)と GET /api/advanced-tts/jobs/{job_id}/(ポーリング)です。認証は 標準 TTS API と同じ token ヘッダー、またはログイン済みのセッション cookie + CSRF トークンです。

下記サンプルは、token ヘッダーでジョブを投入する流れです。Web UI と同じセッション認証で利用する場合は、ログイン済み cookie と X-CSRFToken を送信してください。

2. エンドポイント・リクエスト仕様

POST https://ondoku3.com/api/advanced-tts/
GET https://ondoku3.com/api/advanced-tts/jobs/{job_id}/

ヘッダー

ヘッダー値
Content-Typeapplication/json
tokenアクセストークン(64 文字)。token 認証時は CSRF 不要
X-Job-Tokenジョブ参照トークン。GET ポーリング時は POST レスポンスの job_token をこのヘッダーで送信
Cookiesessionid=...; csrftoken=...(セッション認証時)
X-CSRFTokencookie の csrftoken と同じ値(セッション認証時)
Refererhttps://ondoku3.com/ja/advanced-tts-beta/(セッション認証時)

ボディ(JSON)

フィールド型必須説明
textstring必須読み上げるテキスト(10 文字以上。API の受付上限は無料 400 文字 / 有料 3,000 文字)
voicestring任意音声名(下記リストから指定)。デフォルト: Ruby
tonestring任意読み上げスタイル(例: warm and friendly, storytelling)。最大 100 文字
speednumber任意0.5 〜 1.5(デフォルト 1.0)
pitchnumber任意-1.0 〜 1.0(デフォルト 0.0)
modelstring任意flash(高速) / pro(高品質)
seedinteger任意声色を固定する乱数シード(-2147483648 〜 2147483647)

?token={job_token} クエリパラメータでのポーリングはサポートされません。ジョブステータス確認は必ず X-Job-Token ヘッダーで送信してください。

3. サンプルコード(ジョブ送信 → ポーリング)

# 1) TTS ジョブを投入
JOB=$(curl -s \
  -X POST https://ondoku3.com/api/advanced-tts/ \
  -H "Content-Type: application/json" \
  -H "token: $ONDOKU_TOKEN" \
  -d '{"text":"こんにちは、音読さんです。","voice":"Ruby","tone":"warm and friendly"}')
JOB_ID=$(echo "$JOB" | jq -r .job_id)
JOB_TOKEN=$(echo "$JOB" | jq -r .job_token)
sleep "$(echo "$JOB" | jq -r '.min_poll_after_ms / 1000')"

# 2) ジョブ完了までポーリング
while :; do
  R=$(curl -s \
    -H "X-Job-Token: ${JOB_TOKEN}" \
    "https://ondoku3.com/api/advanced-tts/jobs/${JOB_ID}/")
  STATUS=$(echo "$R" | jq -r .status)
  echo "status: $STATUS"
  [ "$STATUS" = "succeeded" ] && break
  [ "$STATUS" = "failed" ] && { echo "$R"; exit 1; }
  sleep "$(echo "$R" | jq -r '(.poll_after_ms // 3000) / 1000')"
done

# 3) MP3 をダウンロード
URL=$(echo "$R" | jq -r .url)
curl -L "$URL" -o output.mp3
import os
import time
import requests

TOKEN = os.environ["ONDOKU_TOKEN"]

# 1) ジョブを投入
res = requests.post(
    "https://ondoku3.com/api/advanced-tts/",
    headers={
        "Content-Type": "application/json",
        "token": TOKEN,
    },
    json={
        "text": "こんにちは、音読さんです。",
        "voice": "Ruby",
        "tone": "warm and friendly",
    },
    timeout=30,
)
res.raise_for_status()
job = res.json()
job_id, job_token = job["job_id"], job["job_token"]
time.sleep(job["min_poll_after_ms"] / 1000)

# 2) ポーリング
while True:
    r = requests.get(
        f"https://ondoku3.com/api/advanced-tts/jobs/{job_id}/",
        headers={"X-Job-Token": job_token},
        timeout=10,
    ).json()
    print("status:", r["status"])
    if r["status"] == "succeeded":
        break
    if r["status"] == "failed":
        raise RuntimeError(r)
    time.sleep(r.get("poll_after_ms", 3000) / 1000)

# 3) MP3 をダウンロード
mp3 = requests.get(r["url"], timeout=60).content
with open("output.mp3", "wb") as f:
    f.write(mp3)
print(f"saved: output.mp3 ({len(mp3)} bytes)")
import { writeFile } from "node:fs/promises";

const TOKEN = process.env.ONDOKU_TOKEN!;

// 1) ジョブを投入
const submit = await fetch("https://ondoku3.com/api/advanced-tts/", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    token: TOKEN,
  },
  body: JSON.stringify({
    text: "こんにちは、音読さんです。",
    voice: "Ruby",
    tone: "warm and friendly",
  }),
});
type AdvancedTTSJobResponse = {
  job_id: string;
  job_token: string;
  status: "pending" | "running" | "succeeded" | "failed";
  min_poll_after_ms: number;
  poll_url: string;
};

type AdvancedTTSPollResponse = {
  job_id: string;
  status: "pending" | "running" | "succeeded" | "failed";
  poll_after_ms?: number;
  url?: string;
  pk?: number;
  seed?: number;
  code?: string;
  error?: string;
};

const job = (await submit.json()) as AdvancedTTSJobResponse;

// 2) ポーリング
let result: AdvancedTTSPollResponse;
await new Promise((resolve) => setTimeout(resolve, job.min_poll_after_ms));
while (true) {
  const r = await fetch(`https://ondoku3.com/api/advanced-tts/jobs/${job.job_id}/`, {
    headers: { "X-Job-Token": job.job_token },
  }).then((res) => res.json() as Promise);
  console.log("status:", r.status);
  if (r.status === "succeeded") { result = r; break; }
  if (r.status === "failed") throw new Error(JSON.stringify(r));
  await new Promise((resolve) => setTimeout(resolve, r.poll_after_ms ?? 3000));
}

// 3) MP3 をダウンロード
if (!result.url) throw new Error("audio URL is missing");
const mp3 = Buffer.from(await (await fetch(result.url)).arrayBuffer());
await writeFile("output.mp3", mp3);
console.log(`saved: output.mp3 (${mp3.byteLength} bytes)`);

4. レスポンス例

POST レスポンス(202 Accepted):

{
  "job_id": "YOUR_JOB_ID",
  "job_token": "YOUR_JOB_TOKEN",
  "status": "pending",
  "min_poll_after_ms": 4550,
  "poll_url": "/api/advanced-tts/jobs/YOUR_JOB_ID/"
}
フィールド型説明
job_idstringジョブ ID(UUID)
job_tokenstringこのジョブのポーリングに必要な参照トークン
statusstring投入直後の状態。通常は pending
min_poll_after_msnumber初回ポーリングまで待つ推奨ミリ秒
poll_urlstringポーリング先の相対 URL。アクセス時は POST レスポンスの job_token を X-Job-Token ヘッダーで送信する

GET ポーリング(処理中):

{
  "job_id": "YOUR_JOB_ID",
  "status": "pending",
  "poll_after_ms": 1000
}

GET ポーリング(成功時):

{
  "job_id": "YOUR_JOB_ID",
  "status": "succeeded",
  "url": "https://storage.googleapis.com/ondoku3/voice/...",
  "pk": 12345,
  "seed": 123456789
}

GET ポーリング(失敗時):

{
  "job_id": "YOUR_JOB_ID",
  "status": "failed",
  "code": "internal_error",
  "error": "内部サーバーエラーが発生しました"
}
フィールド型説明
job_idstringジョブ ID(UUID)
statusstringpending / running / succeeded / failed
poll_after_msnumber処理中に返る、次回ポーリングまで待つ推奨ミリ秒
urlstring成功時のみ返る音声ファイル URL
pknumber成功時のみ返る生成履歴(Sentence)の ID
seednumberseed が保存されている場合のみ返る、生成に使われた乱数シード
codestring失敗時のみ返るエラーコード(一覧は エラー・案内レスポンス)
errorstring失敗時のみ返るエラーメッセージ

5. 音声リスト(25 種類)

Advanced TTS API の voice パラメータに指定できる音声名 25 種類。各音声のサンプルは 音声サンプル記事で試聴できます。

女性(12 音声)

音声名読み仮名
Annaアンナ
Chloeクロエ
Ellisエリス
Emmaエマ
Floraフローラ
Irisアイリス
Lenaレナ
Lunaルナ
Misaミサ
Rubyルビー
Sophieソフィー
Tinaティナ

男性(13 音声)

音声名読み仮名
Ashアッシュ
Chrisクリス
Edenエデン
Grayグレイ
Hopeホープ
Hugoヒューゴ
Kaiカイ
Leoレオ
Noahノア
Reidリード
Royロイ
Samサム
Yannヤン

6. エラー・案内レスポンス

エラーは JSON の code(エラーコード)と error(メッセージ)で返ります(403 の CSRF エラーと 405 を除く)。HTTP ステータスだけでなく code を見て処理してください。ジョブ投入後の失敗は、ポーリング結果の status=failed で返ります。Web UI では code に応じて案内音声を再生しますが、API レスポンス自体に案内音声 URL は含まれません。

ジョブ作成 POST /api/advanced-tts/

HTTPcode原因
400invalid_tokentoken ヘッダーが 64 文字でない、または一致する有効なユーザーがない
400invalid_json本文が JSON として読めない
400validation_errortext が 10 文字未満 / 絵文字だけ / 同じ文字が 20 文字以上続く
400invalid_speed / invalid_pitch数値でない、または範囲外
400invalid_temperaturetemperature 項目(この文書の対象外。送る必要はありません)を送り、値が数値でないか 0 / 0.5 / 0.7 / 1.0 以外
400invalid_seedseed が整数でない、または範囲外
400invalid_modelmodel が flash / pro 以外
400client_ip_unresolvedtoken なし・未ログインの利用で、接続元 IP を確定できない
400text_too_long受付上限(無料 400 文字 / 有料 3,000 文字)を超えている
400invalid_voice不明な voice 名
400content_policy_violation利用ポリシーにより読み上げできないテキスト
400invalid_requestその他の入力エラー(ユーザー辞書で置き換えた後の本文が上限を超えた場合など)
403(HTML)token ヘッダーなしのセッション認証で、CSRF トークンが不一致 / 未ログイン
405(本文なし)POST 以外のメソッド
429quota_exceeded利用可能な文字数が不足。available(残りの文字数)も返る
429rate_limitedレート制限超過(文字数上限・レート制限)。retry_after 秒(Retry-After ヘッダーも同じ値)待って再試行
500service_not_configuredサーバー側の設定不備
500internal_errorサーバー側エラー(時間を置いて再試行)
503unsupported_location音声合成を提供できない地域からの処理。互換のため error_code(UNSUPPORTED_LOCATION)も返る
503tts_retry_exhausted一時的に受け付けられない(時間を置いて再試行)

ポーリング GET /api/advanced-tts/jobs/{job_id}/

HTTPcode原因
200status=failedジョブの失敗。HTTP ステータスではなく JSON の status / code を確認(code は下の表)
403forbiddenX-Job-Token がジョブと一致しない(ログイン済みセッションでは、自分のジョブでない)
404not_foundジョブが存在しない
405(本文なし)GET 以外のメソッド

ジョブの状態と失敗時の code

status は pending(処理待ち)→ running(処理中)→ succeeded(完了)または failed(失敗)と進みます。failed の時の code は次のとおりです。音声生成の処理から下表以外の code が返ることもあるため、知らない code も失敗として扱ってください。

code原因
content_policy_violation利用ポリシーにより読み上げできないテキスト。本文を変えて再投入
unsupported_location音声合成を提供できない地域からの処理
tts_retry_exhausted一時的に生成できなかった。時間を置いて再投入
invalid_request生成時の入力エラー
job_timeout生成に時間がかかりすぎて打ち切った。再投入
enqueue_failedジョブを処理待ちに入れられなかった
user_unavailable生成中にアカウントが退会・削除された
internal_errorサーバー側エラー

7. 文字数上限・レート制限

1 リクエストの文字数上限

プランAPI の受付上限
無料400 文字
有料3,000 文字

補足: Web UI の入力欄は、有料プランでも既定では 1,000 文字までの表示です(Beta 設定の文字数拡張で 3,000 文字まで広がります)。API はこの設定に関係なく、有料プランなら 3,000 文字まで受け付けます。

レート制限

現在適用している制限: ジョブ作成 POST /api/advanced-tts/ は、接続元 IP ごとに 60 秒あたり 10 回までです(同じ IP から複数のトークンを使っても共有)。超えると HTTP 429 の rate_limited を返し、retry_after と Retry-After ヘッダーに待つ秒数が入ります。

このほかに、Advanced TTS 専用のレート制限は、現在 shadow mode で観測中です。この専用制限ではまだリクエストを遮断せず、超過しても 429 は返しません。正式適用後は、下記の値を超えた場合に rate_limited の JSON と Retry-After ヘッダーを返す予定です。

対象単位予定制限補足
ジョブ作成 POST /api/advanced-tts/ユーザー ID(未ログイン時は IP)30 回 / 60 秒
180 回 / 1 時間
有料・無料などのユーザーステータスでは分けません
ステータス確認 GET /api/advanced-tts/jobs/{job_id}/ログインユーザーまたはジョブ参照トークン + job_id120 回 / 60 秒同じジョブへの過剰ポーリングを抑制します
ステータス確認の合計ログインユーザーまたはジョブ参照トークン600 回 / 60 秒複数ジョブの同時ポーリングを抑制します。API トークン認証またはログイン済みセッションで作成したジョブを X-Job-Token ヘッダーで確認する場合、所有者ユーザーではなくジョブ参照トークン単位で扱います
存在しないジョブ / 権限なしジョブの確認IP30 回 / 60 秒不正な job_id の総当たりを抑制します

既存の文字数不足は quota_exceeded の JSON で返ります。現行の汎用レート制限に当たった場合は rate_limited の JSON で返ります。Web UI では案内音声を再生しますが、API クライアントは HTTP ステータスだけでなく JSON の code を見て処理してください。

429 のレスポンス例:

{
  "code": "rate_limited",
  "error": "レート制限を超えました。しばらく経ってから再試行してください。",
  "retry_after": 55
}

プラン詳細・価格は 料金ページ、利用条件は 利用規約 を参照してください。

8. 使用上の注意事項

認証情報の管理

入力テキスト・生成音声の取り扱い

リトライ指針

HTTP / 状況対応
429 (Rate limit)retry_after 秒、または最低 5 秒待ってから再試行
5xxexponential backoff(2 秒 → 4 秒 → 8 秒、最大 3 回)
4xx(400・403 等)リトライしない。CSRF トークンや voice 名を確認
ジョブ status=failedcode を確認。生成失敗は同じ seed でリトライしても同じ結果になることがあるため、seed を変えて再試行
ジョブが pending のまま長時間5 分以上 pending の場合はサーバー側で滞留している可能性。新規ジョブとして再投入

ポーリング推奨間隔

同時実行・並列度

タイムアウト推奨値

音声ファイル URL の有効期限

CORS(ブラウザから直接叩く場合)

コンテンツポリシー

以下の用途での利用を禁止します:

詳細は 利用規約 を確認してください。

生成音声の著作権・商用利用

9. SLA(稼働率)

Advanced TTS API(Beta)は、月間稼働率 98.0% を SLA として提供します。ジョブの作成(POST)とポーリング(GET)の両方のリクエストを数え、音声生成の失敗(ポーリング結果のジョブの status が failed)は停止に数えません。

稼働率の数え方・停止に含めないもの・SLA を下回った場合の扱いは両 API に共通で、標準 TTS API の SLA 節 を正本とします。SLA の対象は稼働率のみで、応答時間は含みません。

10. 変更履歴

互換性を壊す変更(項目の削除・型や意味の変更・エンドポイントの廃止など)は、実施の 30 日前にこの節で告知します。項目や声の追加など互換を保つ主な変更も、実施後にこの節に記録します(事前告知はしません)。緊急のセキュリティ対応は例外です。

日付内容
2026-10-02Advanced TTS API を公式 API(Beta 版)として提供開始し、SLA(月間稼働率 98.0%)を設定。互換性を壊す変更は 30 日前にこの節で告知するルールを開始

11. 問い合わせ前に

不具合や予期しない挙動を確認したら、まず以下を試してください:

  1. エラー・案内内容を確認: エラー・案内レスポンス 表で対応を確認
  2. Web UI で再現するか確認: Advanced TTS ページ で同じテキスト・voice・tone を試す
  3. CSRF / Cookie を確認: 403 が返る場合は再ログインしてセッションを取り直す
  4. 残文字数を確認: 設定ページ で月間文字数の消費量を確認
  5. 最小ペイロードで疎通テスト: {"text":"これは疎通テストです。","voice":"Ruby"}(text は 10 文字以上) で 202 が返るか
  6. seed を変えて再試行: 生成失敗は seed 依存の可能性があるため、seed を変えるか省略

上記で解消しない場合は お問い合わせ からご連絡ください。再現に必要な以下の情報を添えていただけるとスムーズです:

仕様の変更について: API 仕様の変更は 変更履歴 に記載します。互換性を壊す変更は実施の 30 日前に告知します。