エラーコード
ボット API は失敗を HTTP ステータスコード と detailCode で知らせます。
同じステータスコードでも対処が異なる場合があるので、detailCode まで見て分岐します。
detailCode がないレスポンスもあります。 トークン・権限・呼び出し上限は手前のゲートウェイが先に検査するので、
そこで止められた 401・403・429 には detailCode がありません。まずステータスコードで分け、
detailCode はあるときだけ見てください。
レスポンスの形式
ボットランタイム API は RFC 7807 の形式で応答します。
{
"instance": "/v1/live",
"status": 404,
"title": "Not Found",
"detailCode": "OAPI_MNGR_0301",
"message": "The DJ is not broadcasting right now.",
"userId": null,
"extra": null,
"timestamp": 1788407119681
}
| フィールド | 説明 |
|---|---|
detailCode | 対処を決める値です。この値が契約です。 |
message | 人が読むための説明です。文言は変わる可能性があるため、この値で分岐しないでください。またサービス言語と一致する保証はないので、そのままユーザーに表示せず、表示する文言はボット側で用意します。 |
status | HTTP ステータスコードです。 |
title | ステータスの標準文言です(Not Found・Forbidden …)。分岐に使わないでください。 |
instance | 呼び出したパスです。 |
userId・extra | 社内フレームワークが埋める枠です。ボットランタイム API では 常に null で返ります。 |
timestamp | レスポンスを作った時刻です。epoch milliseconds です。 |
userId・extra はボットが使う値ではありません。 それでも null として応答に含まれるため、
スキーマを additionalProperties: false で固めるとここで壊れます。未知のフィールドは無視させてください。
イベントストリームのエラーは SSE フレームで届きます。GET /v1/live/events は text/event-stream で応答するため、接続に失敗してもボディが
data: で始まります。ボディをそのまま JSON としてパースすると落ちます。
HTTP ステータスコードで判別し、ボディが必要なら data: を取り除いてからパースします。
HTTP/2 404
content-type: text/event-stream;charset=UTF-8
data:{"status":404,"detailCode":"OAPI_MNGR_0301","message":"The DJ is not broadcasting right now."}
ボットが遭遇するコード
/v1/oauth で始まる 2 つを除いたすべてのエンドポイントで返るコードです。何があるかは
エンドポイント一覧 にあります。
400 — リクエストを直す必要があります
detailCode | 何が起きたか | どうするか |
|---|---|---|
OAPI_MNGR_0103 | リクエストが正しくありません。ボディが壊れているか、必須フィールド・Content-Type が抜けているか、メソッドが誤っています。 | リクエストの形式を直します。同じリクエストを送り直しても結果は同じです。 |
OAPI_MNGR_0108 | メッセージが空です。空白のみの場合も含みます。 | 送る内容を確認します。同じリクエストを送り直しても結果は同じです。 |
OAPI_MNGR_0109 | メッセージが 200 文字を超えました。絵文字は 2 文字として数えられることがあります。 | 長さを短くします。 |
401 — 人が連携し直す必要があります
detailCode | 何が起きたか | どうするか |
|---|---|---|
| なし | トークンがないか無効です。失効・破棄・DJ の連携解除・アプリ停止がすべてここに入ります。 | refresh を一度試し、それでも 401 なら 止めて DJ に再連携を案内します。 |
OAPI_MNGR_0203 | 上と同じです。トークンが破棄された直後の 1 分以内は、このコードで届くことがあります。 | 上と同じです。 |
401 を無限にリトライしないでください。 連携が切れた状態では、何度送り直しても失敗し続け、呼び出し上限だけを消費します。
理由を分けて知らせないのは、分けるとトークンが存在するかどうかが外部に漏れるためです。 ボットの対処はいずれの場合も再連携で同じです。
403 — 権限または状態で止められています
detailCode | 何が起きたか | どうするか |
|---|---|---|
| なし | このエンドポイントに必要な権限がありません。 | 再同意だけ で済みます。連携自体は生きています。 |
OAPI_MNGR_0208 | 今はこの配信にチャットを送れません。チャットが凍結されているか、ボットがチャット禁止の状態です。 | 2 つのケースは区別できません。少し後に再試行し、それでも通らなければ DJ に案内します。 |
OAPI_MNGR_0209 | 配信に入場できません。DJ がボットをブロックした可能性があります。 | 再同意でも再連携でも解決しません。DJ が直接解除する必要があります。 |
OAPI_MNGR_0211 | ボットアカウントがこの DJ をフォローできません。DJ がボットをブロックした可能性があります。 | 再同意でも再連携でも解決しません。DJ が直接解除する必要があります。 |
403 は detailCode の有無で分けます。 なければ権限不足、あれば配信側の状態(0208・0209・0211)です。
401 と 403 をまとめて扱わないでください。 401 は DJ が最初から連携し直す必要があり、権限不足の 403 は権限を追加で得る
だけで済みます。同じように処理すると、問題のない連携まで切ってしまいます。
404 — 配信中ではありません
detailCode | 何が起きたか | どうするか |
|---|---|---|
OAPI_MNGR_0301 | DJ が今は配信中ではありません。 | エラーではなく 状態 です。イベントストリームならバックオフして接続し直し、取得ならしばらくして呼び直します。 |
429 — 呼び出しが多すぎます
detailCode | 何が起きたか | どうするか |
|---|---|---|
OAPI_MNGR_0302 | チャットの送信が頻繁すぎます。 | 少し待ってから送り直します。 |
OAPI_MNGR_0302 はボットが送りすぎたときだけでなく、その配信のチャットが全体的に
混み合ったとき にも返ります。上限を配信全体で分け合うため、ボット自身の速度を落としても
すぐには解消しないことがあります。
detailCode なしで 429 だけが返る場合は API の呼び出し上限です。 このときは ボディが空です。
ボディをパースすると落ちるので、ステータスコードだけで判別 してください。上限は 2 種類あります。
| 上限 | 超えると | 再び呼ぶとき |
|---|---|---|
| 秒あたり | 429、ボディ・Retry-After なし | 指数バックオフで再試行します。 |
| 1 日あたり | 429、ボディなし · Retry-After あり | Retry-After 秒だけ待ちます。次のリセット(0 時)までです。 |
1 日の上限は アプリ全体と権限ごとに別々に 数え、どちらかひとつでも超えると止められます。どちらに掛かったかは
x-ratelimit-daily-scope ヘッダーで届きます — あればその権限だけ、なければアプリ全体が止められています。
レスポンスヘッダーで先に速度を落とします
上限のヘッダーは正常なレスポンスにも付きます。429 になる前に この値を見て速度を落としてください。
| ヘッダー | 意味 |
|---|---|
x-ratelimit-remaining | 今残っている秒あたりのトークンです。0 なら次のリクエストは 429 です。 |
x-ratelimit-replenish-rate | 1 秒に補充されるトークン数です。 |
x-ratelimit-burst-capacity | 瞬間的にまとめて使える上限です。 |
x-ratelimit-daily-limit | 1 日の呼び出し上限です。 |
x-ratelimit-daily-remaining | 今日残っている呼び出し数です。 |
x-ratelimit-daily-reset | 次のリセット時刻です。epoch seconds です。 |
x-ratelimit-daily-scope | 1 日の上限の 429 にだけ付きます。掛かった権限です。 |
イベントストリーム(GET /v1/live/events)には上限のヘッダーがありません — この経路は呼び出し上限を数えません。
秒あたりの上限は DJ の連携ごとに別々 で、1 日の上限は アプリ合算 です。連携を増やしても 1 日の総量は増えません。
今日の使用量は開発者センターコンソールのアプリ詳細でも確認できます。
500 — サーバーエラーです
detailCode | 何が起きたか | どうするか |
|---|---|---|
OAPI_MNGR_1002 | サーバーエラーです。 | 指数バックオフで再試行します。リクエストを直しても変わりません。 |
どのエンドポイントでも返ることがあります。 502(OAPI_MNGR_2302・OAPI_MNGR_2303)と違い
どこで起きたかは知らせないので、ボットがすることは 指数バックオフでの再試行 ひとつです。
502 — 少し後に再試行します
detailCode | 何が起きたか | どうするか |
|---|---|---|
OAPI_MNGR_2302 | 配信サーバーのエラーです。 | 指数バックオフで再試行します。 |
OAPI_MNGR_2303 | チャットサーバーのエラーです。 | 指数バックオフで再試行します。 |
トークンエンドポイントのエラーは形式が異なります
POST /v1/oauth/token と POST /v1/oauth/revoke は OAuth 標準(RFC 6749)の形式を
そのまま使います。detailCode ではなく error です。全仕様は トークン にあります。
{
"error": "invalid_grant",
"error_description": "code is expired"
}
error | HTTP | 何が起きたか | どうするか |
|---|---|---|---|
invalid_request | 400 | 必須パラメータが不足しています。 | リクエストの形式を確認します。 |
invalid_client | 401 | Client ID または Client Secret が一致しません。 | 資格情報を確認します。 |
invalid_grant | 400 | code または refresh_token が失効しているか、すでに使われています。 | code は 60 秒以内に使う必要があります。refresh_token が失効している場合は DJ に再連携を案内します。 |
unsupported_grant_type | 400 | 対応していない grant_type です。 | authorization_code または refresh_token を使います。 |