API Reference

The 32 core endpoints. Authentication, response format, rate limits, and every parameter documented. The full surface (46 operations across 42 paths, including key lifecycle and billing) is in the OpenAPI spec.

Building this in Claude Code? Install the wallet auth skill for guided integration: git clone https://github.com/insumerapi/insumer-skill.git ~/.claude/skills/insumer

Postman Collection OpenAPI Spec

See how the core endpoints connect → API Topology

Authentication

Two methods. Use either one per request, not both.

API Key

Send an X-API-Key header. Keys use the format insr_live_ followed by 40 hex characters. Get a free key at /developers/quickstart/. Public endpoints (no key needed): JWKS, compliance templates, code validation, merchant directory, token registry, and discount check.

Wallet Auth

Alternative to X-API-Key on five endpoints: POST /v1/attest, POST /v1/trust, POST /v1/trust/batch, GET /v1/credits, and POST /v1/credits/buy. For agents whose key was purchased via POST /v1/keys/buy. Send Authorization: Wallet <base64(JSON({message, signature}))>, where message is a SIWE string with domain api.insumermodel.com and signature is an EIP-191 personal_sign. The signing wallet must be the wallet that bought the key and must hold the Insumer Access pass on Base. Single-use nonce; Issued At must be within the last 5 minutes. Other endpoints return 501 for this scheme. Wallet auth authenticates the caller only: every wallet evaluated by an attest or trust call comes from the request body, is independent of the signer, and is not required to match it. To bind a verdict to the presenting wallet, verify that wallet's own signature first, then attest the recovered address. Drop-in middleware: @skyemeta/access on npm.

Base URL

https://api.insumermodel.com

All endpoints are relative to this base URL.

Rate Limits

PlanVerification CreditsRequests / DayPrice
Free10 (one-time)100$0
Pro1,000/mo10,000$29/mo
Enterprise5,000/mo100,000$99/mo

Reads (GET requests) use the daily limit and are free. Credits live on the API key and are consumed by attest, trust, and batch trust endpoints. A store has no balance of its own: a discount code (verify, ACP, UCP) or NFC tap that carries a discount uses one credit from the API key that owns the store, and a 0% result is free; every in-store scan uses one credit from that key. A caller using another key is not charged; if you call with the owner key, your key pays. See full pricing, per-call costs, and volume discounts →

Response Format

Success
{
  "ok": true,
  "data": { /* endpoint-specific */ },
  "meta": {
    "version": "1.0",
    "timestamp": "2026-02-27T12:00:00Z"
  }
}
Error
{
  "ok": false,
  "error": {
    "code": 401,
    "message": "Invalid or missing API key."
  },
  "meta": {
    "version": "1.0",
    "timestamp": "2026-02-27T12:00:00Z"
  }
}
402: Out of credits (NOT the x402 quote)
{
  "ok": false,
  "error": {
    "code": 402,
    "message": "Insufficient credits (0 available, 3 required). Buy more via POST /v1/credits/buy."
  }
}
# Two different 402s exist on /v1/attest, /v1/trust and /v1/trust/batch.
# THIS one means a valid key ran dry: top up at POST /v1/credits/buy.
# The other is the x402 pay-per-call quote, returned when a request arrives
# with NO credential headers at all, and it carries an accepts[] array.
# Branch on the presence of accepts[], not on the status code.
429: Daily limit reached
{
  "ok": false,
  "error": {
    "code": 429,
    "message": "Daily rate limit exceeded. Resets in 42 minutes."
  }
}
# The free tier allows 100 requests a day. Credits and the daily limit are
# separate ceilings: you can hold credits and still be rate limited.
503: Data source unavailable (retryable)
{
  "ok": false,
  "error": {
    "code": "rpc_failure",
    "message": "Unable to verify all conditions — data source unavailable after retries",
    "failedConditions": [
      { "source": "balance_read", "chainId": 1, "message": "data source unreachable" }
    ]
  },
  "meta": { "version": "1.0", "timestamp": "..." }
}

