エンドポイント一覧
この文書は、公開ドキュメントとして扱う API を対象に、現行実装のレスポンス形状・要件を記載します。
対象外(内部向け)
以下は内部運用/デバッグ用途のため、この文書の詳細対象外です。
GET /api/debug/enablePOST /api/finalize/callback
デュアルランタイム構成
API ハンドラはフレームワーク非依存の共通実装で、Next.js と Hono(Lambda) の両方から利用されます。
| ランタイム | 用途 | 主な入口 |
|---|---|---|
| Next.js Route Handler | ローカル開発 / SSR | src/app/api/**/route.ts |
| Hono on Lambda | AWS デプロイ API | amplify/functions/hono-api/handler.ts |
公開対象 API 一覧
| メソッド | パス | 主用途 | X-Session-ID | X-Session-Capability |
|---|---|---|---|---|
POST | /api/session | セッション作成 | 不要 | 不要 |
POST | /api/vote | 投票送信 | 必須 | 不要 |
GET | /api/progress | ボット投票進捗 | 必須 | 必須 |
POST | /api/finalize | 集計/証明生成 | 必須 | 必須 |
POST | /api/finalize/cancel | 非同期集計キャンセル | 必須 | 必須 |
GET | /api/sessions/:sessionId/status | 非同期集計ステータス | 不要 | 必須 |
GET | /api/verify | 検証ペイロード取得 | 必須 | 必須 |
POST | /api/verification/run | STARK 検証実行 | 必須 | 必須 |
GET | /api/verification/bundles/:sessionId/:executionId | バンドル ZIP 取得 | 不要 | 必須 |
GET | /api/verification/bundles/:sessionId/:executionId/report | 検証レポート取得 | 不要 | 必須 |
GET | /api/bulletin | 掲示板一覧(inspection) | 必須 | 必須 |
GET | /api/bulletin/:voteId/proof | 最小包含証明 | 必須 | 必須 |
GET | /api/bulletin/consistency-proof | 整合性証明(tooling) | 必須 | 必須 |
GET | /api/botdata/:id | ボット投票データ(tooling) | 必須 | 必須 |
GET | /api/bitmap-proof | ビットマップ証明材料 | 必須 | 必須 |
GET | /api/sth | STH スナップショット | 必須 | 必須 |
GET | /api/zkvm-input-hash | zkVM 入力コミットメント | 不要 | 必須 |
共通の実装上の注意
ミドルウェア構成
ミドルウェアは「全リクエスト共通の固定チェーン」ではなく、エンドポイント実装ごとに必要な検証を呼び出す方式です。セッションヘッダーの要否は上記一覧テーブルを参照してください。
| 区分 | 代表エンドポイント | Turnstile | レート制限 |
|---|---|---|---|
| セッション作成 | POST /api/session | 環境設定次第 | セッション作成用 |
| 投票 | POST /api/vote | あり | 投票用 |
| 集計 | POST /api/finalize | あり | zkVM 用 |
| 非同期集計キャンセル | POST /api/finalize/cancel | なし | キャンセル専用 |
| 検証実行 | POST /api/verification/run | なし | zkVM 用 |
| 読み取り(セッションスコープ) | GET /api/progress, GET /api/bulletin*, GET /api/botdata/:id, GET /api/bitmap-proof, GET /api/sth, GET /api/verify | なし | なし |
| 読み取り(path/query で session を指す) | GET /api/sessions/:sessionId/status, GET /api/verification/bundles/..., GET /api/zkvm-input-hash | なし | なし |
共通セッションエラー(ヘッダースコープ)
X-Session-ID / X-Session-Capability をヘッダーで受け取る大多数のエンドポイントは、validateSessionWithCapability() を経由し、以下の共通エラーを返し得ます。各エンドポイントの「主なエラー」欄ではこれらを省略し、固有エラーのみ記載します。
SESSION_ID_REQUIRED(400)SESSION_CAPABILITY_REQUIRED(401)SESSION_CAPABILITY_INVALID(401)SESSION_CAPABILITY_EXPIRED(401)SESSION_NOT_FOUND(404)
パス/クエリで session を指定するエンドポイント(/api/sessions/:sessionId/status, /api/verification/bundles/..., /api/zkvm-input-hash)も capability 検証は共通ですが、session 特定エラーの形式が異なるため、各エンドポイントで個別に記載します。
ボディサイズ制限
共通 JSON パーサーを使うエンドポイントは API_REQUEST_BODY_LIMIT_BYTES(既定 16 KiB)を超えると PAYLOAD_TOO_LARGE (413) を返します。
例外:
POST /api/finalize/cancelは現状request.json()を直接使うため、この共通サイズ制限の対象外です。JSON 不正や payload 不正は handler 固有の400を返します。
エラーレスポンスの形式
多くのエンドポイントは errorResponse(...) を通して以下の形式を返します。
error(エラーコード)message(メッセージ)statusCode(HTTP ステータス)- 必要に応じて
detailsなど
例えば以下のエンドポイントでは、session/capability 失敗は標準形式ですが、handler 内部の個別検証では { error: "..." } 系の独自形式を返す場合があります。
POST /api/finalize/cancelGET /api/sessions/:sessionId/statusGET /api/bulletin/consistency-proofGET /api/bitmap-proofGET /api/zkvm-input-hash
基本フロー API
POST /api/session
新規セッションを作成します。X-Session-ID は不要です。
レスポンス(200):
data.sessionIddata.electionIddata.electionConfigHashdata.logIddata.capabilityToken
備考:
SESSION_CREATE_TURNSTILE_REQUIRED=1の場合、turnstileTokenが必要です。
POST /api/vote
ユーザー投票を保存し、ボット投票を非同期開始します。
要件:
- ヘッダー:
X-Session-ID必須 - ボディ:
commitment,vote,rand(turnstileTokenは開発設定により省略可) - Turnstile 検証あり
- 投票用レート制限あり
レスポンス(200):
data.voteIddata.commitmentdata.bulletinIndexdata.bulletinRootAtCastdata.timestamp
主なエラー:
CAPTCHA_FAILED(403)GLOBAL_LIMIT_EXCEEDED(503)ALREADY_VOTED(400)SESSION_FINALIZED(400)INVALID_REQUEST(400; リクエスト形式不正)INVALID_COMMITMENT(400)DUPLICATE_VOTE(409)PAYLOAD_TOO_LARGE(413)
GET /api/progress
投票進捗を取得します。
レスポンス(200):
data.countdata.totaldata.completeddata.userVoteddata.finalized
主なエラー: 共通セッションエラー(ヘッダースコープ)のみ。
POST /api/finalize
集計と証明生成を開始します。同期/非同期の 2 形態があります。
要件:
- ヘッダー:
X-Session-ID必須、X-Session-Capability必須 - ボディ:
scenarioId(S0-S5),turnstileToken(環境により必須) - Turnstile 検証あり
- zkVM レート制限あり
レスポンス(200, 同期):
data.sessionIddata.tallydata.bulletinRootdata.verifiedTallydata.voteReceiptdata.receipt(同期成功レスポンスで返却)data.receiptPublication(保存時)data.imageIddata.userVotedata.missingSlotsdata.invalidPresentedSlotsdata.rejectedRecordsdata.missingIndicesdata.invalidIndicesdata.countedIndicesdata.totalExpecteddata.treeSizedata.excludedSlotsdata.excludedCountdata.sthDigestdata.seenBitmapRoot(条件付き)data.includedBitmapRootdata.inputCommitmentdata.seenIndicesCountdata.journaldata.verificationStatusdata.verificationBundleUrl/data.verificationReportUrl/data.verificationReport(条件付き)data.verificationExecutionId(条件付き)data.s3BundleUrl/data.s3BundleKey/data.s3UploadedAt/data.s3BundleExpiresAt(条件付き)data.tamperSummary(条件付き)
補足:
verificationBundleUrlは秘密データを除外した配布用アーカイブの capability 認証付き取得先です。s3BundleUrlは同内容の短命な署名付き URL です。いずれも無認証では取得できません。
レスポンス(202, 非同期):
executionIdstatusUrlstatequeue(nullの場合あり)
主なエラー:
CAPTCHA_FAILED(403)INVALID_REQUEST(400)VERIFICATION_FAILED(400; CT proof unavailable)USER_NOT_VOTED(400)VOTING_NOT_COMPLETE(400)SESSION_ALREADY_FINALIZED(400)ZKVM_RATE_LIMIT_EXCEEDED(429)GLOBAL_LIMIT_EXCEEDED(503)PAYLOAD_TOO_LARGE(413)Invalid ImageID(400; 独自形式{ error: "Invalid ImageID", details: { expected, actual } })
POST /api/finalize/cancel
進行中の非同期集計をキャンセルします。
要件:
FINALIZE_ASYNC_MODE=trueのときのみ有効- ヘッダー:
X-Session-ID(x-session-idも受理) - ヘッダー:
X-Session-Capability必須 - ボディ:
executionId必須、reason任意 - キャンセル専用レート制限あり
レスポンス(200):
state
主なエラー:
GLOBAL_LIMIT_EXCEEDED(503)
handler 固有エラー(独自形式):
404: Async finalization disabled400: Invalid JSON body / payload 不正409: 現在状態ではキャンセル不可501: ストアが cancellation 非対応
GET /api/sessions/:sessionId/status
非同期集計の状態を返します。
要件:
- パスパラメータ
sessionId必須 - ヘッダー:
X-Session-Capability必須
レスポンス(200):
sessionIdfinalizationState(nullの場合あり)queue(nullの場合あり)progress(条件付き)finalizationResult(nullの場合あり)stepFunctions(nullの場合あり)asyncFinalizationMode(enabled/disabled)
主なエラー:
SESSION_CAPABILITY_REQUIRED(401)SESSION_CAPABILITY_INVALID(401)SESSION_CAPABILITY_EXPIRED(401)
handler 固有エラー(独自形式):
400: Session ID is required404: Session not found
検証 API
GET /api/verify
検証画面向けの統合ペイロードを返します。
要件:
- クエリ:
refreshS3=1,includeJournal=1(任意)
レスポンス(200):
data.electionIddata.electionConfigHashdata.logIddata.tallydata.bulletinRootdata.scenarioIddata.verificationStatusdata.verificationBundleUrl/data.verificationReport(条件付き)data.verificationSteps/data.verificationChecksdata.s3BundleUrl/data.s3UploadedAt/data.s3BundleExpiresAt(条件付き)data.imageIddata.tamperDetecteddata.verifiedTallydata.missingSlotsdata.invalidPresentedSlotsdata.rejectedRecordsdata.missingIndicesdata.invalidIndicesdata.countedIndicesdata.totalExpecteddata.treeSizedata.excludedSlotsdata.excludedCountdata.sthDigestdata.seenBitmapRoot(条件付き)data.includedBitmapRootdata.inputCommitmentdata.seenIndicesCount(条件付き)data.journalStatusdata.journal(includeJournal=1のとき)data.voteReceipt(条件付き)data.userVotedata.botVotesSummary(条件付き)data.verificationExecutionId(条件付き)data.tamperSummary(条件付き)
fail-closed 応答:
verificationStatusが許容セット外でも、ストアから取得可能な finalized session に対しては200で通常のdatapayload を返します。data.verificationStatusはfailedに正規化され、verificationSteps/verificationChecksに fail-closed な結果が入ります。
主なエラー:
SESSION_NOT_FINALIZED(400)USER_NOT_VOTED(400)
POST /api/verification/run
サーバー側で STARK レシート検証を実行します。
要件:
- ボディ: JSON オブジェクト(通常は空オブジェクト
{}) - zkVM レート制限あり
レスポンス(200):
data.verificationStatus(success/failed/dev_mode/not_run/running)data.verificationExecutionIddata.estimatedDurationMsdata.idempotent
挙動:
- 既存結果がある場合や実行中の場合は、再実行せず
idempotent: trueを返します。
主なエラー:
SESSION_NOT_FINALIZED(400)INVALID_REQUEST(400)ZKVM_RATE_LIMIT_EXCEEDED(429)GLOBAL_LIMIT_EXCEEDED(503)PAYLOAD_TOO_LARGE(413)INTERNAL_ERROR(500)
バンドル取得 API
両エンドポイントとも X-Session-Capability ヘッダーによる capability 保護が必須です。S3 配信が有効な場合、または Lambda ランタイムでは 302 で期限付き presigned URL にリダイレクトします。
GET /api/verification/bundles/:sessionId/:executionId
秘密データを含まない配布対象アーカイブ bundle.zip を返します。
レスポンス:
200: ZIP バイナリ302: S3 presigned URL へリダイレクト
主なエラー:
SESSION_CAPABILITY_REQUIRED(401)SESSION_CAPABILITY_INVALID(401)SESSION_CAPABILITY_EXPIRED(401)400: パラメータ不正404: バンドル未検出500: ダウンロード URL 生成失敗 / 読み込み失敗
GET /api/verification/bundles/:sessionId/:executionId/report
検証レポート verification.json を返します。これは capability 保護された非公開レポートであり、公開バンドルには含まれません。
レスポンス:
200: JSON302: S3 presigned URL へリダイレクト
主なエラー:
SESSION_CAPABILITY_REQUIRED(401)SESSION_CAPABILITY_INVALID(401)SESSION_CAPABILITY_EXPIRED(401)400: パラメータ不正404: レポート未検出500: ダウンロード URL 生成失敗 / 読み込み失敗
掲示板 API
GET /api/bulletin
掲示板一覧を返します。
要件:
- クエリ:
offset,limit(任意)
レスポンス(200):
commitmentsbulletinRoottreeSizetimestamprootHistory(条件付き)nextOffset/hasMore(ページング時)
主なエラー:
INVALID_OFFSET(400)INVALID_LIMIT(400)INVALID_REQUEST(400;details=BULLETIN_STATE_UNAVAILABLE)
GET /api/bulletin/:voteId/proof
最小形式の包含証明を返します。
要件:
- セッションは finalized 必須
- パス:
voteId(UUID v4 形式)
アクセス制御:
- 原則は「そのセッションのユーザー投票」のみ
- 例外としてシナリオ
S3/S4では対象ボット票を許可
レスポンス(200):
voteIdproof.leafIndexproof.merklePathproof.treeSizeproof.bulletinRootAtCastproof.proofMode
キャッシュ:
Cache-Control: private, no-storeVary: X-Session-ID, X-Session-Capability
主なエラー:
INVALID_VOTE_ID(400)SESSION_NOT_FINALIZED(400)VOTE_NOT_FOUND(404)VERIFICATION_FAILED(400; CT proof unavailable)
GET /api/bulletin/consistency-proof
RFC6962 整合性証明を返します。
補足:
- shipped
/verifyページの verdict authority には含まれません - 現在は secondary tooling / inspection 用の surface として扱います
要件:
- クエリ:
oldSize,newSize必須
レスポンス(200):
oldSizenewSizerootAtOldSizerootAtNewSizeproofNodesoldSubtreeHashes/appendSubtreeHashes(条件付き)timestamp
主なエラー(handler 固有、独自形式):
400:oldSize/newSize欠落・不正・範囲外、掲示板未初期化、proof 生成失敗500: consistency proof 生成中の内部エラー
GET /api/botdata/:id
ボット投票(1..63)のデータと証明を返します。
補足:
- 将来の bot verification UI の building block であり、現行
/verifyページの authority には含まれません
要件:
- セッション finalized 必須
レスポンス(200):
data.iddata.votedata.randomdata.commitmentdata.voteIddata.timestampdata.proof(leafIndex,merklePath,treeSize,bulletinRootAtCast,proofMode)
主なエラー:
INVALID_BOT_ID(400)SESSION_NOT_FINALIZED(400)BOT_DATA_NOT_FOUND(404)INTERNAL_ERROR(500; CT proof を組み立てられない場合を含む)
補助 API
GET /api/bitmap-proof
ビットマップ証明の材料を返します。
要件:
- クエリ:
i(0 以上整数)必須 - クエリ:
kind任意(included/seen、省略時はincluded)
備考:
- 全ストア実装で sessionId をキーに保存済み bitmap を参照します。
includedは counted された index、seenは prover に提示された index を対象にします。
レスポンス(200):
leafChunkauditPath
キャッシュ:
ETag対応If-None-Match一致時304Cache-Control: private, max-age=86400, stale-while-revalidate=3600, immutableVary: X-Session-ID, X-Session-Capability
主なエラー(handler 固有、独自形式):
INVALID_INDEX(400)INVALID_BITMAP_KIND(400)BITMAP_NOT_FOUND(404)INTERNAL_ERROR(500)
GET /api/sth
STH スナップショットを返します。
要件:
- finalized セッションのみ
レスポンス(200):
sth.sthDigeststh.bulletinRootsth.treeSizesth.timestampsth.logId
備考:
- 現行実装の
sth.timestampはジャーナル内時刻ではなく、session.lastActivityを返します。
主なエラー:
SESSION_NOT_FINALIZED(404; このエンドポイント固有の扱い)INTERNAL_ERROR(500; 例: finalized 済みだが journal が欠落している場合)
GET /api/zkvm-input-hash
セッション由来の zkVM 入力コミットメントを返します。
要件:
- クエリ:
sessionId必須 - ヘッダー:
X-Session-Capability必須 - クエリ:
includeData任意(true/1/yesで有効) includeData=trueは debug authorization が必要
レスポンス(200):
inputCommitmentdata(includeData有効時のみ)
主なエラー:
SESSION_CAPABILITY_REQUIRED(401)SESSION_CAPABILITY_INVALID(401)SESSION_CAPABILITY_EXPIRED(401)
handler 固有エラー(独自形式):
INVALID_REQUEST(400)SESSION_NOT_FOUND(404)SESSION_NOT_FINALIZED(400)CT_PROOF_UNAVAILABLE(400)INCLUDE_DATA_FORBIDDEN(403)INTERNAL_ERROR(500)