Webhook
編集が終わったときに署名付きの ReWords.AI Webhook を受け取り、Node.js または Python で X-Rewords-Signature の HMAC を検証します。
POST /edits で callback_url を渡します。ジョブが succeeded または failed になると、GET /edits/{id} で得られるのと
同じ JSON をその URL に POST します。
callback_urlはhttpsの URL である必要があります。クエリ文字列は保持されるので、https://example.com/hooks/rewords?order=1234のように独自の参照を付けられます。- 受け取ったことを伝えるには、10 秒以内に任意の
2xxステータスを返してください。それ以外(別のステータス、タイムアウト、 接続エラー)はすべて失敗と見なします。 - 配信に失敗すると、前回の試行から 1 分、5 分、30 分後に再送します。最後の再送は最初の試行から約 36 分後です。
その後は再送しませんが、
GET /edits/{id}で結果は取得できます。 - 再送では毎回同じバイトと同じ署名を送ります。再送があるため同じジョブを複数回受け取ることがあります。編集の
idを使って、 処理済みのものは無視してください。 - 各配信には署名が付きます:
X-Rewords-Signature: sha256=<16 進数 64 文字>。Webhook シークレットで生のリクエスト本文を HMAC-SHA256 したものです。HMAC の鍵には、whsec_プレフィックスを含むシークレット文字列全体を使ってください。
Webhook シークレット
Webhook シークレットはアカウントごとに 1 つで、すべてのキーで共有されます。 API キーのページで確認できます。そこでリセットもできますが、古いシークレットはすぐに 使えなくなるので、リセットしたらすぐに受信側を更新してください。
署名を検証する
検証に失敗したら 401 でリクエストを拒否し、処理しないでください。再送しても不正な署名は直りません。
import crypto from 'node:crypto';
export function verify(rawBody, header, secret) {
if (typeof header !== 'string') return false;
const expected = Buffer.from('sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex'));
const received = Buffer.from(header);
return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}import hashlib, hmac
from typing import Optional
def verify(raw_body: bytes, header: Optional[str], secret: str) -> bool:
if not header:
return False
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(header.encode(), expected.encode())JSON を解析する前に生のバイトで検証してください。シリアライズし直すと署名が変わります。たとえば Express では、
express.raw({ type: 'application/json' }) で本文を読み取ります。