开发者

从你的后端验证 Spondeo 证明。

一次 REST 调用即可确认持有者所披露的声明——所属身份、机构类别、国家/地区——而绝不暴露其姓名、学校、雇主或邮箱。免费开发者层级:每月 500 次验证。


身份认证

使用 Authorization 请求头中的 API 密钥对验证调用进行认证:Authorization: Bearer sk_live_…(沙盒环境请使用 sk_test_…)。在你的个人中心创建和管理密钥。每个密钥的明文仅在创建时显示一次,且仅以哈希形式存储——请将其保存在服务端,切勿下发到浏览器。

在个人中心管理你的密钥 →


接口

方法 路径 认证 用途
POST /v1/verify API 密钥 验证所提交的证明;返回披露的声明和一个稳定的化名标识。
请求字段: { vp_token, expected_audience, nonce, required? }
响应: { valid, claims, pid, reason }
POST /v1/sandbox/present API 密钥(测试) 铸造一份沙盒测试证明用于验证(测试签发方;仅可用 sk_test_ 密钥验证)。
请求字段: { nonce, affiliation?, audience? }
响应: { vp_token, audience, nonce }
POST /v1/credentials 发起一次所属身份验证(发送 6 位验证码)。
请求字段: { affiliation, email }
响应: { id, status }
POST /v1/credentials/{id}/code 确认验证码并绑定持有者密钥;签发凭证。
请求字段: { code, holder_jwk }
响应: { sd_jwt_vc, credential_id, holder_id, … }
DELETE /v1/credentials/{id} 持有者 撤销一份凭证(限持有者)。
请求字段: { holder_id }
响应: { revoked }
GET /status/{listId} 公开的撤销状态列表。
请求字段:
响应: { list_id, bits }

快速开始

curl

curl -X POST https://vouchmesh.com/v1/verify \
  -H "Authorization: Bearer sk_live_…" \
  -H "content-type: application/json" \
  -d '{"vp_token":"…","expected_audience":"spondeo:proof-link","nonce":"…","required":[{"claim":"affiliation","value":"enrolled_student"}]}'

SDK(TypeScript)

import { Spondeo } from "@spondeo/verify";

const spondeo = new Spondeo("sk_live_…", { baseUrl: "https://vouchmesh.com" });

const res = await spondeo.verify({
  vpToken,
  expectedAudience: "spondeo:proof-link",
  nonce,
  required: [{ claim: "affiliation", value: "enrolled_student" }],
});

if (res.valid) console.log(res.claims, res.pid);

零依赖的 SDK 位于仓库的 sdk/ 目录,并以 @spondeo/verify 发布。


Webhook 回调

在你的个人中心注册一个 Webhook,即可在凭证被撤销的那一刻收到通知。事件仅限于你验证过的凭证——你只会收到与你相关的撤销通知。仅接受公开的 http(s) URL(不接受 localhost 或私有/内部主机)。

在个人中心的 Webhook 一节注册一个 URL。每个 Webhook 仅返回一次签名密钥——请保存在服务端。 在个人中心管理你的密钥 →

事件载荷

发生撤销时,我们会向你的 URL 发送 POST 请求,附带请求头 X-Spondeo-Event: credential.revoked 及下方的 JSON 请求体。其中 status_list.idx 即你已用 /status/{listId} 核对的不透明索引——不含任何 PII。

{
  "type": "credential.revoked",
  "status_list": { "uri": "https://vouchmesh.com/status/1", "idx": 42 },
  "occurred_at": 1717000000000
}

校验签名

每次投递都带有 X-Spondeo-Signature 请求头:它是对完整原始请求体、以你的 Webhook 密钥为密钥计算的十六进制 HMAC-SHA256。请基于原始字节重新计算,并在信任该事件前以常量时间进行比较。

import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody is the EXACT bytes you received (do not re-serialize the parsed JSON).
function verify(rawBody, header, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected), b = Buffer.from(String(header || ""));
  return a.length === b.length && timingSafeEqual(a, b);
}

通过 AI 智能体集成

三条机器可读的路径让智能体无需抓取本文档即可发现并调用 Spondeo。

  • 智能体可读的概览 https://vouchmesh.com/llms.txt 一份关于 Spondeo 功能及调用方式的纯文本摘要,供 LLM 直接读取。
  • OpenAPI 3.1 https://vouchmesh.com/openapi.json 完整的机器可读规范——将代码生成器指向它即可生成带类型的客户端。
  • MCP 服务器 仓库的 mcp/ 目录中提供了一个模型上下文协议(MCP)服务器。它暴露两个工具——verify_affiliation_proof 与 sandbox_present。用 cd mcp && npm install && npm start 运行(环境变量 SPONDEO_API_KEY 与 SPONDEO_BASE_URL),然后将其加入你的 MCP 客户端配置:
{
  "mcpServers": {
    "spondeo": {
      "command": "npx",
      "args": ["tsx", "/abs/path/to/mcp/spondeo-mcp.ts"],
      "env": {
        "SPONDEO_API_KEY": "sk_live_…",
        "SPONDEO_BASE_URL": "https://vouchmesh.com"
      }
    }
  }
}

错误与限制

缺少或填错密钥的验证调用会返回 401 invalid_api_key。超出每月 500 次的免费层级后,密钥会返回 429 quota_exceeded。所有接口还额外受 IP 速率限制。Spondeo 绝不记录或泄露任何 PII——验证方只会看到持有者选择披露的类别/枚举声明。