简中

正式版 v3 API

使用可查验的 x402 证据进行开发。

无须验证即可查询公开证据,或使用 Ethereum 钱包登入以注册并 管理 endpoint。回应会提供具名观察纪录,绝不提供综合 trust score。

基础 URL https://ifandonlyif.io

01 · Quickstart

查询公开证据。

已发布的 Evidence Card 不需要 API key。

阅读图解证据范例

依 endpoint URL 取得证据
curl -G "https://ifandonlyif.io/api/v3/evidence/check" \
  --data-urlencode \
  "url=https://api.example.com/paid-resource"
两种发布路径

observed 卡片可在拥有者认领前公开,条件是 endpoint 启用、未 opt-out 且已有 discovery observation。卡片带有“拥有权未验证”标示与固定 disclaimer。verified tier 首次发布需完成拥有权验证,且至少三笔通过的 initial 或 scheduled observation。404 表示没有公开卡片,不是安全 verdict。查询只读取已储存的证据,不启动 probe。

首页的 提交以供监测 会呼叫 POST /api/v3/discovery/submit,内容为 {"url":"https://api.example.com/paid"}。此公开 route 需启用 discovery ingestion,除通用 rate limit 外,每个 IP 每分钟最多 10 次提交。202 加 queued 表示已记录 candidate(立即排入伫列仅尽力而为);known 不会再次排入。两者都不保证监测或发布。worker 观察前会套用 robots.txt、opt-out、资格及 backoff 规则。payment-network selector 只比较已观察的选项,不限制 worker 验证哪些选项。

提交后,页面每五秒轮询一次 GET /api/v3/discovery/status?url=…,最多一分钟,可用时载入公开卡片。此唯读 route 返回 {"url":"…","status":"pending"},可能附带 retry_after_seconds。其他状态:available、deferred、unavailable、unobserved、disabled。no-store,每个 IP 每分钟 30 次。查看进度 可不重新提交而继续读取。延迟、错误与 unavailable 会停止自动检查。拒绝与 opt-out 细节保持私密。

使用者发起的查询返回 404 时,会读取一次提交状态。只有已确认的 unobserved 会提供提交;pending 或 deferred 则提供进度。URL 格式有效不等于具备监测资格。查询不会自动提交,提交也不要求认领拥有权。

成功回应封装

200 application/json
{
  "success": true,
  "data": {
    "endpoint": {
      "id": "ENDPOINT_UUID",
      "url": "https://api.example.com/paid-resource",
      "name": "Example x402 API"
    },
    "operational_status": "passing",
    "ownership": {
      "status": "verified",
      "method": "iff-well-known"
    },
    "protocol": {
      "status": "pass",
      "version": 2,
      "payment_options": [],
      "check_codes": ["x402_v2_valid"]
    },
    "availability": [
      {
        "window": "24h",
        "samples": 288,
        "reachable_rate": 100,
        "protocol_pass_rate": 99.7,
        "p50_latency_ms": 84,
        "p95_latency_ms": 190
      }
    ],
    "freshness": {
      "status": "fresh",
      "observed_at": "2026-07-12T04:30:00Z",
      "interval_seconds": 300
    },
    "evidence": {
      "report_hash": "HEX_SHA256",
      "monitor_id": "iff-production-monitor",
      "monitor_version": "3.0.0",
      "monitor_signature_algorithm": "ML-DSA-65",
      "monitor_signature": "BASE64_ML_DSA_65_SIGNATURE",
      "monitor_public_key": "BASE64_ML_DSA_65_PUBLIC_KEY"
    }
  }
}

02 · Authentication

使用钱包登入。

拥有者设置使用 API,没有 wallet-connect dashboard。你需要能产生 65-byte EIP-191 personal_sign signature 的 Ethereum externally owned account(EOA),以及 endpoint origin 的部署存取权。不支援 contract-wallet signature(EIP-1271 / EIP-6492)。拥有者 route 使用登入 challenge 后核发的短效 access token。

  1. 要求 challenge

    challenge 会绑定 domain、URI、chain、wallet、nonce 与到期时间。

  2. 签署完全相同的讯息

    以同一钱包地址,将返回的 message 原封不动交给 personal_sign。请在提示中核对 domain、wallet 与 expiry。这是登入 signature,不是 payment 或 token approval。IFF 永远不需要你的 private key 或 recovery phrase。

  3. 交换并轮替

    取得 access_token、refresh_token、token_type 与 expires_in。下方范例以 $ACCESS_TOKEN 代表 access token。每个 refresh token 仅能使用一次:refresh 后请替换两个 token。

