DEV Community

Cover image for Wallet Auth: Gate Any API on What a Wallet Holds
Douglas Borthwick
Douglas Borthwick

Posted on • Originally published at insumermodel.com

Wallet Auth: Gate Any API on What a Wallet Holds

Every authentication system in production today proves who you are. OAuth proves you logged in with Google. API keys prove you registered. JWTs prove a server issued you a session. Wallet Auth proves what you own. That is a different primitive — and it points to something bigger: blockchain state converted into standard internet credentials, consumable by any system that understands a JWT. Wallet Auth does not prove control of a wallet. It proves that a wallet meets specific on-chain conditions.

What Wallet Auth is

Wallet Auth by InsumerAPI is a new category of API access control where access decisions are based on wallet state: what a wallet holds, what it has staked, what credentials it carries. Not identity. Not login sessions. On-chain facts.

The output is a standard ES256 JWT bearer token. The input is a blockchain verification across any of 32 supported chains. Between those two points, InsumerAPI reads the chain, evaluates the conditions you specify, and signs a JWT containing the results. The verifying side never touches a blockchain. That is the architectural point: blockchain data consumed without blockchain infrastructure.

Add "format": "jwt" to any POST /v1/attest request. The response includes a jwt field alongside the standard sig and kid. Same endpoint, same credit cost, one extra field.

How it works

A Wallet Auth request is identical to a standard attestation request with one addition:

Wallet address
      ↓
POST /v1/attest  { format: "jwt" }
      ↓
InsumerAPI reads blockchain state
      ↓
ES256 JWT credential (30 min TTL)
      ↓
API gateway / middleware verifies via JWKS
      ↓
Access decision
Enter fullscreen mode Exit fullscreen mode
curl -X POST https://api.insumermodel.com/v1/attest \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "wallet": "0x1234...abcd",
    "format": "jwt",
    "conditions": [{
      "type": "token_balance",
      "contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "chainId": 1,
      "threshold": 1000,
      "decimals": 6
    }]
  }'
Enter fullscreen mode Exit fullscreen mode

The response includes data.jwt, a three-part ES256-signed JWT. Decode the payload and you get standard claims:

{
  "iss": "https://api.insumermodel.com",
  "sub": "0x1234...abcd",
  "jti": "ATST-A7C3E1B2D4F56789",
  "iat": 1741089600,
  "exp": 1741091400,
  "pass": true,
  "results": [{
    "condition": 0,
    "label": "USDC >= 1000",
    "type": "token_balance",
    "chainId": 1,
    "met": true,
    "evaluatedCondition": {
      "type": "token_balance",
      "contractAddress": "0xA0b8...eB48",
      "chainId": 1,
      "threshold": 1000,
      "decimals": 6
    },
    "conditionHash": "0x3a7f...",
    "blockNumber": "0x12a3b4f",
    "blockTimestamp": "2026-03-04T12:00:00Z"
  }],
  "conditionHash": ["0x3a7f..."]
}
Enter fullscreen mode Exit fullscreen mode

iss is the issuer (https://api.insumermodel.com). sub is the wallet address. exp is 30 minutes from issuance. pass is the overall boolean. results contains per-condition detail including the block number at which the chain was read. conditionHash is a SHA-256 of the evaluated conditions, so verifiers can confirm exactly what was checked. Short expiration ensures the credential reflects recent chain state.

Why this is different

Traditional auth answers: "Is this user who they claim to be?" Wallet Auth answers: "Does this wallet meet these conditions?" The distinction matters because it enables access control patterns that identity-based auth cannot express.

        - **Gate a premium API tier on stablecoin holdings.** Any wallet holding 10,000+ USDC on any of 7 chains gets access. No signup. No KYC. The JWT proves the holding.
        - **Restrict a governance endpoint to token holders.** Only wallets holding UNI, AAVE, or ARB can call the endpoint. The JWT encodes which conditions were met.
        - **Require a Coinbase Verified Account attestation.** The JWT proves a wallet has an EAS attestation on Base from Coinbase. No raw credential data exposed.
        - **Gate content on NFT ownership.** A BAYC holder gets a JWT that any downstream service can verify. The NFT contract is in the claims. The balance is not.
Enter fullscreen mode Exit fullscreen mode

In each case, the access decision is based on verifiable on-chain state. The JWT is the proof. The verifier needs no blockchain connection.

The portable credential

A Wallet Auth JWT can be forwarded from Service A to Service B and verified without re-querying the chain. Service B fetches the JWKS public key once, checks the ES256 signature, reads the claims, and makes an access decision. No blockchain infrastructure. No Insumer SDK. No network call to InsumerAPI at request time.

The JWKS endpoint is at https://insumermodel.com/.well-known/jwks.json (also available at GET /v1/jwks). The key ID is insumer-attest-v1. Any standard JWT library can verify the token: jose, jsonwebtoken, PyJWT, go-jose, or any JOSE-compliant implementation.

This means a single attestation call produces a credential that can be verified by an unlimited number of downstream services. The JWT is self-contained proof of wallet state at a specific block height, valid for 30 minutes.

Gateway compatible

Wallet Auth JWTs are standard ES256 JWTs backed by a JWKS endpoint. They work with any system that accepts JWKS-backed JWTs:

        - Kong
        - Nginx (ngx_http_auth_jwt module)
        - Cloudflare Access
        - AWS API Gateway
        - Azure API Management
        - Traefik
        - Envoy
        - Any OAuth 2.0 middleware
Enter fullscreen mode Exit fullscreen mode

Point your gateway's JWKS URL at https://insumermodel.com/.well-known/jwks.json. Configure it to require alg: ES256 and validate iss: https://api.insumermodel.com. That is the entire blockchain integration.

Verification with insumer-verify

The insumer-verify npm package (v1.3.0) auto-detects the input format. Pass either the full response object or the JWT string directly:

import { verifyAttestation } from "insumer-verify";

// response = await res.json() — the full API envelope
// Pass the JWT string directly from response.data.jwt
const result = await verifyAttestation(response.data.jwt, {
  jwksUrl: "https://insumermodel.com/.well-known/jwks.json"
});

console.log(result.valid);   // true
console.log(result.payload); // the verified attestation data
Enter fullscreen mode Exit fullscreen mode

The package runs signature verification, expiry checks, and condition hash validation. Zero dependencies. Works in Node.js 18+ and browsers.

What it costs

Nothing extra. A Wallet Auth attestation costs the same 1 credit ($0.04) as a standard attestation. The format: "jwt" parameter adds the JWT to the response alongside the existing sig field. Both are always available. Merkle proof attestations with JWT cost 2 credits ($0.08), same as without.

Where to start

Get a free API key at insumermodel.com/developers. Add "format": "jwt" to any attestation request. Read the full Wallet Auth documentation for code examples in JavaScript, Python, and curl.

Wallet Auth is available in all four InsumerAPI SDKs: MCP server (v1.7.5), LangChain (v0.9.13), ElizaOS (v1.0.4), and the OpenAI GPT.

A note on error handling: If the API cannot reach one or more upstream data sources after retries, the attestation request returns HTTP 503 with error.code: "rpc_failure". No JWT is issued, no signature is returned, and no credits are charged. This is a retryable error — wait 2–5 seconds and retry. Do not treat rpc_failure as pass: false; it means the API refused to sign an unverified result.

    Share this article

        [

            Share on X
        ](#)
        [

            LinkedIn
        ](#)
        [

            Reddit
        ](#)


            Discord



            Copy Link
Enter fullscreen mode Exit fullscreen mode

InsumerAPI is free to start. Get an API key and try it. View API Docs

Top comments (0)