Webhook
1tokens は、サブスクライブしたイベントが発生すると、コンソールで登録した HTTPS URL に署名付き POST リクエストを送信します。「Webhook」ページでエンドポイントを作成し、受け取りたいイベントにチェックを入れてください。新しいエンドポイントは 30 秒以内に有効になります。
イベント一覧
モデル
| タイプ | 名称 | data フィールド |
|---|---|---|
model.listed | モデル公開 | model tenant_id previous_status status actor |
model.delisted | モデル非公開 | model tenant_id previous_status status actor |
model.deprecated | モデル非推奨 | model previous_status status actor |
model.price.changed | 販売価格変更 | model tenant_id pricing_status sale_price_mode multiplier price changes actor |
model.user_price.changed | 専用価格変更 | model user_id multiplier changes actor |
model.updated | モデル更新 | model changes actor |
API Key
| タイプ | 名称 | data フィールド |
|---|---|---|
api_key.created | Key 作成 | api_key actor |
api_key.updated | Key 更新 | api_key changes actor |
api_key.revoked | Key 失効 | api_key previous_status status actor |
api_key.expired | Key 期限切れ | api_key actor |
api_key.quota.exhausted | 割当上限 | api_key quota_limit_usd consumed_usd actor |
api_key.rate_window.exceeded | 期間上限超過 | api_key window limit_usd consumed_usd actor |
アカウント
| タイプ | 名称 | data フィールド |
|---|---|---|
account.balance.low | 残高不足 | account threshold_usd request_id actor |
account.balance.exhausted | 残高ゼロ | account reason request_id actor |
account.credit.topup | 入金 | account amount_usd amount_credits source order_no actor |
account.credit.adjusted | 残高調整 | account delta_usd delta_credits kind reason actor |
account.trial.granted | 試用付与 | account amount_credits actor |
account.disabled | アカウント停止 | account previous_status status actor |
account.enabled | アカウント復旧 | account previous_status status actor |
account.password.reset | パスワード再設定 | account actor |
注文
| タイプ | 名称 | data フィールド |
|---|---|---|
order.created | 注文作成 | order actor |
order.paid | 支払い完了 | order paid_at previous_status status actor |
order.failed | 支払い失敗 | order reason previous_status status actor |
order.redeemed | 引き換え完了 | order code_masked actor |
サブスクリプション
| タイプ | 名称 | data フィールド |
|---|---|---|
subscription.started | サブスク開始 | subscription previous_status status actor |
subscription.renewed | サブスク更新 | subscription actor |
subscription.upgraded | サブスク変更 | subscription changes actor |
subscription.cancelled | サブスク解約 | subscription previous_status status actor |
subscription.payment_failed | 更新失敗 | subscription reason actor |
subscription.quota.exhausted | 割当上限 | subscription request_id actor |
タスク
| タイプ | 名称 | data フィールド |
|---|---|---|
task.video.succeeded | 動画完了 | task video_count actor |
task.video.failed | 動画失敗 | task actor |
task.generation.succeeded | 生成完了 | task media output_count actor |
task.generation.failed | 生成失敗 | task media actor |
お知らせ
| タイプ | 名称 | data フィールド |
|---|---|---|
content.changelog.published | 更新履歴公開 | entry actor |
content.article.published | 記事公開 | article tenant_id previous_status status actor |
content.article.unpublished | 記事非公開 | article tenant_id previous_status status actor |
Webhook
| タイプ | 名称 | data フィールド |
|---|---|---|
webhook.endpoint.auto_disabled | エンドポイント自動停止 | endpoint reason consecutive_failures actor |
ペイロード形式
すべてのイベントは同じエンベロープを使います:id(イベント一意 id)、type、domain、created_at(ISO 8601 UTC)、api_version、data。data 内のキーは snake_case、時刻は _at で終わり、金額は十進文字列(_usd / _credits)、値がないフィールドは明示的に null です。再送により同じイベントが複数回届くことがあるため、id で重複排除してください。
{ "id": "evt_01JBXK6Q3N7Y8R2V4W5X6Z7A8B", "type": "model.price.changed", "domain": "model", "created_at": "2026-11-04T08:12:33Z", "api_version": "2026-11-04", "data": { }}リクエストヘッダー
POST https://your-server.example/webhooksContent-Type: application/jsonUser-Agent: Webhooks/1.0X-Event-Id: evt_01JBXK6Q3N7Y8R2V4W5X6Z7A8BX-Event-Type: model.price.changedX-Delivery-Id: 123456X-Timestamp: 1762243953X-Signature: v1=5f1c…署名の検証
エンドポイント作成時に表示されたシークレットで、X-Timestamp の値 + . + 生のリクエストボディ という文字列に対して HMAC-SHA256 を計算し、X-Signature の v1= 以降の16進数と定数時間で比較してください。タイムスタンプが現在時刻と 5 分以上ずれている場合は拒否してください。まず 2xx を返してから処理し、レスポンス全体を 10 秒以内に完了させてください。
import { createHmac, timingSafeEqual } from "node:crypto";export function verify(secret, headers, rawBody) { const ts = headers["x-timestamp"]; if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; const expected = createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex"); const given = String(headers["x-signature"]).replace(/^v1=/, ""); return given.length === expected.length && timingSafeEqual(Buffer.from(given, "hex"), Buffer.from(expected, "hex"));}import hmac, hashlib, timedef verify(secret: str, headers: dict, raw_body: bytes) -> bool: ts = headers["X-Timestamp"] if abs(time.time() - int(ts)) > 300: return False expected = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest() given = headers["X-Signature"].removeprefix("v1=") return hmac.compare_digest(given, expected)func verify(secret string, ts, sig string, body []byte) bool { t, _ := strconv.ParseInt(ts, 10, 64) if math.Abs(float64(time.Now().Unix()-t)) > 300 { return false } mac := hmac.New(sha256.New, []byte(secret)) mac.Write([]byte(ts + ".")) mac.Write(body) expected := hex.EncodeToString(mac.Sum(nil)) return hmac.Equal([]byte(strings.TrimPrefix(sig, "v1=")), []byte(expected))}再試行と自動停止
2xx 以外のレスポンス、または 10 秒以内に応答がない場合は失敗とみなします。各配信は最大 7 回、下表の間隔で試行し、すべて失敗すると「枯渇」としてマークされます。同一エンドポイントで連続 10 件の配信が枯渇すると自動的に停止され、メールで通知されます。修正後にコンソールで再度有効にしてください。どの配信もコンソールから手動で再送できます。
| 試行回数 | 前回からの間隔 |
|---|---|
| 1 | 0 |
| 2 | 1 min |
| 3 | 5 min |
| 4 | 30 min |
| 5 | 2 h |
| 6 | 6 h |
| 7 | 24 h |
エンドポイントの要件
URL は公開された到達可能な HTTPS アドレスである必要があります。プライベート、ループバック、リンクローカルの範囲に解決されるホスト名は拒否されます。リダイレクトには従わず、レスポンスボディは最大 64 KB まで読み取ります。