1. 建立 challenge
curl "https://ifandonlyif.io/api/v3/auth/challenge" \
  -H "content-type: application/json" \
  -d '{"wallet_address":"0xYOUR_WALLET"}'
2. 验证 signature · 请求格式
curl "https://ifandonlyif.io/api/v3/auth/verify" \
  -H "content-type: application/json" \
  -d '{
    "challenge_id":"CHALLENGE_UUID",
    "wallet_address":"0xYOUR_WALLET",
    "message":"EXACT_MESSAGE_FROM_SERVER",
    "signature":"0xSIGNATURE"
  }'

curl 无法签署,signature 来自你的钱包。上例是 request template。请提交原始的 challenge_id 与 message 及钱包的 signature,并以 JSON serializer 建立 body,例如 JSON.stringify({ challenge_id: challenge.challenge_id, wallet_address: wallet, message: challenge.message, signature })。不要将 literal newline 贴入 JSON,也不要自行重建 message。token 请勿出现在 URL、截图、source code 与 shell history。

3. 轮替 refresh token
curl "https://ifandonlyif.io/api/v3/auth/refresh" \
  -H "content-type: application/json" \
  -d '{"refresh_token":"REFRESH_TOKEN"}'

challenge 五分钟后到期且只能使用一次。拥有者回应使用 Cache-Control: no-store。

03 · 拥有权

注册并证明对 endpoint 的控制权。

注册只接受 port 443 的公开 HTTPS endpoint,且不得含 credentials、query string、fragment 或 redirect。它建立 claim attempt,不授予拥有者存取权。

回应含唯一的 claim_attempt_id 与 ownership object(challenge、expires_at、verification_url、document)。challenge 有效 24 小时。任何已验证钱包都可建立独立 attempt;pending attempt 不能读取 private observation、手动 probe、管理 webhook、连结 ERC-8004 或取消发布。

注册 endpoint
curl "https://ifandonlyif.io/api/v3/endpoints" \
  -H "authorization: Bearer $ACCESS_TOKEN" \
  -H "content-type: application/json" \
  -d '{
    "url":"https://api.example.com/paid-resource",
    "name":"Example x402 API",
    "description":"Payment-gated resource"
  }'

201 Created:新 endpoint 与 claim attempt。200 OK:既有 endpoint 新增 attempt。请将 endpoint_id 存为 ENDPOINT_UUID,并保留 claim_attempt_id 供 polling。两者都不排入 verification,也不授予 owner access。等待时请勿重复注册。

对於单一 endpoint,请将回应中的 ownership.document 原封不动发布在 ownership.verification_url,例如:

https://api.example.com/.well-known/iff-trust.json

同一 origin 的 endpoint 共用此档案。新增前请备份目前的 document。将既有 single claim 包成 {"claims":[...]} 的第一项并附加新的 ownership.document,或直接附加到既有 array。保留其他 endpoint 的 claim 与完全相同的 challenge。切勿以最新回应取代整个档案;IFF 不会合并。

旧版 single-claim format 仍受支援。multi-endpoint format 只有一个 top-level field claims:1–64 个 object,每个恰含 endpoint_id、owner_wallet 与 challenge,使用 API 提供的非空值(canonical lowercase UUID、Ethereum wallet address、完全相同的 challenge)。wallet 比对忽略大小写。body 须在 16 KiB 以内。unknown 或重复的 JSON field、重复 endpoint ID、混用 format 或任何 malformed entry 都会使整个档案被拒绝。更新时只替换该 endpoint 的项目。请持续保留有效 claim,供定期 domain-control recheck。

将拥有权验证排入伫列
curl -X POST \
  "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/verify-ownership" \
  -H "authorization: Bearer $ACCESS_TOKEN"

此 verification request 返回 202 Accepted:job 已排入伫列,尚未验证。请遵循 Retry-After(目前为 5 秒),再用同一钱包的 access token polling:

