DEV Community

Cover image for Verify Token Holdings Across 31 Blockchains with One API Call
Douglas Borthwick
Douglas Borthwick

Posted on

Verify Token Holdings Across 31 Blockchains with One API Call

You need to know if a wallet holds at least 100 UNI on Ethereum. Or if it owns a specific NFT on Base. Or if it has USDC on Polygon.

The usual approach: spin up an RPC node (or pay for one), write ERC-20 balanceOf calls, handle each chain's quirks, deal with decimals, and pray the node doesn't rate-limit you on a Saturday night.

There's a simpler way. The InsumerAPI lets you verify token balances and NFT ownership across 31 blockchains with a single POST request. You get back a signed true/false. No actual balances are exposed. One credit per verification, and you get 10 free credits to start.

Let me show you how it works.

Get a Free API Key (30 seconds)

No approval process. No credit card. Just POST your email:

curl -X POST https://us-central1-insumer-merchant.cloudfunctions.net/createDeveloperApiKey \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "appName": "My App", "tier": "free"}'
Enter fullscreen mode Exit fullscreen mode

You get back an API key that starts with insr_live_. The free tier gives you 10 verification credits and 100 read requests per day. That's enough to build and test your integration.

Example 1: Boolean Attestation with curl

Let's check whether a wallet holds at least 100 UNI on Ethereum. UNI's contract address is 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984, and it uses 18 decimals.

curl -X POST https://us-central1-insumer-merchant.cloudfunctions.net/insumerApi/v1/attest \
  -H "Content-Type: application/json" \
  -H "X-API-Key: insr_live_YOUR_KEY_HERE" \
  -d '{
    "wallet": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "conditions": [{
      "type": "token_balance",
      "contractAddress": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
      "chainId": 1,
      "threshold": 100,
      "decimals": 18,
      "label": "UNI >= 100"
    }]
  }'
Enter fullscreen mode Exit fullscreen mode

The response:

{
  "ok": true,
  "data": {
    "attestation": {
      "id": "ATST-A7C3E",
      "pass": true,
      "results": [
        {
          "condition": 0,
          "label": "UNI >= 100",
          "type": "token_balance",
          "chainId": 1,
          "met": true
        }
      ],
      "passCount": 1,
      "failCount": 0,
      "attestedAt": "2026-02-24T15:30:00.000Z",
      "expiresAt": "2026-02-24T16:00:00.000Z"
    },
    "sig": "MEYCIQDx...base64..."
  },
  "meta": {
    "creditsRemaining": 9,
    "version": "1.0",
    "timestamp": "2026-02-24T15:30:00.000Z"
  }
}
Enter fullscreen mode Exit fullscreen mode

A few things to notice:

  • pass is the top-level boolean. true means all conditions were met.
  • results gives you the per-condition breakdown.
  • sig is an ECDSA P-256/SHA-256 signature over the attestation data. You can verify it client-side if you need cryptographic proof.
  • The actual token balance is never revealed. You asked "at least 100?" and got back "yes."

Multi-condition checks

You can pass up to 10 conditions in a single call. Mix token balances and NFT ownership across different chains:

curl -X POST https://us-central1-insumer-merchant.cloudfunctions.net/insumerApi/v1/attest \
  -H "Content-Type: application/json" \
  -H "X-API-Key: insr_live_YOUR_KEY_HERE" \
  -d '{
    "wallet": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "conditions": [
      {
        "type": "token_balance",
        "contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "chainId": 1,
        "threshold": 1000,
        "decimals": 6,
        "label": "USDC >= 1000 on Ethereum"
      },
      {
        "type": "nft_ownership",
        "contractAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
        "chainId": 1,
        "label": "Bored Ape holder"
      },
      {
        "type": "token_balance",
        "contractAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "chainId": 8453,
        "threshold": 500,
        "decimals": 6,
        "label": "USDC >= 500 on Base"
      }
    ]
  }'
Enter fullscreen mode Exit fullscreen mode

pass is only true when all conditions are met. Each condition's met field tells you which ones passed individually.

Example 2: Python with langchain-insumer

If you're building a LangChain agent, the langchain-insumer package wraps the API into 6 ready-made tools.

Install it:

pip install langchain-insumer
Enter fullscreen mode Exit fullscreen mode

Verify a token balance in a few lines:

from langchain_insumer import InsumerAPIWrapper, InsumerAttestTool

api = InsumerAPIWrapper(api_key="insr_live_YOUR_KEY_HERE")

result = api.attest(
    wallet="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    conditions=[{
        "type": "token_balance",
        "contractAddress": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
        "chainId": 1,
        "threshold": 100,
        "decimals": 18,
        "label": "UNI >= 100"
    }]
)

print(result["data"]["attestation"]["pass"])  # True or False
Enter fullscreen mode Exit fullscreen mode

To give a LangChain agent the ability to verify tokens on its own:

from langchain_insumer import InsumerAPIWrapper, InsumerAttestTool

api = InsumerAPIWrapper(api_key="insr_live_YOUR_KEY_HERE")
tools = [InsumerAttestTool(api_wrapper=api)]

