エピソードの管理

番組オーナーが利用するREST APIです。作成・更新はLISTENから配信している番組が対象です。外部RSS番組も一覧・詳細を取得できます。無料を含む全プランで利用でき、メディアのアップロード・限定公開には各プランの利用枠が適用されます。

認証とエンドポイント

Bearerトークンに取得は read、作成は create、更新は update 権限が必要です。URLには番組・エピソードのIDを指定します。

GET   /api/v1/podcasts/{podcast}/episodes
POST  /api/v1/podcasts/{podcast}/episodes
GET   /api/v1/episodes/{episode}
PATCH /api/v1/episodes/{episode}

一覧の first は1〜100(既定50)、after は前回の meta.next_cursor です。ID降順で、下書き・予約公開も含みます。meta.has_more で続きの有無を確認できます。

作成

ファイルアップロードで音声またはビデオを送信し、返された path を指定します。大容量ファイルにはマルチパートを利用できます。

curl -X POST "https://listen.style/api/v1/podcasts/$PODCAST_ID/episodes" \
  -H "Authorization: Bearer $LISTEN_API_TOKEN" \
  -H 'Accept: application/json' -H 'Content-Type: application/json' \
  -d '{"title":"第8回","visibility":"public","status":"draft","audio_path":"graphql-tmp/UPLOAD.mp3","season_number":1,"episode_number":8}'

title と visibility は必須です。音声は audio_path または media.audio_path、ビデオは media.video.path と任意の media.video.thumbnail_path で指定します。audio_path と media は併用できません。画像は image_path、ラウドネス正規化は normalize_loudness で指定できます。

visibility は public / limited / private / followers_only / paid_only。status は draft / published / scheduled(省略すると published)です。予約公開は status: "scheduled" と scheduled_at: "2026-11-01T09:00:00+09:00" のようにタイムゾーン付き日時を指定してください。メディア処理は非同期で、受付成功は配信準備完了を意味しません。

成功は 201。同じアップロードパスによる再送は48時間の冪等性記録で同じエピソードを返します。再試行時はパスを変えないでください。別エピソードを作るときは新しいアップロードを使います。

取得と部分更新

詳細取得・更新の応答例です(日時はUTC)。

{"data":{"id":"EPISODE_ID","podcast_id":"PODCAST_ID","guid":"GUID","title":"第8回","description":"説明","slug":"episode-8","visibility":"public","status":"scheduled","season_number":1,"episode_number":8,"published_at":"2026-11-01T00:00:00+00:00","scheduled_at":"2026-11-01T00:00:00+00:00","updated_at":"2026-10-15T00:00:00+00:00","revision":"64-character-revision"}}

published_at は保存されている公開日時で、予約中は未来の日時です。scheduled_at は予約中のみ日時、それ以外は null です。

curl -X PATCH "https://listen.style/api/v1/episodes/$EPISODE_ID" \
  -H "Authorization: Bearer $LISTEN_API_TOKEN" \
  -H 'Accept: application/json' -H 'Content-Type: application/json' \
  -d '{"description":"新しい説明","expected_revision":"取得したrevision"}'

省略した項目は維持します。 description・season_number・episode_number は明示的な null で消去できます。予約日時の消去は status: "draft" と scheduled_at: null を同時に送ってください。slug はURL用の半角英数字とハイフン(最大100文字)。expected_revision は任意ですが、取得後の編集競合を検出するため指定を推奨します。不一致なら 409 で変更しません。

字幕の取り込み済み確認

一覧・詳細・作成・更新の応答には transcript_imported_at が含まれます。最後に字幕をアップロードした日時をUTCのISO 8601形式(例:2026-10-16T06:00:00+00:00)で返します。日時があれば取り込み済みの印があり、自動文字起こしや出演者変更による自動話者分離の上書きから保護されています。再アップロードが成功するたびに日時が更新されます。

null は取り込み記録がないことを表します。字幕がない場合、自動生成の場合、印の導入前にアップロードした場合を含むため、null だけで字幕の有無や生成元は判定できません。無料を含む全プランで、番組オーナーが read 権限で確認できます。一覧でも日時を返すため、字幕本文をダウンロードせず複数回分をまとめて照合できます。字幕アップロードの応答でも同じ項目を返します。

制限とエラー

API共通の利用者ごと毎分60回の制限が適用されます。401 未認証、403 権限不足、404 対象なし、409 更新競合、422 不正な入力・外部RSS番組への作成更新・利用枠不足、429 回数制限です。429 は Retry-After に従って再試行してください。

既存GraphQLは引き続き利用できます。ただし従来の updateEpisode は、説明・話数・シーズンを省略すると空になる動作を維持しています。RESTのPATCHとは異なります。新しい連携にはRESTを推奨し、既存連携を予告なく停止する方針ではありません。