Webhook
编辑完成时接收带签名的 ReWords.AI Webhook,并用 Node.js 或 Python 校验 X-Rewords-Signature HMAC。
在 POST /edits 中传入 callback_url。任务变为 succeeded 或 failed 时,我们会把与 GET /edits/{id} 返回内容相同的 JSON
POST 到这个 URL。
callback_url必须是httpsURL。它的查询字符串会保留,所以你可以加上自己的标识,例如https://example.com/hooks/rewords?order=1234。- 10 秒内返回任意
2xx状态表示已收到。其他任何情况——别的状态码、超时、连接错误——都算作失败。 - 投递失败后,会在上一次尝试之后 1、5、30 分钟重试,所以最后一次重试大约在第一次之后 36 分钟。之后不再重试;
GET /edits/{id}仍然会返回结果。 - 每次重试发送的字节和签名都完全相同。由于有重试,同一个任务你可能会收到不止一次:用编辑的
id忽略已经处理过的。 - 每次投递都带签名:
X-Rewords-Signature: sha256=<64 个十六进制字符>,即用你的 Webhook 密钥对原始请求体计算的 HMAC-SHA256。 请把整个密钥字符串(包括whsec_前缀)作为 HMAC 的密钥。
你的 Webhook 密钥
每个账号有一个 Webhook 密钥,由它的所有 API 密钥共享。在你的 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' }) 读取请求体。