コンテンツにスキップ

ウェブフック

ウェブフックは、投稿の公開成功、失敗、返信の送信など、バックグラウンドの非同期タスクが完了した際にリアルタイムの HTTP POST 通知を配信します。


メソッドパス説明必要なスコープ
POST/v1/brand/webhooks/subscriptions新しいウェブフックエンドポイントを登録webhooks:write または *
GET/v1/brand/webhooks/subscriptions登録済みのウェブフック購読を一覧表示webhooks:read または *
DELETE/v1/brand/webhooks/subscriptions/{id}ウェブフック購読を削除webhooks:write または *

🔔 サポートされているイベントタイプ

Section titled “🔔 サポートされているイベントタイプ”
イベント名トリガー条件
sns.publish.succeeded投稿が対象のソーシャルネットワークに正常に公開された
sns.publish.failed投稿の公開に失敗した (エラーコードと再試行の適格性を含む)
sns.publish.blocked_entitlementクォータ制限またはプラン期限切れにより公開がブロックされた
sns.reply.succeeded返信コメントが正常に投稿された
sns.reply.failed返信コメントの送信に失敗した
sns.provider.notification_received外部 SNS プロバイダーからリアルタイムのウェブフックを受信した

📦 ウェブフックペイロードの例 (sns.publish.succeeded)

Section titled “📦 ウェブフックペイロードの例 (sns.publish.succeeded)”
{
"event_id": "evt_01jm8za2example",
"event_type": "sns.publish.succeeded",
"schema_version": 1,
"occurred_at": "2026-08-16T03:30:00Z",
"producer": "ankk.sns",
"brand_ref": "brand_01jm8v4k9example",
"idempotency_key": "launch-2026-001",
"trace_id": "trc_9a8b7c6d",
"data": {
"content_id": "content_01jm8za2example",
"publish_job_id": "job_01jm8za2jobexample",
"sns_type": "instagram",
"connection_id": "conn_01jm8x9k2example",
"provider_post_id": "18029384756102938",
"permalink": "https://www.instagram.com/p/C-example/"
}
}

ウェブフックのリクエストには、カスタム検証ヘッダーが含まれています。

  • Social-Webhook-Signature: 署名ペイロード (t=1723780000,v1=hex_signature)
  • Social-Webhook-Timestamp: Unix タイムスタンプ (秒)
  • Social-Webhook-Id: イベント識別子
import crypto from 'node:crypto';
export function verifyWebhookSignature(
rawBody: string,
signatureHeader: string,
timestampHeader: string,
secret: string
): boolean {
const signedPayload = `${timestampHeader}.${rawBody}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expectedSignature)
);
}
import hmac
import hashlib
def verify_webhook_signature(raw_body: bytes, signature: str, timestamp: str, secret: str) -> bool:
signed_payload = f"{timestamp}.".encode('utf-8') + raw_body
expected = hmac.new(secret.encode('utf-8'), signed_payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(signature, expected)

[!CAUTION] 署名検証には、解析される前の生のリクエストボディ (raw request body) を使用する必要があります。