開発者向け

エージェントが自分ではできない作業を、人に頼めるようにする

店の様子を見に行く、紙の資料を書き起こす、実物を確かめる、電話で問い合わせる。MCP のツールを足すか REST API を呼べば、こうした作業を人に頼めます。人を探す、連絡する、支払うといった手間は ProofMarket が引き受けます。

返ってくるのは答えだけではありません。AI が写真と答えを依頼文と突き合わせた判定、何人の答えが一致したか、Solana に記録した結果と支払いの署名も一緒に返るので、エージェントはその結果を使ってよいかを自分で判断できます。

つなぎ方は3通りあります

どれを選んでも、使えるキーと上限は同じです。試験運用中は API キー(pm_test_ で始まる)を運営者が発行します。API キーを申し込む依頼者の画面(履歴・残高)

claude.ai などのリモート MCP

コネクタの追加画面にこの URL を入れます。接続のときに ProofMarket の画面が開くので、そこで API キーを入れます。キーがアプリ側に保存されることはありません。

https://proofmarket.fun/mcp

Claude Code などのローカルのエージェント

同じ URL に、API キーをヘッダーで渡して登録します。

claude mcp add --transport http proofmarket https://proofmarket.fun/mcp \
  --header "Authorization: Bearer pm_test_..."

REST API

依頼の作成には Idempotency-Key ヘッダーが要ります。同じキーで送り直しても、依頼は1件しかできません。

curl -X POST https://proofmarket.fun/v1/verifications \
  -H "Authorization: Bearer $PROOFMARKET_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d @request.json
curl https://proofmarket.fun/v1/verifications/ver_... \
  -H "Authorization: Bearer $PROOFMARKET_API_KEY"

各 AI からつなぐ

同じ MCP の窓口に、それぞれのやり方でつなぎます。「確認済み」は、運営者がこの本番の窓口に実際につないで結果を読めたものです。

  • Claude Code

    確認済み
    1. ターミナルで claude mcp add --transport http proofmarket https://proofmarket.fun/mcp --header "Authorization: Bearer <API キー>" を実行する
    2. claude を起動し、「ProofMarket の道具を一覧して」と頼む。4つ以上の道具が出れば接続できている

    キーをチャットに貼らない。--header の値はこの端末の設定にだけ残る

  • claude.ai(ブラウザ・アプリ)

    確認済み
    1. 設定 → コネクタ → 「カスタムコネクタを追加」を開く
    2. 名前に ProofMarket、URL に https://proofmarket.fun/mcp を入れて追加する
    3. 「接続」を押すと ProofMarket の許可画面が開く。API キーを貼って許可する
    4. 新しい会話で ProofMarket を有効にし、依頼を出す

    OAuth 2.1(動的クライアント登録・PKCE)で接続する。キーは ProofMarket 側にだけ渡る

  • ChatGPT

    手順のみ(未確認)
    1. 設定 → アプリ → 詳細設定 で「開発者モード」をオンにする(Plus 以上)
    2. 設定 → コネクタ → 「カスタムコネクタを追加」で URL に https://proofmarket.fun/mcp、認証に OAuth を選ぶ
    3. 許可画面で API キーを貼る

    ChatGPT は動的クライアント登録に対応していて、ProofMarket 側もそれを出している

  • Cursor・Windsurf などの MCP 対応エディタ

    手順のみ(未確認)
    1. MCP の設定に { "url": "https://proofmarket.fun/mcp", "headers": { "Authorization": "Bearer <API キー>" } } の形で足す
    2. OAuth に対応したクライアントなら headers を省き、接続時に出る許可画面でキーを貼る
  • 自作のエージェント(REST・SDK)

    確認済み
    1. Authorization: Bearer <API キー> を付けて REST API を呼ぶ。依頼の作成には Idempotency-Key が要る
    2. TypeScript なら packages/sdk の ProofMarketClient を使う。MCP サーバーもこの SDK の上に載っている

つながらないときは、画面に出た文言をそのまま申し込みフォームから送ってください。OAuth の窓口は https://proofmarket.fun/.well-known/oauth-authorization-server で確かめられます。

登録なしで使う(x402)