Returned when an upstream data source is unavailable after retries. No attestation signed, no JWT, no credits charged. Retry after 2–5 seconds. Applies to: /v1/attest, /v1/trust, /v1/verify, /v1/acp/discount, /v1/ucp/discount, /v1/discount/check. /v1/trust/batch returns 200 instead, with an error entry in the results array for any wallet whose reads failed.

Endpoint Index

MethodEndpointDescription
Verification
POST/v1/attestBoolean attestation across 37 chains
GET/v1/jwksJWKS public key for signature verification
GET/v1/compliance/templatesList available compliance templates
Trust
POST/v1/trustWallet trust profile (155–176 checks)
POST/v1/trust/batchBatch trust profiles (up to 10)
Commerce
POST/v1/acp/discountGenerate ACP-format discount
POST/v1/ucp/discountGenerate UCP-format discount
GET/v1/codes/{code}Validate discount code (public)
POST/v1/verifyVerify wallet and get discount
POST/v1/payment/confirmConfirm code redemption
GET/v1/discount/checkCheck discount eligibility
Merchants
GET/v1/merchantsList published merchants
GET/v1/merchants/{id}Get merchant details
GET/v1/tokensList supported tokens
Onboarding
POST/v1/merchantsCreate merchant programmatically
POST/v1/merchants/{id}/domain-verificationRequest domain verification token
PUT/v1/merchants/{id}/domain-verificationTrigger domain verification check
PUT/v1/merchants/{id}/verificationPartner asserts domain (partner keys only)
PUT/v1/merchants/{id}/tokensUpdate accepted tokens
PUT/v1/merchants/{id}/nftsUpdate accepted NFTs
PUT/v1/merchants/{id}/settingsUpdate merchant settings
POST/v1/merchants/{id}/creditsBuy credits for the owner key (compatibility)
POST/v1/merchants/{id}/directoryPublish to / unpublish from directory
GET/v1/merchants/{id}/statusGet merchant setup status
POST/v1/registry/submitSubmit a token/NFT to the registry (pending)
White-Label Scanner
POST/v1/merchants/{id}/scannersAdd or remove a scanner PIN
GET/v1/merchants/{id}/scannersList a merchant's scanners
POST/v1/scanner/sessionValidate a scanner PIN, return config
POST/v1/pass/verifyVerify a scanned pass, return discount
Account
POST/v1/keys/buyBuy API key with USDC, USDT, or BTC (no auth)
GET/v1/creditsCheck credit balance
POST/v1/credits/buyBuy credits with USDC, USDT, or BTC

Verification

POST /v1/attest

Boolean attestation. Checks token balances, NFT ownership, EAS attestations, Farcaster identity, arbitrary boolean view calls, dimensionless ratio rules, account code, and agent standing across 37 chains. Returns ECDSA P-256 signed result with a post-quantum signature (pqSig/pqKid). Up to 10 conditions per request. Full docs →