查看你的拥有权尝试
curl "https://ifandonlyif.io/api/v3/endpoints?page=1&page_size=20" \
  -H "authorization: Bearer $ACCESS_TOKEN"

于 data.claim_attempts[].id 找到已保存的 attempt ID(必要时查看后续页面),读取 status、outcome_code 与 verification_failures。pending 不是成功;verified 表示 proof 通过;failed、expired、superseded 已结案。data.endpoints 列出 authoritative ownership。后续注册不会轮替另一钱包的 challenge。只有成功的 same-origin proof 可取代 owner;transfer 会停用旧 webhook 并重设发布资格。

检查失败后 attempt 仍为 pending 时,请修正已部署的档案,并在 24 小时内重新排入 verification。attempt 已到期或结案时,请重新注册该 URL、发布新 document 并排入新 attempt。verification 返回 409:没有可用的 pending attempt。503:queue 不可用,不代表通过;请以 backoff 重试。401:更新 token 或重新登入。

拥有权验证通过后

owner access 与首次发布是不同步骤。verified-tier card 在 ownership verification 完成且至少三笔通过的 initial 或 scheduled observation 后才公开;manual probe 不计入。等待期间公开 404 不代表 ownership 验证失败。请用仅限 owner 的 history 诊断:

读取私人观察纪录历史
curl "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/observations?page=1&page_size=20" \
  -H "authorization: Bearer $ACCESS_TOKEN"

读取 data.observations 与各 probe_type。要求 private diagnostic 时,执行下方命令,再 polling 此 history 等候新的 manual observation。202 仅确认已排入伫列。manual 结果不会变更 public card、发布资格、manifest 或通知。

将私人诊断排入伫列
curl -X POST \
  "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/probes" \
  -H "authorization: Bearer $ACCESS_TOKEN"

接著请设置变更通知。要停止监测并隐藏卡片,请使用下方仅限 owner 的动作。它也会停用 webhook 与 pending delivery,但保留 immutable observation、claim-attempt audit 与 transparency-log entry。快取的卡片最多可再显示 30 秒。要恢复,请重新注册该 URL 并再次证明控制权。

停止监测并取消发布 · 会变更 endpoint 状态
curl -X DELETE \
  "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID" \
  -H "authorization: Bearer $ACCESS_TOKEN"

成功停止返回 204 No Content。wallet 没有目前的 verified 或 stale claim 时,owner management route 返回 404(仅有 pending attempt 不足)。claim 为 stale 时,history 与停止仍可用,但建立 webhook 或 manual probe 会返回 409,直到 ownership 再次验证。

证据界线

ownership 只证明对受监测 origin 的控制权,不证明谁操作 backend、付款后会发生什么,或 endpoint 是否安全。

04 · Reference

endpoint 参考数据。

以 :id 结尾的路径参数为 UUID。分页接受 page 与最大 100 的 page_size。每个 GET route 也回应 HEAD。公开 route 与 POST /api/v3/verify 返回 Access-Control-Allow-Origin: *;需 authentication 的 route 不返回。

公开与验证

方法路径用途
GET/healthLiveness 与依赖是否可用的概略布林值(不含服务名称、版本或元件标签)。
GET/api/v3/evidence/check?url=…依 normalized endpoint URL 取得已发布的 Evidence Card。
GET/api/v3/evidence/endpoints/:id依 endpoint ID 取得已发布的 Evidence Card。
GET/api/v3/evidence/manifests/:id依 manifest ID 取得附有 ETag、不可变的每日 evidence manifest。它与上述 endpoint ID 使用不同的 ID 空间。请从 Evidence Card 的 anchor.manifest_uri 取得 manifest ID;若在此传入 endpoint ID,会返回 404 并说明原因。
GET/api/v3/log/anchors/latest已签署 transparency-log tree head 最新提交或已确认的 ERC-8004 anchor。
POST/api/v3/auth/challenge建立一次性的 wallet challenge。
POST/api/v3/auth/verify验证 EIP-191 signature 并签发 token pair。
POST/api/v3/auth/refresh轮替只能使用一次的 refresh token。
POST/api/v3/verify将收到的 x402 requirement 与独立 observation 进行 Preflight 比较。
GET/api/v3/receipts/keys可选实验性功能 Service Receipt v2 目前使用与保留的 public key(v1 key 列为 previous)。
GET/api/v3/badge/:id.json用于 shields.io endpoint badge 的 JSON,描述 endpoint 目前的 requirement consistency。