# Pass `tools` to your agent. The agent can now verify
# token balances and NFT ownership autonomously.
Enter fullscreen mode Exit fullscreen mode

The full toolkit includes InsumerAttestTool, InsumerVerifyTool, InsumerListMerchantsTool, InsumerListTokensTool, InsumerCheckDiscountTool, and InsumerCreditsTool. Your agent can discover merchants, check discounts, and create signed verification codes without any human involvement.

Example 3: MCP Server with Claude Desktop

If you use Claude Desktop, Cursor, or Windsurf, you can add on-chain verification as an MCP tool. No code required beyond the config file.

Add this to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "insumer": {
      "command": "npx",
      "args": ["-y", "mcp-server-insumer"],
      "env": {
        "INSUMER_API_KEY": "insr_live_YOUR_KEY_HERE"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Restart Claude Desktop. You now have 16 tools available covering every API endpoint. You can ask Claude things like:

"Does wallet 0xd8dA... hold at least 1000 USDC on Ethereum?"

"List all merchants that accept UNI tokens."

"Check what discount 0xd8dA... qualifies for at merchant acme-coffee."

Claude calls the appropriate tools automatically and gives you the results in plain language.

The MCP server is published on npm: mcp-server-insumer.

What Can You Build With This?

Token-gated discounts

A merchant accepts UNI holders. Customers who hold 1,000+ UNI get 15% off. The flow:

  1. Customer connects wallet on the merchant's site.
  2. Your backend calls POST /v1/attest with a token_balance condition.
  3. If pass is true, apply the discount.
  4. The customer's actual balance is never stored in your database.

The API also has a higher-level GET /v1/discount/check endpoint that calculates the discount directly based on a merchant's configured tiers. That call is free and doesn't consume credits.

On-chain credential verification

Need to confirm someone holds a specific credential NFT? Maybe it's a KYC attestation NFT, a professional certification, or a membership badge issued on-chain.

curl -X POST .../insumerApi/v1/attest \
  -H "X-API-Key: insr_live_..." \
  -d '{
    "wallet": "0x...",
    "conditions": [{
      "type": "nft_ownership",
      "contractAddress": "0x_CREDENTIAL_NFT_CONTRACT",
      "chainId": 8453,
      "label": "KYC attestation NFT"
    }]
  }'
Enter fullscreen mode Exit fullscreen mode

Boolean result, signed response. No need to parse NFT metadata or enumerate token IDs.

DAO governance eligibility

Before allowing a wallet to submit a governance proposal, verify it meets the token threshold:

from langchain_insumer import InsumerAPIWrapper

api = InsumerAPIWrapper(api_key="insr_live_YOUR_KEY_HERE")

result = api.attest(
    wallet=proposer_address,
    conditions=[{
        "type": "token_balance",
        "contractAddress": governance_token_address,
        "chainId": 1,
        "threshold": 10000,
        "decimals": 18,
        "label": "Governance token >= 10,000"
    }]
)

if result["data"]["attestation"]["pass"]:
    allow_proposal()
else:
    reject_proposal()
Enter fullscreen mode Exit fullscreen mode

AI agent commerce

This is where things get interesting. An AI agent can autonomously:

  1. Discover merchants via GET /v1/merchants
  2. Check a user's discount eligibility via GET /v1/discount/check
  3. Create a signed discount code via POST /v1/verify
  4. Confirm USDC payment via POST /v1/payment/confirm

The full merchant lifecycle is also available through the API. An agent can create a merchant account, configure token tiers, verify domain ownership, and publish to the directory. No human approval needed.

Supported Chains

The API covers 31 chains. Here are some of the more common ones:

Chain Chain ID Notes
Ethereum 1
Base 8453
Polygon 137
Arbitrum 42161
Optimism 10
BNB Chain 56 USDC uses 18 decimals here
Avalanche 43114
Solana "solana" String, not integer
zkSync Era 324
Scroll 534352
Linea 59144
Blast 81457
Berachain 80094

Plus Chiliz, Soneium, Plume, Sonic, Gnosis, Mantle, Taiko, Ronin, Celo, Moonbeam, Moonriver, Viction, opBNB, World Chain, Unichain, Ink, Sei, and ApeChain. Full list in the OpenAPI spec.

Note that Solana uses the string "solana" as the chain ID, not an integer. Pass the wallet address in the solanaWallet field instead of wallet.

Pricing

Tier Daily Reads Verification Credits Price
Free 100/day 10 (one-time) $0
Pro 10,000/day 100 (one-time) $29/mo
Enterprise 100,000/day 500 (one-time) $99/mo

Each verification costs 1 credit ($0.04). Read-only calls like listing merchants or checking discounts use the daily read limit and don't cost credits. You can buy more credits anytime with USDC at 25 credits per 1 USDC.

Resources

Everything you need to get started:

The free tier key takes 30 seconds to get and gives you enough credits to build a proof of concept. If you have questions, reach out at contact@insumermodel.com.

Top comments (0)