ParameterTypeDescription
walletstring required*EVM wallet address (0x + 40 hex). Required unless a non-EVM wallet field is provided
solanaWalletstring optionalSolana wallet address (raw base58; .sol domain resolution not supported). Required if any condition uses chainId "solana"
xrplWalletstring optionalXRPL wallet address (r-address). Required if any condition uses chainId "xrpl"
bitcoinWalletstring optionalBitcoin address (P2PKH, P2SH, bech32, or Taproot). Required if any condition uses chainId "bitcoin"
tronWalletstring optionalTron wallet address (T-prefixed, base58, 34 chars). Required if any condition uses chainId "tron". Supports native TRX and TRC-20 tokens (e.g. USDT-TRC20)
stellarWalletstring optionalStellar wallet address (G-prefixed StrKey, 56 chars). Required if any condition uses chainId "stellar". Supports native XLM and classic trustline assets (USDC, BENJI). Soroban contract balances not visible
suiWalletstring optionalSui wallet address (0x + 64 hex chars). Required if any condition uses chainId "sui". Supports native SUI and Sui-native tokens (e.g. USDC)
conditionsarray requiredArray of condition objects (max 10). Each has: type, contractAddress, chainId, threshold, decimals (plus assetCode for Stellar trustlines, currency for XRPL trustlines, multiple/amount for ratio_to_amount, minFraction for ratio_to_supply). decimals is optional: the token's own decimals are always read from the chain and are the scale, and a value you send is a cross-check (a value that differs from the token's own is a 400 that names the token's own value; a value that is not an integer from 0 to 100 is a 400). On Sui, contractAddress must be a coin type (address::module::Name); anything else is a 400. Types: token_balance, nft_ownership, eas_attestation, farcaster_id, evm_view_call (arbitrary bool-returning view function, requires selector in the form "functionName(address)", EVM chains only), ratio_to_amount (balance ≥ multiple × amount, EVM chains only), ratio_to_supply (balance / totalSupply ≥ minFraction, EVM chains and ERC-20 tokens only), erc8004_agent (ERC-8004 agent registration; requires agentId as a uint256 decimal string; Base only), erc7710_delegation (ERC-7710 delegation validity; requires delegationManager, expectedDelegator, and the signed delegation object; Base only; max 3 per request; attestations containing one expire in 5 minutes). Both agent types are generally available on any API key, and reachable with no key at all via x402 pay-per-call ($0.05 standard rate). erc8004_agent does not support Merkle proofs; erc7710_delegation does. With proof: "merkle" it returns an EIP-1186 revocation proof (subject: "delegation_revocation") on DelegationManagers whose storage layout has been verified on-chain. account_code (the code state of the wallet address itself at the anchored block; requires expect: "none" for a plain key account, "eip7702" for the EIP-7702 delegation designator, or "contract" for any other code, the three exclusive on a chain; optional delegate with "eip7702" only, an EVM address the designator must point at, a 400 with any other expect; any EVM chain, a non-EVM chainId is a 400; the result is the boolean met, the code and the delegation target are never returned; 1 credit, x402 at the standard rate; with proof: "merkle" an account proof whose codeHash is the proven value, subject: "account_code"). Full docs → chainId accepts EVM integers (Ethereum=1, Base=8453, XDC=50, Robinhood Chain=4663, Arc=5042, etc.) or strings "solana", "xrpl", "bitcoin", "tron", "stellar", "sui". On v2 keys (every newly created key), threshold and the ratio fields multiple / amount / minFraction are decimal strings (e.g. "100", "0.005"), not JSON numbers, and a number returns 400. v1 keys accept either; a string is valid on both. All of these are token/display units, not base units or wei: "100" means 100 whole USDC and "0.001" means 0.001 ETH. Decimals are auto-detected, so a base-unit value is not rejected: it is a valid request for a much larger amount and returns met: false
proofstring optionalSet to "merkle" for EIP-1186 proofs. 2 credits instead of 1, refunded whenever no proof is delivered. Storage proofs on 27 of 31 EVM chains; contractAddress "native" returns an account proof (subject "account_balance"), and an account_code condition returns an account proof with codeHash as the proven value (subject "account_code")
formatstring optionalSet to "jwt" to include a Wallet Auth by InsumerAPI token (ES256-signed JWT), verifiable by any standard JWT library using JWKS. The jwt is unchanged by the post-quantum signature, and a pqJwt is returned beside it: a compact JWS with alg: "ML-DSA-65", signed under the post-quantum key. A verifier that checks the post-quantum signature binds it to the jwt by the whole claim set, comparing parsed JSON and never bytes, and reports any difference as refuted (see specification Section 12, Check 6). No additional cost
declaredLimitsstring optionalDefault "include". Set to "omit" to leave the decoded caveat limits out of erc7710_delegation results, which then carry declaredLimitsOmitted: true. Use it when the attestation will be forwarded to third parties and the principal's spending ceiling should not travel with it. met, delegationHash and conditionHash are byte-identical either way. No additional cost
GET /v1/jwks

Returns the JWKS (JSON Web Key Set) containing the ECDSA P-256 public key used to sign attestation and trust responses and the ML-DSA-65 post-quantum key as RFC 9964 AKP entries appended after the EC entries. 24-hour cache. Also available as a static file at /.well-known/jwks.json.

No parameters. Returns { keys: [{ kty: "EC", crv, x, y, kid, alg, use }, ..., { kty: "AKP", alg: "ML-DSA-65", pub, kid, use }] }