API キーがなくても、Solana のウォレットを持つエージェントなら依頼を出せます。依頼ごとに USDC を払う方式で、申し込みも契約も要りません。支払いの形式は x402(v2)の exact 方式に従っています。

  1. 依頼をPOST /v1/x402/verificationsに送ります。中身は request.json と同じで、principal_ref は要りません。
  2. 402 が返ります。PAYMENT-REQUIRED ヘッダーに、払う額(報酬×人数)、宛先、通貨(Devnet の USDC)、手数料を持つ側の公開鍵が入っています。中身に問題がある依頼は、払う前に 400 などで断ります。
  3. 指定どおりの USDC の送金取引を作り、自分の鍵で署名します。手数料は ProofMarket が持つので、ウォレットに SOL は要りません。
  4. 同じ依頼を PAYMENT-SIGNATURE ヘッダー付きで送り直します。取引が Solana で確定してから依頼が作られ、201 で verification_id、結果を読むための API キー、支払いの取引の URL が返ります。
# 1回目: 402 と支払い条件
curl -i -X POST https://proofmarket.fun/v1/x402/verifications \
  -H "Content-Type: application/json" -d @request.json

# 2回目: 署名した取引を付けて送り直す
curl -X POST https://proofmarket.fun/v1/x402/verifications \
  -H "Content-Type: application/json" -d @request.json \
  -H "PAYMENT-SIGNATURE: <base64 の PaymentPayload>"
# 見本のエージェント(リポジトリの scripts/)。402 の受け取りから結果待ちまで通しで動く
# 17 種類どれでも出せる。種類の一覧は --list-types、送らずに中身を見るなら --dry-run
A="pnpm --filter @proofmarket/scripts run run x402-agent.ts --base-url https://proofmarket.fun"

$A --type DOCUMENT_TRANSCRIPTION --question "届いた紙の請求書の合計金額の行を書き写してください"
$A --type PHONE_INQUIRY --question "この番号の病院に、今日の午後の外来の受付時間を聞いてください"
$A --type MEASUREMENT --unit cm --question "玄関のドアの幅を測ってください"
$A --type CUSTOM_CHOICE --choices "はい,いいえ" --question "この駅のエレベーターは今動いていますか"
$A --type PLACE_STATUS_VERIFICATION --lat 35.6595 --lng 139.7005

同じ取引を2回送っても、依頼は1件しかできません。2回目は同じ verification_id を返し、API キーは付けません。1件の上限は 5 USDC です。テスト用の USDC は Circle の faucet(Solana Devnet)で受け取れます。

結果を利用者に見せる(証明のリンク)

エージェントが利用者に答えるとき、「AI の推測ではなく、人が確かめた事実だ」と示せます。

結果が出ると、result.proof に3つの値が入ります。url は公開の結果ページで、いつ・何人が・どう確かめたかと、Solana の記録を誰でも見られます。badge_url は答えと時刻を1行で示す画像、markdown はそのバッジをリンク付きで貼れる文字列です。質問文・写真・位置・文章の答えは、このページに出ません。

"proof": {
  "url": "https://proofmarket.fun/r/ver_01J9Z4K8...",
  "badge_url": "https://proofmarket.fun/r/ver_01J9Z4K8.../badge.svg",
  "markdown": "[![人が確認](https://proofmarket.fun/r/ver_01J9Z4K8.../badge.svg)](https://proofmarket.fun/r/ver_01J9Z4K8...)"
}

結果をみんなの地図に載せる

公共の場所についての事実は、依頼した本人のほかにも役に立ちます。

依頼に "publish": true を付けると、結果が VERIFIED になったときみんなの地図に72時間載ります。公開されるのは、質問文、指定した場所、答え、確かめた時刻と人数です。質問文に個人の事情を書いた依頼には付けないでください。場所のある依頼で、答えが選択か数値のものだけが対象で、それ以外は 400 を返します。一覧は GET /v1/public/map でも読めるので、ほかのエージェントが依頼を出す前に調べる使い方もできます。

MCP のツール(7つ)

request_reality_verification
質問を出す。verification_id がすぐ返り、結果は後から読む
get_reality_verification
状態と結果を読む。wait_seconds(最大20秒)で変化を待てる
cancel_reality_verification
まだ誰も向かっていない依頼を取り消す。拘束した額は残高に戻る
dispute_reality_verification
結果に異議を出す。確定から24時間以内に1回だけ。同じ場所・同じ質問の再確認(既定は2人一致)を新しく作る
watch_reality_verification
見守りを始める。望む答えが返るまで決めた間隔で確かめ続け、合ったら止まる。回数の上限も付けられる
list_reality_verification_watches
見守りと定期確認の一覧。止まった理由と、条件に合った依頼の ID が分かる
stop_reality_verification_watch
見守りや定期確認を止める。すでに作られた依頼はそのまま進む

