コンテンツにスキップ
サポート

Webhook

Webhook を使うと、LabelGrid アカウント内でイベントが発生したときにリアルタイムで通知を受け取れます。Webhook でワークフローを自動化したり、外部システムと連携したりできます。

開発者の方へ: Webhook は API からプログラムで管理することもできます。エンドポイントと例については、LabelGrid API ドキュメントをご覧ください。

  1. Webhook を設定する - URL と、どのイベントを受け取るかを指定します
  2. イベントが発生する - たとえば、リリースがストアに配信されます
  3. LabelGrid が POST リクエストを送信する - あなたのサーバーがイベントデータを受け取ります
  4. システムがそれを処理する - イベントに応じてワークフローを自動化します

  1. 右上のプロフィールアイコンをクリックします
  2. ドロップダウンメニューから Webhooks を選択します

  1. Create Webhook をクリックします
  2. この Webhook を識別するための Name を入力します
  3. 通知を受け取りたい URL を入力します
  4. この Webhook をトリガーする Events を選択します
  5. Create をクリックします

Webhook を作成すると、シークレットキー が発行されます。受信したリクエストが実際に LabelGrid からのものかを検証するために使います。

  • シークレットは安全に保管してください
  • 受信リクエストの署名を検証してください
  • 漏えいした場合は、シークレットを再生成してください

次のイベントを受け取るように Webhook を設定できます。イベント識別子 は、ペイロードの event プロパティと X-Webhook-Event ヘッダーに表示される値です。

イベント識別子説明
delivery.completedリリースが配信先へ正常に配信されたときに発生します
delivery.failed配信先への配信が失敗したときに発生します
takedown.completedテイクダウンのリクエストが完了したときに発生します
release.review.status_changedリリースの審査ステータスが変わったときに発生します
release.preflight.report_ready保留中のリリースの Preflight QC レポートが取得できる状態になったときに発生します
stream_radar.flag_createdStream Radar のフラグが立てられたとき、または解決済みのフラグが新しい検出で再開したときに発生します
stream_radar.flag_resolved検出が止まって Stream Radar のフラグが解決したときに発生します
release.distributedリリースが配信されたときに発生します
payment.statement_ready支払い明細が閲覧できる状態になったときに発生します
transcode.completedトラックの音声トランスコードが正常に完了したときに発生します
transcode.failedトラックのトランスコードが失敗または未完了で終了したときに発生します
distribution.outlet.status_changed配信先ごとの配信ステータスが変化するたびに発生します

1 つの Webhook で複数のイベントを選ぶことも、イベントの種類ごとに別々の Webhook を作ることもできます。

このリストはプログラムから取得することもできます。GET /api/public/Webhook/event-types は、すべてのイベントを、そのペイロードのキーと型を記述した data スキーマとともに返します。これにより、スキーマを厳密に扱うコンシューマーは、受信データのバリデーションを事前に広げておけます。


Webhook の一覧には、次の情報が表示されます。

説明
Name自分で付けた Webhook の名前
URL通知の送信先
Events設定したイベントの数
Status有効か無効か
Success / Fail配信の成功回数と失敗回数
Last TriggeredWebhook が最後に呼び出された時刻
  1. Webhook の行で Edit の操作をクリックします
  2. 名前、URL、イベントを変更します
  3. Save をクリックします

Webhook を削除せずに、有効・無効を切り替えられます。

  • Active - Webhook が通知を受け取ります
  • Inactive - Webhook は一時停止され、通知は送信されません
  1. Webhook の行で Delete の操作をクリックします
  2. 削除を確定します

本番で Webhook に頼る前に、テストしておきましょう。

  1. Webhook の Test の操作をクリックします
  2. LabelGrid が指定の URL にテスト用ペイロードを送信します
  3. エンドポイントがそれを正しく受信・処理できたかを確認します

Webhook の動作を監視し、問題を調査できます。

  1. Webhook の View Logs の操作をクリックします
  2. すべての Webhook 配信の履歴が表示されます

各ログエントリーには、次の情報が表示されます。

項目説明
Event Typeこの配信をトリガーしたイベント
Response Statusあなたのサーバーが返した HTTP ステータスコード
Durationリクエストにかかった時間
Attempt再試行の回数
Timestamp配信が発生した時刻