Responses sign under one of three key IDs over the same P-256 key: insumer-attest-v1 (legacy keys), insumer-attest-v2 (new keys, domain-separated), and insumer-trust-v2 (trust profiles). Select the key by the kid on the response; never hardcode one. The two AKP entries that follow, insumer-attest-pq1 and insumer-trust-pq1, hold the ML-DSA-65 key for the post-quantum signature (pqSig/pqKid); resolve them by the pqKid on the response. See the signing spec.

GET /v1/compliance/templates

Lists all available compliance templates with their condition configurations. Full docs →

No parameters. Returns data.templates, keyed by name, each with provider, description, chainId and chainName: coinbase_verified_account, coinbase_verified_country, coinbase_one (Base), gitcoin_passport_score, gitcoin_passport_active (Optimism).

Trust

POST /v1/trust

Generates an ECDSA-signed wallet trust profile with curated presence checks across up to 14 dimensions: stablecoins (52), governance (8), nfts (3), staking (5), institutional_stablecoins (8), tokenized_treasuries (16), stablecoin_deposits (39), wrapped_bitcoin (12), names (2), account (10: contract code and EIP-7702 delegation present, on Ethereum, Base, Arbitrum, Optimism and Polygon), 155 base checks across 27 chains, plus optional solana (14), xrpl (3), bitcoin (1) and tron (3) dimensions. Up to 176 checks across 29 chains. Dimensions come back in a fixed order, the same for every wallet. conditionSetVersion is "2026-10-08" on every key version and names the check list that was run. 3 credits per call. Full docs →

ParameterTypeDescription
walletstring requiredEVM wallet address (0x + 40 hex)
solanaWalletstring optionalSolana wallet address. Adds the 14-check solana dimension (USDC, OUSD, PYUSD, USDG, USD1, USDS, EURC, BUIDL, USDY, cbBTC, WBTC, tBTC, jitoSOL, mSOL) and evaluates the Solana institutional_stablecoins checks
xrplWalletstring optionalXRPL wallet address (r-address). Adds the xrpl dimension (RLUSD, USDC, OUSG) and evaluates EURCV on XRPL
bitcoinWalletstring optionalBitcoin address. Adds the bitcoin dimension (native BTC presence check)
tronWalletstring optionalTron T-address. Adds the tron dimension (USDT, USD1, WBTC)
stellarWalletstring optionalStellar G-address. Evaluates the institutional_stablecoins checks for USDC and BENJI on Stellar (classic trustlines)
suiWalletstring optionalSui 0x + 64 hex address. Evaluates USDC on Sui (institutional_stablecoins) and USDY on Sui (tokenized_treasuries)
proofstring optionalSet to "merkle" for storage proofs. EVM token rows carry a storage proof when the token's balance slot can be discovered; rows whose balance is computed rather than stored (Aave aTokens, BUIDL) and tokens with non-standard storage layouts are declined with a stated reason; NFT, non-EVM and account rows are declined (account rows with a reason pointing at /v1/attest); a check that was not evaluated carries no proof key at all; the premium is refunded whenever no proof is delivered. 6 credits instead of 3
POST /v1/trust/batch

Batch trust profiles for up to 10 wallets in a single request, each profile signed separately. 3 credits per wallet. Partial success supported.

ParameterTypeDescription
walletsarray requiredArray of objects (max 10). Each has: wallet (required), and optional solanaWallet, xrplWallet, bitcoinWallet, tronWallet, stellarWallet, suiWallet
proofstring optionalSet to "merkle" for storage proofs. 6 credits per wallet

Commerce

POST /v1/acp/discount

Check wallet state against the store's conditions and generate a discount code in OpenAI/Stripe ACP format. Cost, errors and the hourly limit are the same as /v1/verify. Full docs →

