Express API for verifying BringID Semaphore proofs on-chain.
Verifies proofs via the BringID SDK and a JSON-RPC provider for the given chain_id.
Content-Type:application/jsonapi-secret-key: required only whenREQUEST_VALIDATION=truein env; must matchAPI_SECRET.
| Field | Required | Type | Notes |
|---|---|---|---|
app_id |
yes | string | BringID app id (also used for SDK init). |
chain_id |
yes | integer | Supported: 8453 (Base), 84532 (Base Sepolia). RPC URLs come from env (BASE_MAINNET_RPC_URL, BASE_SEPOLIA_RPC_URL). |
proofs |
yes | array | Each item: credential_group_id, app_id, semaphore_proof (see below). |
contract |
no | string | Passed through to BringID verifyProofs. |
context |
no | integer | Passed through to BringID verifyProofs. |
semaphore_proof per proof item:
merkle_tree_depth(number)merkle_tree_root(string)nullifier(string)message(string)scope(string)points(string[])
{ "success": true, "verified": true }verified is true or false depending on on-chain verification.
400 — validation (Celebrate)
{
"success": false,
"error": "Validation error",
"errors": ["<code>", "..."]
}Codes are machine strings (e.g. CHAIN_ID_REQUIRED, APP_ID_BODY_REQUIRED).
400 — bad request (operational)
{
"success": false,
"error": "<message>",
"message": "<message>",
"errors": ["<cause>"]
}Examples: UNSUPPORTED_CHAIN_ID, RPC_URL_NOT_CONFIGURED.
403 — auth (when REQUEST_VALIDATION=true and header missing or wrong)
{
"success": false,
"error": "<message>",
"message": "<message>",
"errors": ["UNAUTHORIZED_REQUEST" | "API_SECRET_KEY_NOT_PROVIDED"]
}400 — ethers / contract-style (error.reason present)
{ "success": false, "errors": "<reason or structured reason>" }500 — unhandled
{ "success": false, "errors": ["SERVER_ERROR"] }curl -sS -X POST http://localhost:8000/api/v1/proof/verify \
-H "Content-Type: application/json" \
-d '{"app_id":"YOUR_APP","chain_id":84532,"proofs":[]}'Replace proofs with a valid proof array for real checks.