已验证的钱包与 endpoint 拥有者

下方每个 route 都需要 Authorization: Bearer <access_token>。registration、polling 与 verification 限建立 attempt 的 wallet;management route 需 verified 或 stale ownership。

方法路径用途
POST/api/v3/endpoints建立独立的 claim attempt 与 ownership challenge,不会授予权限。
GET/api/v3/endpoints列出具有效拥有权的 endpoint 与此钱包的 claim-attempt 稽核状态。
DELETE/api/v3/endpoints/:id取消发布 endpoint,并保留不可变的 evidence。
POST/api/v3/endpoints/:id/verify-ownership将 well-known ownership verification 排入伫列。
POST/api/v3/endpoints/:id/probes将仅限 owner 的 manual observation 排入伫列。
GET/api/v3/endpoints/:id/observations分页读取完整的 observation history。
POST/api/v3/endpoints/:id/webhooks建立用于 status 或 requirement 变更的 owner Webhook;secret 只会返回一次。
GET/api/v3/endpoints/:id/webhooks列出作用中的 target,不含 secret。
DELETE/api/v3/endpoints/:id/webhooks/:webhookId停用 Webhook 与待传送项目。
POST/api/v3/endpoints/:id/erc8004连结 owner 持有的 ERC-8004 agent identity。

05 · 回应模型

分别解读各项维度。

ownership
目前的 domain-control 状态、方式与验证时间。
protocol
最新的 x402 解析结果、版本、各项具名检查与宣告的 payment option。
availability
24 小时与 7 天的样本、百分比与 p50/p95 latency。
freshness
最新 observation 是否仍在发布所需的 freshness window 内。
evidence
Canonical report hash、monitor identity、ML-DSA-65 signature(旧 report 为 Ed25519)与 public key。
anchor
可选的每日 manifest 链上状态与 transaction provenance。

rate 为 0 至 100 的百分比。缺少的 measurement 会略去或为 null;请勿推论为通过。

observed tier 的 probe 也会按 UTC 日计数。每个结束的日子会封存成一份每日确认文件,其 hash 以一个 leaf 进入 transparency log;启用 change-only storage 后,只有 observed state 变动时才保存完整的签名 observation。GET /api/v3/evidence/observed-confirmations/:day(或 /latest)返回原始 body、document_hash、leaf_hash 与承诺等级:sealed、logged 或 anchored。这是 monitor 观测到的统计,不证明每次 probe 都实际执行。

06 · Webhook

验证每一次传送。

衍生的 operational status 改变时,owner subscription 收到 endpoint.status_changed;合格 observation 显示不同 payment requirement fingerprint 时,收到 endpoint.requirement_changed(不证明攻击)。manual probe 不触发任何事件;observed-tier card 不授予 subscription 权限。

建立订阅
curl "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/webhooks" \
  -H "authorization: Bearer $ACCESS_TOKEN" \
  -H "content-type: application/json" \
  -d '{"target_url":"https://hooks.example.com/iff"}'

建立订阅需 verified ownership,返回 201 Created,含 id、target_url 与 secret。请将 ID 存为 WEBHOOK_UUID,并把 secret 存放于接收端服务器;secret 只显示一次,无法取回。target 须为公开 HTTPS/443,不得含 credentials、query string、fragment 或 redirect。作用中 target 重复或作用中订阅超过 10 个,返回 409。

建立订阅不传送测试事件。事件随符合资格的 observation 变更而触发,不随每次 probe。依赖通知前,请先验证下列 header。

X-IFF-Timestamp: 1700000000 X-IFF-Signature: sha256=<hex digest> Idempotency-Key: <delivery uuid>
  1. 拒绝超出允许 clock-skew 范围的 timestamp。
  2. 使用仅显示一次的 secret,对 timestamp + "." + raw_body 计算 HMAC-SHA256。
  3. 以 constant-time 比较 hex digest。
  4. 依 Idempotency-Key 去重;重复传送仍应回应 2xx。
列出作用中的订阅 · 不会传回 secret
curl "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/webhooks" \
  -H "authorization: Bearer $ACCESS_TOKEN"