イベントが発生すると、LabelGrid は指定の URL に JSON ペイロードを含む POST リクエストを送信します。

{
"event": "delivery.completed",
"timestamp": "2026-05-05T10:00:00+00:00",
"webhook_id": "123",
"data": {
// Event-specific data
}
}

timestamp フィールドは ISO 8601 形式です。webhook_id は設定した Webhook の ID で、X-Webhook-Id ヘッダーと一致します。


data オブジェクトの構造は event の種類によって異なります。以下のフィールド型はすべて、ペイロードにシリアライズされた状態の JSON 型です。

リリースの配信が最終的な成功状態に達したときに、配信先ごとに 1 回発生します。

{
"event": "delivery.completed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "complete"
}
}
フィールド説明
distro_queue_idintegerこの配信処理の内部キュー ID
release_idinteger配信されたリリース
label_idintegerリリースが属するレーベル。追加の照会なしにイベントを振り分けられます
release_catstring | nullリリースのカタログ参照番号
outlet_idinteger | null配信先の ID
outlet_namestring | null配信先の表示名(例: "Spotify"
statusstringこのイベントでは常に "complete"

リリースの配信が最終的な失敗状態に達したときに、配信先ごとに 1 回発生します。ペイロードは delivery.completed と同じで、message フィールドが追加されます。

{
"event": "delivery.failed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "error",
"message": "Outlet rejected the delivery: missing ISRC."
}
}
フィールド説明
statusstringerrorfaultrejectedbatch_exception のいずれか
messagestring | null配信先または配信パイプラインからの失敗理由

テイクダウンのリクエストが成功したときに、配信先ごとに 1 回発生します。delivery.completed と同じ構造に、takedown: true のフラグが追加されます。

{
"event": "takedown.completed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "complete",
"takedown": true
}
}

リリースが distributed(配信済み)の配信状態に移行したときに、リリースごとに 1 回発生します。発生するのは distributed への移行時のみで、すでに配信済みのリリースをその後に保存しても発生しません。

{
"event": "release.distributed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"release_title": "Summer EP",
"delivery_status": "distributed"
}
}

リリースが審査ステータスの間を移動するたびに発生します。

{
"event": "release.review.status_changed",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"release_title": "Summer EP",
"previous_status": "to_review",
"new_status": "approved"
}
}
フィールド説明
previous_statusstring変更前のステータス。draftto_reviewapprovedrejectedrequire_changesaudit のいずれか
new_statusstring変更後のステータス。値の範囲は同じ
review_issuesarray(任意)require_changes および rejected への移行時にのみ含まれます。対応が必要な問題が入ります。それ以外の移行ではキー自体が省略されるため、常に存在するとは限らない前提で扱ってください

レビュー前の保留にあるリリースについて、Preflight QC の品質レポートが取得できる状態になったときに発生します。ご利用にはアカウントで Preflight QC アドオンが有効になっている必要があります。

{
"event": "release.preflight.report_ready",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"release_title": "Summer EP",
"generated_at": "2026-07-07T09:58:12+00:00",
"profile": { "name": "quality_report", "version": 2 },
"counts": { "blocking": 1, "informational": 2, "requires_feedback": 1 }
}
}
フィールド説明
release_idintegerレポートが属するリリース
label_idintegerリリースが属するレーベル
release_catstring | nullリリースのカタログ参照番号
release_titlestring | nullリリースのタイトル
generated_atstringチェックが完了した時刻(ISO 8601)。品質レポートエンドポイントの report.generated_at と一致します
profileobjectカウントの算出に用いた品質プロファイル: {name, version}
countsobject集計カウントのみ: {blocking, informational, requires_feedback}requires_feedback のカウントは他の 2 つと重複します

Stream Radar のフラグが立てられたときに発生します。まったく新しいフラグ、または以前に解決したフラグが新しい検出で再開した場合のいずれかです。ご利用にはアカウントで Stream Radar アドオンが有効になっている必要があります。transition フィールドが 2 つのケースを区別します。新しいフラグの場合は published、再び有効になった場合は reopened です。