ParameterTypeDescription
merchantIdstring requiredMerchant ID from the registry
walletstring required*EVM wallet address (0x...)
solanaWalletstring optionalSolana wallet address
xrplWalletstring optionalXRPL wallet address (r-address). The checksum is verified; an address that fails it returns 400
walletProofobject optionalProof that the caller controls wallet: { message, signature }, an EIP-4361 message signed by that EVM wallet, with domain api.insumermodel.com or the store’s own website, URI https://api.insumermodel.com/v1/merchants/{merchantId}, Issued At within the last 5 minutes and an unused nonce. A store can give unproven wallets a lower discount or a daily limit; a proven wallet gets the full discount. A proof that fails is refused (401, or 400 when it is not a { message, signature } object) and uses no credit. Send it with wallet only
itemsarray optionalCart items with path and amount (minor units). Supply items or subtotal to receive an applied discount
subtotalnumber optionalOrder-level base in minor units (a fraction is truncated), for callers that do not send line items. Ignored when items is supplied
POST /v1/ucp/discount

Check wallet state against the store's conditions and generate a discount code in Google UCP format. Cost, errors and the hourly limit are the same as /v1/verify.

ParameterTypeDescription
merchantIdstring requiredMerchant ID from the registry
walletstring required*EVM wallet address (0x...)
solanaWalletstring optionalSolana wallet address
xrplWalletstring optionalXRPL wallet address (r-address). The checksum is verified; an address that fails it returns 400
walletProofobject optionalProof that the caller controls wallet: { message, signature }, an EIP-4361 message signed by that EVM wallet, with domain api.insumermodel.com or the store’s own website, URI https://api.insumermodel.com/v1/merchants/{merchantId}, Issued At within the last 5 minutes and an unused nonce. A store can give unproven wallets a lower discount or a daily limit; a proven wallet gets the full discount. A proof that fails is refused (401, or 400 when it is not a { message, signature } object) and uses no credit. Send it with wallet only
itemsarray optionalCart items with path and amount (minor units). Supply items or subtotal to receive an applied discount
subtotalnumber optionalOrder-level base in minor units (a fraction is truncated), for callers that do not send line items. Ignored when items is supplied
GET /v1/codes/{code}

Validate a discount code. Public endpoint, no API key required. Returns code status, merchant, discount percentage, and expiry.

ParameterTypeDescription
codestring requiredPath parameter. The discount code to validate

Invalid codes return reason: "not_found" | "expired" | "already_used"

POST /v1/verify

Verify wallet token/NFT holdings against a merchant's configured requirements and return a discount code if eligible. A code that carries a discount costs one credit from the API key that owns the store; a 0% result is free, and a caller using another key is not charged. 402 when the owner key has no credits left (only for a code that carries a discount); 403 when the store has no active owner API key; Paid discount codes requested with a key other than the store's owner are subject to an hourly limit (429; the message says when to try again). The result is signed first; the credit is taken and the code is stored together after that, and a coupon is created only once the code exists. A result that cannot be signed, or a code that cannot be stored, answers 503 in the standard error envelope with no credit used and no code created. A read that does not complete answers 503 rpc_failure. Both are safe to retry.

ParameterTypeDescription
merchantIdstring requiredMerchant ID from the registry
walletstring required*EVM wallet address (0x...)
solanaWalletstring optionalSolana wallet address
xrplWalletstring optionalXRPL wallet address (r-address). The checksum is verified; an address that fails it returns 400
walletProofobject optionalProof that the caller controls wallet: { message, signature }, an EIP-4361 message signed by that EVM wallet, with domain api.insumermodel.com or the store’s own website, URI https://api.insumermodel.com/v1/merchants/{merchantId}, Issued At within the last 5 minutes and an unused nonce. A store can give unproven wallets a lower discount or a daily limit; a proven wallet gets the full discount. A proof that fails is refused (401, or 400 when it is not a { message, signature } object) and uses no credit. Send it with wallet only
POST /v1/payment/confirm

Verify an on-chain USDC payment and mark a discount code as used. Confirms the transaction on-chain before accepting.

ParameterTypeDescription
codestring requiredThe discount code to confirm (INSR-XXXXX)
txHashstring requiredOn-chain USDC transaction hash
chainIdnumber|"solana" requiredChain ID of the payment (e.g. 1, 8453, "solana")
amountnumber|string requiredUSDC amount paid
GET /v1/discount/check

