curl -G "https://ifandonlyif.io/api/v3/evidence/check" \
--data-urlencode \
"url=https://api.example.com/paid-resource"
observed card は、endpoint が active で、opt-out されておらず、discovery observation がある場合、owner の claim 前でも public にできます。「ownership 未検証」の表示と固定の disclaimer が付きます。verified tier の最初の公開には、ownership verification の成功と、passing した initial または scheduled observation が 3 件以上必要です。404 は public card がないことを意味し、安全 verdict ではありません。lookup は probe を開始せず、保存済み evidence を読み取ります。
ホームページの 監視対象として送信 は POST /api/v3/discovery/submit を {"url":"https://api.example.com/paid"} とともに呼びます。この public route は discovery ingestion が有効である必要があり、general rate limit に加え IP ごとに毎分 10 submission までです。202 と queued は candidate が記録されたことを意味します(即時 enqueue は best-effort)。known は再 enqueue しません。どちらも monitoring や公開を保証しません。worker は observation 前に robots.txt、opt-out、eligibility、backoff rule を適用します。payment-network selector は observed option を比較するだけで、worker が検証する option を制限しません。
submission 後、page は最大 1 分間、5 秒ごとに GET /api/v3/discovery/status?url=… を polling し、利用可能になれば public card を読み込みます。この read-only route は {"url":"…","status":"pending"} を返し、必要に応じて retry_after_seconds を含みます。ほかの state: available、deferred、unavailable、unobserved、disabled。no-store で、IP ごと毎分 30 回まで。Check progress は再 submission せずに read を再開します。delay、error、unavailable は自動確認を停止します。rejection と opt-out の詳細は非公開です。
user-initiated lookup が 404 を返すと、submission status を一度読みます。submission を提示するのは確認済みの unobserved だけで、pending または deferred では進捗を提示します。URL format が有効でも monitoring eligibility にはなりません。lookup は自動 submission せず、submission に ownership claim は不要です。
成功 response の envelope
{
"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
ウォレットでサインインする。
owner setup は wallet-connect dashboard ではなく API を使用します。65-byte EIP-191 personal_sign signature を生成できる Ethereum externally owned account(EOA)と、endpoint origin への deployment access が必要です。contract-wallet signature(EIP-1271 / EIP-6492)は非対応です。owner route は login challenge 後に発行される短時間有効な access token を使います。
-
challenge を要求
challenge は domain、URI、chain、wallet、nonce、expiry に bind されます。
-
正確な message に署名
返された
messageは変更せず、同じ wallet address で wallet のpersonal_signmethod に渡してください。wallet prompt で domain、wallet、expiry を確認します。これは login signature であり、payment や token approval ではありません。IFF が private key や recovery phrase を必要とすることはありません。 -
交換とローテーション
access_token、refresh_token、token_type、expires_inを受け取ります。以下の owner example では access token を$ACCESS_TOKENとして使用してください。refresh token はすべて single-use です。refresh 後は両方の token を新しい response のものに置き換えます。
curl "https://ifandonlyif.io/api/v3/auth/challenge" \
-H "content-type: application/json" \
-d '{"wallet_address":"0xYOUR_WALLET"}'
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 は wallet から得ます。上記は request template です。元の challenge_id と message を wallet の signature とともに送信し、body は JSON.stringify({ challenge_id: challenge.challenge_id, wallet_address: wallet, message: challenge.message, signature }) のような JSON serializer で作成してください。JSON に literal newline を貼り付けたり message を再構築したりしないでください。token は URL、screenshot、source code、shell history に残さないでください。
curl "https://ifandonlyif.io/api/v3/auth/refresh" \
-H "content-type: application/json" \
-d '{"refresh_token":"REFRESH_TOKEN"}'
challenge は 5 分で expiry し、1 回だけ使用できます。owner response には Cache-Control: no-store が付与されます。
03 · Ownership
endpoint を登録し、制御権を証明する。
registration は credentials、query string、fragment、redirect のない port 443 の public HTTPS endpoint だけを受け付けます。owner access ではなく claim attempt を作成します。
response には一意の claim_attempt_id と ownership object(challenge、expires_at、verification_url、document)が含まれます。challenge の有効期間は 24 時間です。authentication 済みの wallet は独立した attempt を作成できますが、pending attempt では private observation の閲覧、manual probe、Webhook 管理、ERC-8004 連携、公開停止はできません。
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 として保存し、polling 用に claim_attempt_id を保持してください。どちらも verification を queue せず、owner access も付与しません。待つ間は繰り返し registration しないでください。
1 つの endpoint では、response の ownership.document を変更せず ownership.verification_url に公開します。例:
https://api.example.com/.well-known/iff-trust.json同じ origin の endpoint はこの file を共有します。追加前に現在の document を backup してください。既存の single claim を {"claims":[...]} の最初の item にして新しい ownership.document を append するか、既存 array に append します。ほかの endpoint の claim と正確な challenge は維持してください。file 全体を最新 response で置き換えないでください。IFF は merge しません。
従来の single-claim format も利用できます。multi-endpoint format の top-level field は claims のみで、1〜64 個の object を含み、各 object は endpoint_id、owner_wallet、challenge だけを持ちます。API が返した空でない値(canonical な小文字 UUID、Ethereum address、完全一致の challenge)を使います。wallet 比較は大文字・小文字を区別しません。body は 16 KiB 以内。未知または重複する JSON field、重複 endpoint ID、format の混在、不正な項目があるとファイル全体が拒否されます。更新時はその endpoint の項目だけを置き換えます。定期的な domain-control の再確認のため、検証後も有効な claim を公開しておいてください。
curl -X POST \
"https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/verify-ownership" \
-H "authorization: Bearer $ACCESS_TOKEN"
この verification request は 202 Accepted を返します。job は queue 済みですが、まだ verified ではありません。Retry-After(現在 5 秒)に従い、同じ wallet の access token で poll してください。
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 は終了した attempt です。data.endpoints は現在有効な ownership を列挙します。後からの登録は別の wallet の challenge を更新しません。owner を置き換えられるのは成功した same-origin proof だけで、移転は古い Webhook を無効にし公開資格をリセットします。
確認失敗後も attempt が pending なら、ファイルを修正し、24 時間以内に verification を再度 queue してください。期限切れまたは終了した attempt では、同じ URL を再登録し、新しい document を公開して新しい attempt を queue します。verification の 409: 利用可能な pending attempt なし。503: queue 利用不可で、成功ではありません。backoff で再試行。401: token 更新または再ログインが必要です。
ownership が通過した後
owner access と最初の公開は別です。verified-tier card は ownership verification 完了後、initial または scheduled observation が 3 回以上通過すると公開されます。manual probe は含まれません。待機中の公開 404 は ownership の失敗ではありません。owner 専用の履歴で調べます。
curl "https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/observations?page=1&page_size=20" \
-H "authorization: Bearer $ACCESS_TOKEN"
data.observations と各 probe_type を確認します。非公開の診断は下の command を実行し、新しい manual observation をこの履歴で polling します。202 は queue に入ったことだけを示します。manual の結果は public card、公開資格、manifest、通知を変更しません。
curl -X POST \
"https://ifandonlyif.io/api/v3/endpoints/ENDPOINT_UUID/probes" \
-H "authorization: Bearer $ACCESS_TOKEN"
次に変更通知を設定します。monitoring を停止して card を非公開にするには、下の owner 専用操作を使います。Webhook と送信待ち delivery も停止しますが、immutable observation、claim-attempt の監査情報、transparency-log entry は残ります。キャッシュ済みの card は最大 30 秒表示されることがあります。再開するには同じ URL を登録し、control を再度証明してください。
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 の場合、履歴と停止は使えますが、ownership が再検証されるまで Webhook 作成と manual probe は 409 を返します。
ownership が証明するのは monitoring 対象 origin の control だけです。backend の運用者、payment 後の動作、endpoint が safe かどうかは証明しません。
04 · Reference
endpoint リファレンス.
:id で終わる path parameter は UUID です。pagination は page と最大 100 の page_size を受け付けます。各 GET route は HEAD にも応答します。public route と POST /api/v3/verify は Access-Control-Allow-Origin: * を返し、authentication が必要な route は返しません。
公開と authentication
| Method | Path | Purpose |
|---|---|---|
| GET | /health | liveness と大まかな dependency boolean(service name、version、component label は含みません)。 |
| 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 付きの immutable な日次 evidence manifest を取得します。これは上の endpoint ID とは別の ID 空間です。manifest ID は Evidence Card の anchor.manifest_uri から取得してください。ここに endpoint ID を渡すと、理由を示すメッセージとともに 404 を返します。 |
| GET | /api/v3/log/anchors/latest | signed transparency-log tree head に対する、最新の submitted または confirmed ERC-8004 anchor。 |
| POST | /api/v3/auth/challenge | one-time wallet challenge を作成します。 |
| POST | /api/v3/auth/verify | EIP-191 signature を検証し、token pair を発行します。 |
| POST | /api/v3/auth/refresh | single-use refresh token を rotate します。 |
| POST | /api/v3/verify | 受け取った x402 requirement を independent observation と preflight-check します。 |
| GET | /api/v3/receipts/keys | 任意かつ実験的な Service Receipt v2 の current および retained public key(v1 key は previous として掲載)。 |
| GET | /api/v3/badge/:id.json | endpoint の current requirement consistency 用 shields.io endpoint-badge JSON。 |
authenticated wallet と endpoint owner
下のすべての route に Authorization: Bearer <access_token> が必要です。登録、polling、verification は attempt を作成した wallet 用で、management route は verified または stale の ownership が必要です。
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v3/endpoints | 独立した、authorization を付与しない claim attempt と ownership challenge を作成します。 |
| GET | /api/v3/endpoints | authoritative endpoint と、この wallet の claim-attempt audit status を一覧表示します。 |
| DELETE | /api/v3/endpoints/:id | immutable evidence を保持したまま endpoint を非公開にします。 |
| POST | /api/v3/endpoints/:id/verify-ownership | well-known ownership verification を queue に入れます。 |
| POST | /api/v3/endpoints/:id/probes | owner-only manual observation を queue に入れます。 |
| GET | /api/v3/endpoints/:id/observations | pagination された full observation history を読み取ります。 |
| POST | /api/v3/endpoints/:id/webhooks | status または requirement change 用の owner webhook を作成します。secret は 1 回だけ返されます。 |
| GET | /api/v3/endpoints/:id/webhooks | secret を含めずに active target を一覧表示します。 |
| DELETE | /api/v3/endpoints/:id/webhooks/:webhookId | webhook と pending delivery を deactivate します。 |
| POST | /api/v3/endpoints/:id/erc8004 | owner が保持する ERC-8004 agent identity を link します。 |
05 · Response model
各ディメンションを独立して読む。
ownership- 現在の domain-control status、method、verification time。
protocol- 最新の x402 parse result、version、名前付き check、advertised payment option。
availability- 24 時間・7 日間の sample、percentage rate、p50/p95 latency。
freshness- 最新の observation が publication freshness window 内にあるかどうか。
evidence- canonical report hash、monitor identity、ML-DSA-65 signature(旧 report は Ed25519)、public key。
anchor- 任意の daily manifest chain status と transaction provenance。
rate は 0 から 100 の百分率です。missing measurement は省略されるか null です。pass と推論しないでください。
observed tier の probe は UTC 日ごとにも集計されます。終了した日は 1 つの日次確認ドキュメントに封印され、その hash は 1 つの leaf として transparency log に入ります。change-only storage を有効にすると、署名付き observation 全体は observed state が変化したときだけ保存されます。GET /api/v3/evidence/observed-confirmations/:day(または /latest)は元の body、document_hash、leaf_hash と commitment level(sealed、logged、anchored)を返します。これは monitor が観測した統計であり、すべての probe が実行された証明ではありません。
06 · Webhooks
すべての delivery を検証する。
derived operational status が変わると owner subscription は endpoint.status_changed を、eligible observation が異なる payment requirement fingerprint を示すと endpoint.requirement_changed を受け取ります(attack の証明ではありません)。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 は受信側 server に保管してください。secret は一度しか表示されず、再取得できません。target は公開 HTTPS/443 で、credentials、query string、fragment、redirect を含められません。有効な target の重複、または有効な subscription が 10 件を超えると 409 を返します。
subscription を作成してもテストイベントは送信されません。イベントは対象となる observation の変化で発生し、probe ごとではありません。通知に頼る前に、受信側で下の header を検証してください。
X-IFF-Timestamp: 1700000000
X-IFF-Signature: sha256=<hex digest>
Idempotency-Key: <delivery uuid>
- 許容する clock-skew window 外の timestamp を拒否します。
- one-time secret を使い、
timestamp + "." + raw_bodyに対して HMAC-SHA256 を計算します。 - hex digest を constant time で比較します。
Idempotency-Keyで deduplicate します。繰り返された delivery にも 2xx を返します。
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 を返し、送信待ち delivery を停止しますが、endpoint の公開は停止しません。secret を失ったら削除して作り直してください。secret を client-side code に公開してはいけません。
07 · Preflight
支払う前に確認する。
受け取った x402 payment requirement に対して action する前に、IFF の独立した signed observation と比較します。URL を probe せず、保存するのは observation がない場合の normalized URL だけです。verdict は consistent、diverged、unobserved、stale のいずれかで、composite score はなく、safety、delivery、trust の主張もしません。
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
- 任意の language から
POST /api/v3/verifyを使用できます。public preflight check に API key は不要です。 - Badge

実験的 capability showcase:Service Receipt v2
Service Receipt v2 は単一の verification result に対する任意の signed artifact で、core preflight contract には含まれません。response、verification-request digest、5 分間の action window を IFF 専用の ML-DSA-65 receipt key で結び付けます。receipt を省略するか null を送れば response は変わりません。{} または "version":"2" は v2 を発行し、"1" は 422 を返します。既存の v1 receipt は引き続き検証できます。
"receipt":{"version":"2","nonce":"checkout_7f3a"}
- Signed artifact
- この機能を有効にして成功すると、他の response field を変更せずに
service_receiptが追加されます。 - Local verifier
- 単独の envelope または API response 全体を Receipt showcase(英語) に貼り付けてください。検証はブラウザ内でローカルに実行されます。
curl "https://ifandonlyif.io/api/v3/receipts/keys"
Service Receipt は payment、service delivery、caller identity、remote execution、result correctness、safety を証明しません。receipt key が内包された result に署名したことを記録するだけです。
有効な ML-DSA-65(v2)または Ed25519(v1)signature は、内包された key が receipt に署名したこと(provenance であり attestation ではない)を示しますが、その key が申告された issuer に属することは示しません。same-origin HTTPS key directory との一致は認識されます。最も厳格な policy では、正確な issuer と、独立した経路で pin した完全な sha256: fingerprint も照合します。復号した signed subject が正で、外側の response と比較します。参照された evidence は専用の proof を検証するまで未検証です。IFF は現在 compute_proof を null に設定します。
08 · エラーと制限
evidence を推論せずに失敗として扱う。
{
"error": true,
"message": "human-readable reason"
}
| status | 意味 |
|---|---|
400 | 不正な JSON、UUID、URL、pagination、または input shape。 |
401 | token が missing、invalid、expired、replayed、または token type が不正。 |
403 | authenticated wallet は request された resource を所有していません。 |
404 | public evidence または要求された owner resource がありません。 |
409 | ownership state、duplicate target、または resource state が conflict しています。 |
422 | 無効な x402 requirement、receipt version、または receipt nonce。 |
429 | rate limit に到達しました。backoff して retry します。 |
503 | evidence repository、queue、registry、receipt issuance、または別の dependency が unavailable です。 |
IFF は external observer です。paid canary transaction を実行せず、payment-safety の主張をせず、payment 後の delivery を保証せず、endpoint が trustworthy かも判断しません。monitor signature が示すのは provenance と tamper evidence であり、attestation ではありません。