服务端 API
你的服务端只需要调用两个接口:渲染表单前创建 intent,收到表单后兑换 token。其余接口都是可选的。
请求约定
- 服务地址:
https://captcha.moe(自己部署时换成你的服务地址)。 - 所有请求都是
POST,请求体为 JSON,并带上Content-Type: application/json。 - Secret key 放在请求头
Authorization: Bearer mc_sec_…里,不要放在请求体中,也不要出现在浏览器里。 - 建议设置 5 秒左右的超时。超时和网络错误按「暂时不可用」处理。
- 失败时返回非 2xx 状态码和
{"error":"错误码"},全部错误码见错误码与排查。
| 接口 | 谁来调用 | 用途 |
|---|---|---|
POST /intents | 你的服务端 | 为一次操作创建验证许可(必需) |
POST /siteverify | 你的服务端 | 兑换访客提交的 token(必需) |
POST /feedback | 你的服务端 | 回传业务结果,例如确认是恶意注册(可选) |
POST /grants | 你的服务端 | 为已登录会话申请短时挑战豁免(可选,需部署开启) |
POST /challenge、/solve | 组件 | 浏览器完成挑战,你不需要调用 |
POST /intents
在渲染表单之前调用,为「这一次操作」创建许可。把返回的 intent_id 保存到服务端记录里,再填进组件。
请求字段
| 字段 | 类型 | 说明 |
|---|---|---|
action | 字符串,必填 | 业务动作名,1–64 位字母、数字、- 或 _,例如 signup。兑换时必须一致。 |
nonce | 字符串,必填 | 服务端生成的随机值,16–128 位字母、数字、- 或 _。重试同一次创建时复用,得到同一个许可。 |
hostname | 字符串,必填 | 表单所在域名,小写、不含协议和端口,必须在站点的允许域名里。 |
session | 字符串,可选 | 你的服务端会话的 HMAC,64 位小写十六进制。用于把许可绑定到会话,不要发送原始会话 ID。 |
subject | 字符串,可选 | 业务主体(例如账号)的 HMAC,64 位小写十六进制,用于按主体限流。不要发送邮箱或用户名。 |
trusted_grant_id | UUID,可选 | 使用短时挑战豁免时填入,见挑战豁免。 |
响应字段
| 字段 | 说明 |
|---|---|
intent_id | 许可 ID,填进组件的 data-intent,并保存到服务端记录 |
sitekey | 站点的 Site key,填进组件的 data-sitekey |
action、hostname | 与请求相同,可用来核对 |
expires_at | 许可的截止时间(Unix 秒),创建后 5 分钟 |
POST https://captcha.moe/intents
Authorization: Bearer mc_sec_你的密钥
Content-Type: application/json
{
"action": "signup",
"nonce": "6f1c2a0e-0b8e-4c4f-9f5d-2d7c1e9a4b10",
"hostname": "example.com"
}POST /siteverify
收到表单后调用。只有 response 来自浏览器,其余字段都从你的服务端记录读取。返回 200 且各字段与记录一致,才执行业务。
请求字段
| 字段 | 类型 | 说明 |
|---|---|---|
response | 字符串,必填 | 表单字段 moe-captcha-response 的值 |
intent_id | UUID,必填 | 创建时保存的 intent_id |
action、hostname | 字符串,必填 | 和创建 intent 时完全相同 |
idempotency_key | 字符串,必填 | 幂等键,16–128 位字母、数字、- 或 _。同一次提交重试时复用:10 分钟内返回同一结果,不重复扣费。 |
响应字段
| 字段 | 说明 |
|---|---|
success | 成功时为 true;失败时不会返回 200,而是返回错误码 |
intent_id、action、hostname | 请逐一与服务端记录比较,不一致就拒绝 |
decision_id | 这次验证的编号。保存下来,回传业务结果时要用 |
assessment | 目前固定为 passed,表示许可已通过,不是人类概率分数 |
POST https://captcha.moe/siteverify
Authorization: Bearer mc_sec_你的密钥
Content-Type: application/json
{
"response": "表单里的 moe-captcha-response",
"intent_id": "8c1f5d2e-3a47-4b1e-9c0d-5e6f7a8b9c0d",
"action": "signup",
"hostname": "example.com",
"idempotency_key": "d3b07384-d9a0-4c7b-8b1e-2f6c1a9e5d44"
}POST /feedback
可选。兑换成功后 7 天内,把业务上的最终判断告诉我们,例如这个注册后来被确认为恶意账号。反馈不会改变已有结果,也不会触发封禁。
| 字段 | 说明 |
|---|---|
decision_id | /siteverify 返回的 decision_id |
event_id | 你生成的 UUID。网络重试时复用,不要换新的 |
outcome | confirmed_abuse、legitimate 或 unknown |
business_type | 业务类型,1–64 位字母、数字、- 或 _ |
occurred_at | 业务结果发生的时间(Unix 秒),不早于兑换、不晚于现在 |
supersedes_event_id | 可选。修正之前的反馈时,指向最近一次的 event_id |
请求
POST https://captcha.moe/feedback
Authorization: Bearer mc_sec_你的密钥
Content-Type: application/json
{
"decision_id": "5b2e7c11-9d4a-4f0e-8a6b-1c3d5e7f9a2b",
"event_id": "0e9d8c7b-6a5f-4e3d-2c1b-0a9f8e7d6c5b",
"outcome": "confirmed_abuse",
"business_type": "signup",
"occurred_at": 1789400600
}成功返回 {"accepted":true,"event_id":"…","revision":1,"expires_at":…}。字段规则和修正流程见回传业务结果。
POST /grants
可选,需要部署开启。为已登录会话或刚完成过挑战的访客申请短时豁免,下一次验证可以跳过挑战,但仍需兑换和计费。字段、撤销(POST /grants/revoke)和错误处理见挑战豁免。
组件调用的接口
POST /challenge 和 POST /solve 由组件在浏览器里调用,按页面的来源(Origin)校验域名。你不需要、也不应该从服务端调用它们。它们的错误会通过组件的错误回调告诉你。
请求格式错误时
缺少字段或字段格式不对时,任何接口都返回 422 和出错的字段;请求体不是合法 JSON 返回 400 bad-request,没有使用 JSON 返回 415 unsupported-media-type,把 secret 放进请求体返回 422 secret-in-body:
响应
HTTP/1.1 422 Unprocessable Entity
{
"error": "bad-request",
"field": "nonce"
}