停止一个订阅 · 会变更通知状态
curl -X DELETE \
  "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/webhooks/WEBHOOK_UUID" \
  -H "authorization: Bearer $ACCESS_TOKEN"

清单位于 data。删除返回 204 No Content,停止待传送项目,不取消发布 endpoint。遗失 secret 时请删除并重建订阅。切勿在 client-side code 暴露 secret。

07 · Preflight

付款前先检查。

对收到的 x402 payment requirement 采取行动前,先与 IFF 独立且已签署的 observation 比较。它不 probe URL,且仅在尚无 observation 时储存 normalized URL。verdict 为 consistent、diverged、unobserved 或 stale:没有 composite score,也不作 safety、delivery 或 trust 主张。

验证 requirement
curl "https://ifandonlyif.io/api/v3/verify" \
  -H "content-type: application/json" \
  -d '{
    "url":"https://api.example.com/v1/quote",
    "payment_required":{"x402Version":2,"accepts":[{
      "scheme":"exact",
      "network":"eip155:8453",
      "asset":"0xab12cd34ab12cd34ab12cd34ab12cd34ab12cd34",
      "amount":"1000",
      "payTo":"0xef56ab78ef56ab78ef56ab78ef56ab78ef56ab78",
      "maxTimeoutSeconds":60
    }]}
  }'
TypeScript SDK
npm install @ifandonlyif/x402-preflight — 使用 verify()、wrapFetch() 或内含的 MCP command。阅读 SDK 指南.
Direct API
可从任何程序语言使用 POST /api/v3/verify。公开 Preflight 检查不需要 API key。
Badge
![x402 evidence](https://img.shields.io/endpoint?url=https://ifandonlyif.io/api/v3/badge/ENDPOINT_UUID.json)

实验性功能展示:Service Receipt v2

Service Receipt v2 是单一 verification result 的可选 signed artifact,不属于 core preflight contract。它将 response、verification-request digest 与五分钟 action window 绑定于 IFF 专用 ML-DSA-65 receipt key。略去 receipt 或传送 null 不改变 response;{} 或 "version":"2" 签发 v2,"1" 返回 422。既有 v1 receipt 仍可验证。

选择加入实验性 receipt
"receipt":{"version":"2","nonce":"checkout_7f3a"}
已签署的 artifact
成功选用此功能后会新增 service_receipt,不会变更其他 response field。
本机 verifier
将独立 envelope 或完整 API response 贴入Receipt 展示页(英文)。验证会在浏览器本机执行。
取得目前与先前的 receipt key
curl "https://ifandonlyif.io/api/v3/receipts/keys"
不是 x402 payment receipt

Service Receipt 不证明 payment、service delivery、caller identity、remote execution、result correctness 或 safety,只记录某个 receipt key 签署了内含的 result。

分开进行 verification 检查

有效的 ML-DSA-65(v2)或 Ed25519(v1)signature 表示内含的 key 签署了 receipt(provenance,不是 attestation),但不表示该 key 属于声称的 issuer。符合 same-origin HTTPS key directory 的 key 可辨识;最严格的 policy 还会比对确切 issuer 与独立钉选的完整 sha256: fingerprint。解码后的 signed subject 才具权威,须与外层 response 比较。引用的 evidence 在其专属 proof 通过前仍未验证。IFF 目前将 compute_proof 设为 null。

08 · 错误与限制

失败时不要推论证据。

错误封装
{
  "error": true,
  "message": "human-readable reason"
}
状态含义
400JSON、UUID、URL、分页或输入结构格式错误。
401token 缺少、无效、过期、重放或类型错误。
403已通过 authentication 的钱包不拥有所请求的资源。
404公开 evidence 或所请求的 owner 资源不存在。
409ownership 状态、重复 target 或资源状态冲突。
422x402 requirement、receipt version 或 receipt nonce 无效。
429已达 rate limit;请以 backoff 重试。
503Evidence repository、queue、registry、receipt 签发或其他依赖不可用。
安全假设

IFF 是外部 observer。它不执行 paid canary transaction、不作 payment-safety 主张、不保证付款后的 delivery,也不判定 endpoint 是否值得信任。monitor signature 显示 provenance 与 tamper evidence,不是 attestation。