{
"event": "stream_radar.flag_created",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"flag_id": 4501,
"dsp": "spotify",
"isrc": "USRC12345678",
"release_id": 789,
"track_id": 654,
"severity": "high",
"status": "active",
"transition": "published",
"first_detected_at": "2026-07-06T00:00:00+00:00",
"last_detected_at": "2026-07-07T00:00:00+00:00",
"estimated_affected_streams": 12500,
"published_at": "2026-07-07T09:58:12+00:00",
"resolved_at": null
}
}
フィールド説明
flag_idintegerフラグの安定した識別子。Stream Radar エンドポイントの id と一致します
dspstringパターンが見られたプラットフォーム(例: spotify
isrcstring関与している録音の ISRC
release_idinteger録音が属するリリース
track_idinteger | nullISRC が自分のトラックの 1 つに一意に対応する場合の、その特定のトラック
severitystringlowmedium、または high
statusstringこのイベントでは active
transitionstring新しいフラグの場合は published、解決済みのフラグが再び有効になった場合は reopened
first_detected_atstring | nullこのトラックとプラットフォームでパターンが最初に見られた時刻(ISO 8601)
last_detected_atstring | null最新の検出(ISO 8601)
estimated_affected_streamsinteger | null関与しているストリーム数の推定値
published_atstringフラグが最初にあなたに提示された時刻(ISO 8601)
resolved_atstring | nullフラグが有効な間は null

検出が止まって Stream Radar のフラグが解決したときに発生します。ご利用には Stream Radar アドオンが必要です。フィールドは stream_radar.flag_created と同じ(transition を除く)で、statusresolved に設定され、resolved_at が入ります。

{
"event": "stream_radar.flag_resolved",
"timestamp": "2026-07-14T10:00:00+00:00",
"webhook_id": "123",
"data": {
"flag_id": 4501,
"dsp": "spotify",
"isrc": "USRC12345678",
"release_id": 789,
"track_id": 654,
"severity": "high",
"status": "resolved",
"first_detected_at": "2026-07-06T00:00:00+00:00",
"last_detected_at": "2026-07-12T00:00:00+00:00",
"estimated_affected_streams": 18700,
"published_at": "2026-07-07T09:58:12+00:00",
"resolved_at": "2026-07-14T09:55:03+00:00"
}
}

支払い明細が生成され、閲覧できる状態になったときに発生します。

{
"event": "payment.statement_ready",
"timestamp": "2026-05-18T10:00:00+00:00",
"webhook_id": "123",
"data": {
"payment_request_id": 1024,
"invoice_number": "INV-2026-001",
"period": "2026-04-30",
"amount": 1234.56,
"total_due_usd": 1234.56,
"currency": "USD"
}
}
フィールド説明
payment_request_idinteger内部の支払いリクエスト ID
invoice_numberstring明細の請求書参照番号
periodstring | null対象期間の末日(ISO 8601 の日付形式 YYYY-MM-DD
amountnumbercurrency で表した明細金額
total_due_usdnumberUSD に換算した明細合計
currencystringISO 4217 の通貨コード(既定は USD

トラックの音声トランスコードが完了したときに発生します。transcode.completed は成功時に、transcode.failed はトランスコードが失敗または未完了で終了したときに発生します。どちらも同じペイロード構造を共有します。

{
"event": "transcode.completed",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"release_id": 789,
"label_id": 321,
"track_id": 654,
"transcoder_queue_id": 987,
"status": "complete",
"status_message": "transcode_complete",
"files": [
{ "asset_type_id": 2, "status": "complete" }
]
}
}
フィールド説明
release_idintegerトラックが属するリリース
label_idintegerリリースが属するレーベル
track_idintegerトランスコードされたトラック
transcoder_queue_idintegerトランスコードの内部キュー ID
statusstring生のキューステータス: completeerrorincomplete のいずれか
status_messagestring安全な列挙型の理由コード: transcode_completetranscode_errortranscode_incomplete のいずれか
filesarrayトラックのファイルごとの詳細: トランスコードされたファイルごとに {asset_type_id, status}

配信先ごとの配信ステータスの遷移が発生する たびに 発生します(例: scheduled → transcoding → batched → complete)。delivery.completeddelivery.failedtakedown.completed がカバーする最終状態だけでなく、すべての遷移が対象です。このイベントは設計上、送信量が多くなります。配信先ごとの進行状況をすべて把握したい場合にのみ購読してください。

{
"event": "distribution.outlet.status_changed",
"timestamp": "2026-07-07T10:00:00+00:00",
"webhook_id": "123",
"data": {
"distro_queue_id": 456,
"release_id": 789,
"label_id": 321,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"previous_status": "transcoding",
"status": "batched"
}
}
フィールド説明
distro_queue_idintegerこの配信の内部キュー ID
release_idinteger配信中のリリース
label_idintegerリリースが属するレーベル
release_catstring | nullリリースのカタログ参照番号
outlet_idinteger | null配信先の ID
outlet_namestring | null配信先の表示名
previous_statusstring | null直前のステータス。認識可能な直前のステータスが行になかった場合は null
statusstring新しいステータス

すべての Webhook 配信には署名が付与されており、それが実際に LabelGrid から送られたものかを検証できます。イベントを処理する前に、必ず署名を検証してください。

すべての Webhook の POST リクエストには、次のヘッダーが含まれます。

ヘッダー説明
X-Webhook-Signature生のリクエストボディの HMAC-SHA256。小文字の 16 進数で、アルゴリズムの接頭辞は付きません
X-Webhook-Timestamp配信の ISO 8601 タイムスタンプ(ボディ内の timestamp プロパティと同じ値)
X-Webhook-Eventイベント識別子(例: delivery.completed
X-Webhook-Id配信を受け取る Webhook の ID
User-AgentLabelGrid-Webhooks/1.0
Content-Typeapplication/json
  • アルゴリズム: HMAC-SHA256
  • エンコーディング: 小文字の 16 進数
  • 接頭辞: なし。値は sha256=... ではなく、16 進ダイジェストそのものです
  • 署名対象: 生の JSON リクエストボディ全体(ボディ自体にタイムスタンプがプロパティとして含まれるため、タイムスタンプも暗黙的に署名されます)
  1. JSON のパースや変換を行う前に、生のリクエストボディ を読み取ります。パース済みの JSON を再シリアライズすると、バイト列が変わって署名が一致しなくなることがあります。
  2. HMAC-SHA256(raw_body, your_webhook_secret) を計算し、小文字の 16 進ダイジェストを取得します。
  3. 定数時間比較を使って X-Webhook-Signature と照合します。
  4. (推奨)X-Webhook-Timestamp がリプレイ許容時間より古い場合は、リクエストを拒否します。許容時間は 5 分を目安にしてください。
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$expected = hash_hmac('sha256', $rawBody, $webhookSecret);
if (! hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
// Reject deliveries older than 5 minutes
if (abs(time() - strtotime($timestamp)) > 300) {
http_response_code(401);
exit('Stale delivery');
}
$payload = json_decode($rawBody, true);
// ... process the event
http_response_code(200);
const crypto = require('crypto');
// Express: capture raw body BEFORE any JSON middleware
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const rawBody = req.body; // Buffer
const signature = req.header('X-Webhook-Signature') || '';
const timestamp = req.header('X-Webhook-Timestamp') || '';
const expected = crypto
.createHmac('sha256', webhookSecret)
.update(rawBody)
.digest('hex');
const sigBuf = Buffer.from(signature, 'hex');
const expBuf = Buffer.from(expected, 'hex');
if (sigBuf.length !== expBuf.length || !crypto.timingSafeEqual(sigBuf, expBuf)) {
return res.status(401).send('Invalid signature');
}
if (Math.abs(Date.now() - new Date(timestamp).getTime()) > 5 * 60 * 1000) {
return res.status(401).send('Stale delivery');
}
const payload = JSON.parse(rawBody.toString('utf8'));
// ... process the event
res.sendStatus(200);
});
import hmac, hashlib
from datetime import datetime, timezone
raw_body = request.get_data() # Flask: bytes, before any JSON parsing
signature = request.headers.get('X-Webhook-Signature', '')
timestamp = request.headers.get('X-Webhook-Timestamp', '')
expected = hmac.new(
webhook_secret.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
return ('Invalid signature', 401)
delivery_time = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
if abs((datetime.now(timezone.utc) - delivery_time).total_seconds()) > 300:
return ('Stale delivery', 401)
return ('', 200) # process the event, then ack
  • ハッシュ化の前にボディを再シリアライズする。 JSON を自動でパースするフレームワーク(Express の express.json()、Laravel の既定のリクエストボディなど)は、元のバイト列を失います。まず生のボディを取得してください。
  • 定数時間でない比較(=====)を使う。 タイミング攻撃を受ける可能性があります。常に hash_equals(PHP)、crypto.timingSafeEqual(Node)、hmac.compare_digest(Python)、または使用言語の同等のものを使ってください。
  • sha256= の接頭辞を期待する。 ヘッダーの値は接頭辞のない 16 進ダイジェストそのものです。
  • タイムスタンプのチェックを省く。 これを省くと、漏えいした署名がいつまでもリプレイされる恐れがあります。

制限
リクエストのタイムアウト10 秒
最大ペイロードサイズ64 KB
ユーザーあたりの最大 Webhook 数10

エンドポイントが 10 秒以内に応答しない場合、その配信は失敗として扱われ、再試行されます。

エンドポイントが 2xx 以外のステータスを返すかタイムアウトした場合、LabelGrid は指数バックオフで再試行します。

試行再試行までの待機時間
1 → 230 秒
2 → 31 分
3 → 42 分
4 → 54 分
5 → 68 分
6 → 716 分
7 → 832 分
8 → 964 分
9 → 10128 分

各間隔には 0〜30 秒のジッターが含まれます。10 回試行しても成功しない場合(合計で約 4.5 時間が経過)、その配信は恒久的な失敗として記録され、それ以上の再試行は行われません。

Webhook のエンドポイントで失敗が続くと(成功した配信を一度も挟まずに配信失敗が繰り返されると)、LabelGrid はその Webhook を自動的に無効化し、明らかにイベントを受信できないエンドポイントへの再試行を停止します。失敗回数は 配信が成功するたびに リセットされるため、たまに起きる一時的な不調で Webhook が無効化されることはありません。無効化されるのは、継続的で途切れない失敗が続いた場合だけです。

この方法で Webhook が無効化されると、その所有者にメールが送信されます。メールには、Webhook の名前とそのエンドポイントの URL、そして無効化のきっかけとなった失敗の種類(たとえば接続タイムアウトや HTTP エラーの繰り返しなど)が記載されます。

再有効化はセルフサービスです。エンドポイントを修正したうえで、プロフィール → Webhooks から Webhook を再びオンに切り替えてください。無効化された Webhook を再有効化すると、失敗回数がリセットされます。Webhook の一覧には各 Webhook の有効状態と現在の失敗回数が表示されるため、問題のあるエンドポイントを一目で見つけられます。

信頼性のためのベストプラクティス

Section titled “信頼性のためのベストプラクティス”
  • 2xx レスポンス を素早く(10 秒以内に)返す
  • 確認応答を返したあとで、データを非同期に処理する
  • すべてのリクエストで署名を検証する(Webhook 署名の検証 を参照)
  • Webhook の一覧で失敗回数を監視する
  • イベントの取りこぼしを調査するときは、配信ログを確認する

  • リリースが公開されたら Slack にメッセージを送る
  • 配信が失敗したらチームにメールを送る
  • 社内ダッシュボードを更新する
  • リリースが配信されたらマーケティングキャンペーンを開始する
  • 新しいコンテンツが利用可能になったらウェブサイトを更新する
  • 外部のプロジェクト管理ツールにステータスを同期する
  • 配信失敗を即座にアラートで受け取る
  • 配信の進捗をリアルタイムで追跡する
  • 審査ステータスの変化を監視する

Webhook がイベントを受け取らない

Section titled “Webhook がイベントを受け取らない”
  1. ステータスを確認する - Webhook は Active になっていますか?
  2. URL を確認する - エンドポイントはインターネットからアクセスできますか?
  3. イベントを確認する - 正しいイベントが選択されていますか?
  4. ログを確認する - エラーは記録されていませんか?
  1. エンドポイントを確認する - 200 OK を返していますか?
  2. 応答時間を確認する - タイムアウト内に応答していますか?
  3. エラーメッセージを確認する - 何が失敗していますか?
  4. 手動でテストする - テスト用 Webhook を送ってみる

Webhook シークレットが漏えいした場合:

  1. Webhook の設定で Regenerate Secret をクリックします
  2. 新しいシークレットでアプリケーションを更新します
  3. 古いシークレットはただちに無効になります

Webhook についてご不明な点がありましたら、サポートチームにお問い合わせください

LabelGridはまだお使いではありませんか?

いまお読みいただいた内容は、すべて当社のプラットフォームでご利用いただけます。

LabelGridでできることを見る →