Check if a wallet is eligible for a discount at a specific merchant without generating a code. Answers 503 rpc_failure when a read does not complete: nothing is concluded about the wallet, so retry. A frozen XRPL trust line earns no tier.

ParameterTypeDescription
merchantstring requiredQuery parameter. Merchant ID
walletstring optionalQuery parameter. EVM wallet address
solanaWalletstring optionalQuery parameter. Solana wallet address
xrplWalletstring optionalQuery parameter. XRPL wallet address (r-address). The checksum is verified; an address that fails it returns 400

Merchants

GET /v1/merchants

List all published merchants in the directory. Returns merchant name, ID, location, accepted tokens, and discount tiers.

ParameterTypeDescription
tokenstring queryFilter by token symbol
verifiedstring queryFilter by domain verification status ("true" or "false")
limitinteger queryResults per page (default 50, max 200)
offsetinteger queryPagination offset
GET /v1/merchants/{id}

Get full details for a specific merchant including accepted tokens, NFTs, discount configuration, and business info.

ParameterTypeDescription
idstring requiredPath parameter. Merchant document ID
GET /v1/tokens

List all tokens supported across the platform with contract addresses, chain IDs, decimals, and logos.

ParameterTypeDescription
chaininteger|string queryFilter by chain ID
symbolstring queryFilter by token symbol
typestring queryFilter by "token" or "nft"

Onboarding

POST /v1/merchants

Create a new merchant programmatically. The API key that creates it owns it and pays one credit for each code or tap at the store that carries a discount (a 0% result is free) and for every in-store scan; the store has no balance of its own. A key can create a limited number of merchants (429 past it). Full docs →

ParameterTypeDescription
companyNamestring requiredDisplay name (max 100 chars)
companyIdstring requiredUnique ID. Alphanumeric, dash, underscore (2-50 chars)
locationstring optionalCity or region (max 200 chars)
POST /v1/merchants/{id}/domain-verification

Generate a verification token for proving domain ownership. Supports DNS TXT record, HTML meta tag, or verification file. Each POST regenerates the token.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
domainstring requiredDomain to verify (e.g. example.com). No protocol prefix.
PUT /v1/merchants/{id}/domain-verification

Check all three verification methods (DNS TXT, meta tag, file) for the previously requested domain. Rate limited per merchant (429 says when to retry).

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
PUT /v1/merchants/{id}/tokens

Configure which tokens the merchant accepts and the minimum balance required for discounts.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
ownTokenobject|null optionalMerchant's own token config (symbol, chainId, contractAddress, decimals, tiers; currency for an XRPL trust line token). Send null or {"enabled": false} to switch it off; any other non-boolean enabled returns 400. A tier discount is a whole number from 1 to 50: a value with a fraction returns 400. A Solana mint, an XRPL issuer address and an XRPL currency code are validated, and a value that fails returns 400. decimals is required but not used when a discount is evaluated
partnerTokensarray optionalArray of partner token configs, same structure as ownToken
PUT /v1/merchants/{id}/nfts

Configure which NFT collections the merchant accepts for discounts.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
nftCollectionsarray requiredArray of NFT objects with contractAddress, chainId, name, discount. Max 4. discount is a whole number from 1 to 50: a value with a fraction returns 400. A Solana mint, an XRPL issuer address and an XRPL taxon (integer 0 to 4294967295) are validated, and a value that fails returns 400
PUT /v1/merchants/{id}/settings

Update discount stacking mode, cap, the store’s terms for wallets sent without a walletProof, and USDC payment settings. All fields optional.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
discountModestring optional"highest" (best single discount), "stack" (sum all) or "capped" (sum all, then cap at discountCap)
discountCapinteger optionalMaximum total discount percentage, a whole number from 1 to 100. A value with a fraction returns 400
maxDiscountsPerWalletPerDayinteger|null optionalThe store’s limit on discount codes per UTC day for a wallet sent without a walletProof, a whole number from 1 to 100; null removes it. Past the limit, /v1/verify, /v1/acp/discount and /v1/ucp/discount return 429 with no credit used
maxUnprovenDiscountinteger|null optionalThe most a wallet sent without a walletProof can get, a whole number from 0 to 100 (0 = no discount); null gives it the same discount as a proven wallet
usdcPaymentobject|null optionalUSDC payment config (enabled, evmAddress, solanaAddress, preferredChainId) or null to disable
pausedboolean optionaltrue pauses the store’s recognition, false resumes it. While paused, discount codes for the store are refused with 409 (“This store’s recognition is paused.”; no credit used, no code created), /v1/pass/verify answers recognized: false with paused: true, and the store is left out of GET /v1/merchants. Resuming restores everything
POST /v1/merchants/{id}/credits

