統合ガイド認証エンドポイント規約モデルエラーWebhook
1tokens1tokens
はじめにAPI リファレンス

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.createdKey 作成api_key actor
api_key.updatedKey 更新api_key changes actor
api_key.revokedKey 失効api_key previous_status status actor
api_key.expiredKey 期限切れ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 件の配信が枯渇すると自動的に停止され、メールで通知されます。修正後にコンソールで再度有効にしてください。どの配信もコンソールから手動で再送できます。

試行回数前回からの間隔
10
21 min
35 min
430 min
52 h
66 h
724 h

エンドポイントの要件

URL は公開された到達可能な HTTPS アドレスである必要があります。プライベート、ループバック、リンクローカルの範囲に解決されるホスト名は拒否されます。リダイレクトには従わず、レスポンスボディは最大 64 KB まで読み取ります。

エラー

Previous Page

On this page

イベント一覧モデルAPI Keyアカウント注文サブスクリプションタスクお知らせWebhookペイロード形式リクエストヘッダー署名の検証再試行と自動停止エンドポイントの要件
{
  "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/webhooks
Content-Type: application/json
User-Agent: Webhooks/1.0
X-Event-Id: evt_01JBXK6Q3N7Y8R2V4W5X6Z7A8B
X-Event-Type: model.price.changed
X-Delivery-Id: 123456
X-Timestamp: 1762243953
X-Signature: v1=5f1c…
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, time

def 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))
}