人が現地まで行くので、結果が出るまでふつう10〜60分かかります。状態が VERIFIED・REJECTED・EXPIRED のどれかになるまで、エージェントに答えを推測させないでください。

依頼の中身

request.json の例です。principal_ref は API キーと一緒に渡される ID です。

{
  "type": "PLACE_STATUS_VERIFICATION",
  "question": "この店はいま営業していますか?",
  "answer_schema": { "type": "enum", "values": ["OPEN", "CLOSED", "UNCLEAR"] },
  "location": { "lat": 35.6595, "lng": 139.7005, "radius_m": 80 },
  "deadline": "2026-10-12T12:00:00+09:00",
  "evidence_requirements": { "photo": true, "task_nonce": true },
  "assurance": { "level": "standard" },
  "bounty": { "asset": "USDC", "amount": "0.5", "network": "solana-devnet" },
  "principal_ref": "prn_..."
}
question
確かめたいこと・してほしい作業。1000字まで。本なら書名・ページ・箇所まで書く
type
PLACE_STATUS_VERIFICATION(営業しているか)、QUEUE_LENGTH(店の外の行列)、NOTICE_POSTED(店頭の掲示)、CROWD_LEVEL(混み具合)、SEAT_AVAILABILITY(空席)、PARKING_AVAILABILITY(駐車場の空き)、STOCK_CHECK(在庫)、PRICE_CHECK(値段)、SIGN_TRANSCRIPTION(掲示・メニューの書き起こし)、SITE_REPORT(現地の様子の報告)、DOCUMENT_TRANSCRIPTION(本・紙資料の書き起こし)、DOCUMENT_QA(本・紙資料を読んで答える)、PRODUCT_INSPECTION(実物の確認)、PHONE_INQUIRY(電話での問い合わせ)、MEASUREMENT(計測)、CUSTOM_CHOICE(選んで答える質問)、CUSTOM_TASK(その他の作業)。API キーごとに使える種類を絞れる
answer_schema
答えの形。type ごとに決まっている。選択式は { "type": "enum", "values": [...] }(PLACE_STATUS_VERIFICATION: OPEN・CLOSED・UNCLEAR、QUEUE_LENGTH: NO_QUEUE・SHORT_QUEUE・LONG_QUEUE・UNCLEAR、NOTICE_POSTED: POSTED・NOT_POSTED・UNCLEAR、CROWD_LEVEL: EMPTY・MODERATE・CROWDED・UNCLEAR、SEAT_AVAILABILITY: SEATS_AVAILABLE・FULL・UNCLEAR、PARKING_AVAILABILITY: SPACES_AVAILABLE・FULL・UNCLEAR、STOCK_CHECK: IN_STOCK・OUT_OF_STOCK・UNCLEAR から2個以上。CUSTOM_CHOICE は自分で6個まで決める)。数値は { "type": "number", "unit": "円" }(PRICE_CHECK・MEASUREMENT)。文章は { "type": "text", "max_chars": 2000 }(ほかの種類)。文章の答えは結果の answers に全員分が入り、answer にはその SHA-256 が入る
location
緯度・経度と半径(25〜500m)。現地で行う種類では必須。本・電話・実物の確認など、場所を問わない種類では省ける
deadline
締め切り。今から10分後〜24時間後
freshness.max_age_seconds
写真が撮られてから何秒以内なら有効か。60〜3600秒、既定は300秒
assurance
何人に確かめてもらうか(required_witnesses、最大5人)と、何人の答えがそろえば確定か(quorum)。{ "level": "fast" | "standard" | "high" } と書けば、それぞれ1人・2人一致・3人中2人になる
bounty
1人あたりの報酬。試験運用中は Solana Devnet のテスト用 USDC
worker_requirements(任意)
{ "min_tier": "standard" | "trusted" } で、引き受けられる worker を記録の良い人に絞る。trusted は有効な提出が10件以上で、複数人の依頼での一致率が90%以上の人

結果の読み方

status が次の3つのどれかになったら確定です。確定までの途中の状態(OPEN、CLAIMED など)では result は null です。

VERIFIED
quorum 以上の答えがそろった。answer に答えが入る
REJECTED
答えが割れた(NO_CONSENSUS)か、有効な証言が足りなかった
EXPIRED
締め切りまでに確定しなかった。拘束した額は返金される

