DEV Community

Douglas Borthwick
Douglas Borthwick

Posted on

How to Build a Token-Gated Discount System in 20 Lines of Code

You have a storefront. Your most loyal customers hold your project's token. You want to give them a discount automatically. No coupon codes, no manual lists, no spreadsheet of wallet addresses.

Here is how to wire that up with a single API and about 20 lines of Express.js.

What we are building

A lightweight Express server that:

  1. Takes a customer's wallet address
  2. Checks whether they hold a specific token on any of 31 supported chains
  3. Returns the discount they qualify for

The API doing the heavy lifting is InsumerAPI. It handles the multi-chain lookup and returns a simple boolean: does this wallet meet the condition, yes or no? It never exposes raw balances to your server. Every response is signed with ECDSA P-256, so you can verify the result cryptographically.

Step 0: Grab a free API key

No credit card, no OAuth. One POST request:

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

Response:

{
  "success": true,
  "key": "insr_live_6cc334d80d...",
  "tier": "free",
  "dailyLimit": 100,
  "apiKeyCredits": 10
}
Enter fullscreen mode Exit fullscreen mode

Save the key. The free tier gives you 100 daily reads and 10 verification credits to start.

Step 1: Scaffold

mkdir token-discounts && cd token-discounts
npm init -y
npm install express
Enter fullscreen mode Exit fullscreen mode

Step 2: Build the server

Create server.js:

const express = require("express");
const app = express();
app.use(express.json());

const API = "https://us-central1-insumer-merchant.cloudfunctions.net/insumerApi";
const KEY = process.env.INSUMER_API_KEY;
const headers = { "Content-Type": "application/json", "X-API-Key": KEY };

app.post("/check-discount", async (req, res) => {
  const { wallet, merchantId } = req.body;

  // Check what discount this wallet qualifies for
  const discountRes = await fetch(
    `${API}/v1/discount/check?wallet=${wallet}&merchant=${merchantId}`,
    { headers }
  );
  const { data } = await discountRes.json();

  if (!data.eligible) {
    return res.json({ eligible: false, message: "No qualifying tokens found" });
  }

  res.json({
    eligible: true,
    totalDiscount: data.totalDiscount,
    merchant: data.merchantName,
    breakdown: data.breakdown.map((t) => ({
      token: t.symbol,
      tier: t.tier,
      discount: t.discount,
    })),
  });
});

app.listen(3000, () => console.log("Discount server running on :3000"));
Enter fullscreen mode Exit fullscreen mode

That is the whole thing. One API call, one response.

Step 3: Run it

INSUMER_API_KEY=insr_live_your_key_here node server.js
Enter fullscreen mode Exit fullscreen mode

Test with curl:

curl -X POST http://localhost:3000/check-discount \
  -H "Content-Type: application/json" \
  -d '{"wallet": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "merchantId": "BLUEMTN"}'
Enter fullscreen mode Exit fullscreen mode

If the wallet holds qualifying tokens:

{
  "eligible": true,
  "totalDiscount": 12,
  "merchant": "Blue Mountain Coffee",
  "breakdown": [
    { "token": "SHIB", "tier": "Gold", "discount": 8 },
    { "token": "NOTE", "tier": "Holder", "discount": 4 }
  ]
}
Enter fullscreen mode Exit fullscreen mode

If not:

{
  "eligible": false,
  "message": "No qualifying tokens found"
}
Enter fullscreen mode Exit fullscreen mode

Going deeper: verify specific conditions with /v1/attest

The discount check is merchant-specific. If you need custom verification logic (like "does this wallet hold at least 10,000 of token X on Arbitrum?"), use the /v1/attest endpoint directly:

const attestRes = await fetch(`${API}/v1/attest`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    wallet: "0xABC...123",
    conditions: [
      {
        type: "token_balance",
        contractAddress: "0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE",
        chainId: 1,
        threshold: 10000,
        label: "SHIB Gold",
      },
      {
        type: "nft_ownership",
        contractAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
        chainId: 1,
        label: "BAYC holder",
      },
    ],
  }),
});
const { data } = await attestRes.json();
// data.attestation.pass -> true if ALL conditions met
// data.attestation.results -> [{ label: "SHIB Gold", met: true }, { label: "BAYC holder", met: false }]
// data.sig -> ECDSA P-256 signature (base64, 88 chars)
Enter fullscreen mode Exit fullscreen mode

Up to 10 conditions per call, across any mix of the 31 supported chains. Each verification costs 1 credit ($0.04).

What is happening under the hood

The /v1/discount/check endpoint scans the customer's wallet across all chains where the merchant has configured tokens. It returns the tier and discount per token, but never raw balances. Your backend sees "SHIB, Gold tier, 8% off." It does not see "this wallet holds 847,293,019 SHIB." The financial data stays on-chain.

The /v1/attest endpoint is the lower-level primitive. It takes arbitrary conditions and returns booleans with an ECDSA signature. You can pass this signature to downstream systems (other APIs, smart contracts, audit logs) as cryptographic proof that the verification happened.

Both endpoints work across 31 blockchains: Ethereum, Base, Polygon, Arbitrum, Optimism, Avalanche, BNB Chain, Solana, and 23 more. You do not pass a chain preference for discount checks. The API checks everywhere the merchant has tokens configured.

If you prefer AI agent tooling

InsumerAPI also ships as:

  • MCP Server: npx -y mcp-server-insumer for Claude, Cursor, and any MCP-compatible client. 16 tools covering all endpoints. npm
  • LangChain toolkit: pip install langchain-insumer for Python agent frameworks. 6 tools plus HTTP wrapper. PyPI
  • GPT Actions: Import the OpenAPI spec into a Custom GPT. Already live in the GPT Store as InsumerAPI Verify.

These let AI agents autonomously discover merchants, verify tokens, and generate discount codes without writing integration code.

Links

Free to start. 10 verification credits included. Grab a key.

Top comments (0)