Kept for compatibility. Buys credits with USDC, USDT or BTC into the regular balance of the API key that owns the merchant, the same balance that pays for the store's codes, scans and taps. Flat $0.04 per credit (25 credits per $1) at every purchase size. POST /v1/credits/buy is the normal way to top up and carries the volume tiers. See wallet addresses →

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
txHashstring requiredUSDC transfer transaction hash
chainIdinteger|string requiredChain where USDC was sent
amountnumber requiredUSDC amount sent (min 5, human-readable units)
updateWalletboolean optionalSet to true to change the registered sender wallet. Default false

Sender verification: The first purchase registers the sender wallet to the API key. Subsequent purchases must come from the same sender. To change the registered wallet, include "updateWallet": true; the verified transfer proves ownership.

POST /v1/merchants/{id}/directory

Publish (or refresh) the merchant's listing in the public directory. No request body needed to publish. Send { "listed": false } to unpublish (delist). Partner-provisioned merchants (created with an externalId) must pass domain verification before they can publish.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
listedboolean optionalSet false to unpublish. Omit to publish/refresh
GET /v1/merchants/{id}/status

Get the setup completion status for a merchant. Shows which steps are done: domain verified, tokens configured, published, etc.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
PUT /v1/merchants/{id}/verification

Record that a managing white-label partner verified an org's domain in its own branded flow, so the org can publish to the directory without seeing an Insumer-branded challenge. Sets verification.status=verified with method=partner. Restricted to designated white-label partner keys: self-serve keys get 403 and must use the domain-verification challenge flow above.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
domainstring requiredDomain the partner verified (no protocol prefix)
POST /v1/registry/submit

Submit a token or NFT collection to the public registry as pending for human approval. API key required (free: no credits charged). Idempotent per chain + address. A submission is held as pending until approved; some are added at once (the response says which: pending, active). Returns a flat envelope (no data wrapper).

ParameterTypeDescription
namestring requiredDisplay name
assetTypestring optional"token" or "nft". If omitted, inferred from standard, defaulting to "nft"
symbolstring required for tokensTicker symbol. A token submission without one returns 400
contractAddressstring required*EVM contract address (or mintAddress for Solana), or "native" for the chain's own asset
chainIdnumber or string requiredPositive integer for EVM, or "solana"
chainName, image, standard, website, descriptionstring optionalListing metadata
sourcestring optionalProvenance tag shown in the admin review queue

White-Label Scanner

Lets a partner run its own branded scanner against merchants it manages, with no dashboard account required. The partner builds only UI; InsumerAPI does all the cryptographic verification. There is deliberately no pass “sign” endpoint: signing is the InsumerAPI primitive and is never exposed as an API call. Scanners only verify passes that InsumerAPI itself issued.

POST /v1/merchants/{id}/scanners

Add a scanner PIN ({ name?, pin }, 4–8 digits; a merchant can hold a limited number of scanners) or remove one ({ remove: scannerId }). Owner key only. PINs are stored salted + hashed and never returned.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
pinstring optional*4–8 digits (to add a scanner)
namestring optionalScanner label (default “Register”)
removestring optional*Scanner id to remove
GET /v1/merchants/{id}/scanners

List a merchant's scanners (id and name only; PINs are never exposed). Owner key only.

ParameterTypeDescription
idstring requiredPath parameter. Merchant ID
POST /v1/scanner/session

Validate a scanner PIN and return the merchant config for a login-less branded scanner. Owner key only. Repeated failed PIN attempts are limited per merchant (429).