result には答えのほかに、有効な証言の数、一致率、場所・鮮度・写真の使い回しなどの確認結果、Solana に記録した証拠のハッシュと取引の URL が入ります。写真と正確な位置は入りません。写真を見たいときは、自分の依頼に限ってGET /v1/verifications/{id}/evidenceで5分間だけ有効な URL を取れます。店舗が自分で「本日臨時休業」などと申告していれば、GET の store_report に参考として入ります。判定には使っていません。

結果を待たずに受け取る(Webhook)

送り先の URL は運営者が登録します。本文には ProofMarket-Signature ヘッダーで署名が付き、5分以上ずれたものは捨ててください。

  • verification.open
  • verification.claimed
  • verification.submitted
  • verification.verified
  • verification.rejected
  • verification.settled
  • verification.expired
  • verification.cancelled

結果に納得できないとき

確定から24時間以内なら、1回だけ異議を出せます。同じ場所・同じ質問で、新しく再確認の依頼が作られます。費用はふつうの依頼と同じで、元の結果と支払いはそのまま残ります。

curl -X POST https://proofmarket.fun/v1/verifications/ver_.../dispute \
  -H "Authorization: Bearer $PROOFMARKET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "閉店の張り紙を見た", "assurance": { "level": "high" } }'

返る recheck_verification_id をふつうの依頼と同じように読みます。元の依頼の GET には recheck が付き、再確認の答えが元と同じだったか(matches_original)が分かります。違ったときは運営者が元の提出を見直します。

少し前の結果があれば、それを受け取る

依頼に reuse を付けると、同じ店について少し前に確定した結果を探し、あれば人を出さずにその場で返します。待ち時間がなく、試験運用中は費用もかかりません。

"reuse": { "max_age_seconds": 600 },   // 10分以内の結果があれば使う
"allow_reuse": true                     // 自分の結果をほかの依頼者に使わせてよい

使われるのは、元の依頼者が allow_reuse を付けた結果だけです。店・種類・答えの選択肢が同じで、VERIFIED のものに限ります。見つかれば 200 で reused: true と結果そのものが返り、新しい依頼は作られません。NOTICE_POSTED は質問ごとに見る掲示が違うので対象外です。

決まった時刻に繰り返し確かめる

「平日の朝 9 時に、この店が開いているか」のような確認は、予定として登録できます。時刻が来るたびに通常の依頼が1件作られるので、残高や上限、確認の手順はふつうの依頼と同じです。

curl -X POST https://proofmarket.fun/v1/schedules \
  -H "Authorization: Bearer $PROOFMARKET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request": { ...request.json から deadline を除いたもの },
    "deadline_minutes": 30,
    "times_jst": ["09:00"],
    "days_jst": [1, 2, 3, 4, 5]
  }'

時刻は日本時間、曜日は 0 が日曜です。できた依頼は Webhook か GET /v1/schedules の last_verification_id で追えます。残高不足などで3回続けて作れなかった予定と、API キーが止められた予定は自動で止まります。止めるときは DELETE /v1/schedules/{id} を呼びます。1つのキーで動かせる予定は10件までです。

望む答えが返るまで見守る

「エレベーターが復旧したら知らせて」「棚に入荷したら知らせて」のような依頼は、見守りとして登録できます。決めた間隔で確かめ続け、条件に合う答えが確定したら止まります。

curl -X POST https://proofmarket.fun/v1/schedules \
  -H "Authorization: Bearer $PROOFMARKET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request": { ...STOCK_CHECK の依頼。deadline は除く },
    "deadline_minutes": 60,
    "every_minutes": 120,                 // 2時間おき。最初の1回はすぐ
    "max_runs": 12,                       // 多くても12回で止まる
    "stop_when": { "answer": "IN_STOCK" } // この答えが確定したら止まる
  }'

1回ごとに通常の依頼が作られ、そのぶんだけ払います。条件は、選択で答える依頼なら { "answer": ... } か { "answer_in": [...] }、数値で答える依頼なら { "number": { "min": 1 } } のように書きます。文章で答える依頼には付けられません。条件に合うと、その依頼の verification.verified の Webhook が届き、GET /v1/schedules の stopped_reason が condition_met、matched_verification_id に合った依頼の ID が入ります。MCP では watch_reality_verification で同じことができます。

上限と支払い

API キーごとに、1件あたりの上限額と1日(日本時間)の上限額が決まっています。依頼を出すと、報酬×人数の額が前払いの残高から拘束され、確定すると worker に支払われます。期限切れや取り消しのときは残高に戻ります。試験運用中の残高は Solana Devnet のテスト用 USDC で、実際のお金は動きません。