ParameterTypeDescription
merchantIdstring requiredMerchant ID
pinstring required4–8 digit scanner PIN
POST /v1/pass/verify

Verify a scanned pass and compute the discount. InsumerAPI verifies the ECDSA signature on the scanned QR, enforces 65-second freshness, then computes the discount against the merchant config. A bad signature is rejected with no discount. Metered on the partner key.

ParameterTypeDescription
merchantIdstring requiredMerchant ID
qrobject requiredThe scanned pass object including its sig (signed bytes are the object with sig removed)

Account

GET /v1/credits

Check your current credit balance and plan tier.

No parameters. Returns apiKeyCredits, tier, and dailyLimit.

POST /v1/keys/buy No auth required

Buy a new API key with USDC, USDT, or BTC. Agent-friendly: no email or prior authentication needed. The sender wallet from the transaction becomes the key's identity. See wallet addresses and volume discounts →

ParameterTypeDescription
txHashstring requiredTransfer transaction hash
chainIdinteger|string requiredChain where payment was sent. Supported: ETH (1), Base (8453), Polygon (137), Arbitrum (42161), Optimism (10), BNB (56), Avalanche (43114), Solana ("solana"), Bitcoin ("bitcoin"), Tron ("tron", USDT-TRC20)
amountnumber required for stablecoinsUSDC/USDT amount sent (min 5). Not required for BTC (USD value derived from on-chain amount at market rate)
appNamestring requiredName for the API key (e.g. your agent or app name, max 100 chars)
keyDeliverystring optionalCredential shape: "wallet" | "apiKey" | "both", default "wallet", case-insensitive. Default suppresses the API key string in the response when the Insumer Access pass mints to the sender wallet on EVM: the wallet + pass is the credential. Pass "apiKey" or "both" to receive a key string in addition

How it works: Send USDC, USDT, or BTC to the platform wallet on any supported chain, then call this endpoint with the transaction hash. The on-chain transfer is verified (BTC requires 1 confirmation), a new API key is created, and credits are added at volume-discount rates. USDC and USDT are accepted at face value; BTC is converted to USD at the market rate. One key per wallet. Use POST /v1/credits/buy to top up an existing key.

Response fields: On EVM purchases an Insumer Access pass (non-transferable ERC-721 on Base) is minted to the sender wallet; details are in the passMint block. The response also carries authMethod ("wallet" | "apiKey" | "both") indicating which credentials were delivered, and on the wallet path a human-readable authHint. The key field is conditionally present: omitted by default when the pass mints, returned when keyDelivery is "apiKey"/"both", and returned regardless on non-EVM purchases (Solana, BTC, Tron) or when the pass mint defers, so no buyer is left without a usable credential.

POST /v1/credits/buy

Purchase additional verification credits using USDC, USDT, or BTC on supported chains. See wallet addresses and volume discounts →

ParameterTypeDescription
txHashstring requiredTransfer transaction hash
chainIdinteger|string requiredChain where payment was sent. Supported: ETH (1), Base (8453), Polygon (137), Arbitrum (42161), Optimism (10), BNB (56), Avalanche (43114), Solana ("solana"), Bitcoin ("bitcoin"), Tron ("tron", USDT-TRC20)
amountnumber required for stablecoinsUSDC/USDT amount sent. Not required for BTC
updateWalletboolean optionalSet to true to change the registered sender wallet. Default false. Ignored for wallet-auth callers (see Sender verification below)

Auth: Accepts X-API-Key or Authorization: Wallet (SIWE envelope from a wallet that holds the Insumer Access pass). Wallet-auth callers let an SBT-holding agent top up without ever handling an API key. See Authentication →

Sender verification: The first purchase registers the sender wallet to the API key. Subsequent purchases must come from the same sender. To change the registered wallet, include "updateWallet": true; the verified transfer proves ownership. Wallet-auth callers: updateWallet is ignored. The SIWE signer is already bound to the registered wallet and the soulbound Insumer Access pass cannot follow a rotation, so honouring the rewrite would silently lock the caller out on the next sign-in. To rotate, use X-API-Key auth.

← Onboarding Back to Developers Hub →