AI Agent Commerce

Return discount data in OpenAI ACP or Google UCP format so AI shopping agents can apply token-holder discounts natively. Same on-chain verification, standard protocol output.

Combines signed attestation with protocol-native discount output.

Auth: X-API-Key. Wallet-signed auth (Authorization: Wallet) is not accepted on the commerce endpoints; it covers /v1/attest, /v1/trust, /v1/trust/batch, /v1/credits, and /v1/credits/buy. See Authentication →

Building this in Claude Code? Install the wallet auth skill and Claude will write correct, signature-verifying integration code on the first try.

git clone https://github.com/insumerapi/insumer-skill.git ~/.claude/skills/insumer

View on Smithery · GitHub repo

What this does

Generate discount codes from on-chain token holdings in standard commerce protocol formats. ACP-compatible agents get Stripe coupon objects. UCP-compatible agents get Google commerce extensions. Every response is ECDSA-signed with the same key as POST /v1/attest, published at JWKS. The signed payload differs from an attestation's, so it is not checked by the same flow: verify it against JWKS directly, or validate the code through GET /v1/codes/{code}.

A code that carries a discount costs one credit ($0.04 at the base rate), paid by the API key that owns the store (the key that created it); a 0% result is free. A caller using another key is not charged, and the store has no balance of its own. If you call with the owner key, your key pays, and meta.creditsCharged shows 1. 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). Stores run through a licensed platform such as Skye Meta are covered by that platform's license.

Three-step flow

1

Verify holdings

POST /v1/acp/discount or POST /v1/ucp/discount with wallet address and merchantId. The API checks on-chain balances against the merchant's configured tiers.

2

Get discount code

Response includes an INSR-XXXXX discount code wrapped in the protocol-native format. ACP returns Stripe coupon objects. UCP returns Google commerce extensions.

3

Validate at checkout

Merchant backend calls GET /v1/codes/{code} to confirm the code is valid, unexpired, and unused before applying the discount.

POST /v1/acp/discount

ACP Discount

Verifies token holdings and returns the result in OpenAI ACP format. Returns Stripe-style coupon objects with applied and rejected arrays. A code that carries a discount costs 1 credit, paid by the API key that owns the store; a 0% result is free. Response is ECDSA-signed.

Parameters

Parameter Type Required Description
merchantId string Required Merchant ID
wallet string Required* EVM wallet address (0x...). Required unless solanaWallet or xrplWallet is provided.
solanaWallet string Optional Solana wallet address. Use instead of wallet for Solana-based merchants.
xrplWallet string Optional XRPL wallet address (r-address). Use for XRP Ledger-based merchants. The checksum is verified; an address that fails it returns 400.
walletProof object Optional Proof that the caller controls wallet: {message, signature}, an EIP-4361 (Sign-In with Ethereum) message signed by that wallet within the last 5 minutes, with domain api.insumermodel.com or the store's own website, URI https://api.insumermodel.com/v1/merchants/{merchantId} and an unused nonce. A proven wallet gets the full discount its holdings earn, without the store's limits for unproven wallets. A proof object without a string message and signature returns 400; a proof that does not verify returns 401. Neither uses a credit. EVM only: send it with wallet, not with solanaWallet or xrplWallet.
items array Optional Cart items with path and amount (minor units). Supply items or subtotal to receive an applied discount: with neither, applied is empty even for a qualifying wallet, and the discount reaches you through verification.
subtotal number Optional Order-level base in minor units (a fraction is truncated), for callers that do not send line items. Ignored when items is supplied.

Request

curl
curl -X POST \
  https://api.insumermodel.com/v1/acp/discount \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "merchantId": "merchant_abc123",
    "wallet": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "items": [
      { "path": "$.line_items[0]", "amount": 12000 }
    ]
  }'

merchant_abc123 is a placeholder: use the ID of a merchant you created (see Merchant Onboarding). An unknown merchantId returns 404 Merchant not found.

Response

200 OK
{
  "ok": true,
  "data": {
    "protocol": "acp",
    "version": "2026-04-17",
    "discounts": {
      "codes": [],
      "applied": [
        {
          "id": "INSR-A7B3K",
          "coupon": {
            "id": "insumer-insr-a7b3k",
            "name": "Token Holder Discount (15% off)",
            "percent_off": 15
          },
          "amount": 1800,
          "automatic": true,
          "method": "across",
          "priority": 10,
          "allocations": [
            { "path": "$.line_items[0]", "amount": 1800 }
          ],
          "start": "2026-02-27T12:00:00Z",
          "end": "2026-02-27T12:30:00Z"
        }
      ],
      "rejected": []
    },
    "verification": {
      "code": "INSR-A7B3K",
      "expiresAt": "2026-02-27T12:30:00Z",
      "breakdown": [{ "symbol": "UNI", "tier": "Gold", "discount": 15 }],
      "sig": "MEUCIQD...",
      "kid": "insumer-attest-v1",
      "walletProven": false
    }
  },
  "meta": { "creditsRemaining": 47, "creditsCharged": 0, "version": "1.0", "timestamp": "2026-02-27T12:00:00.000Z" }
}

No qualifying tier

When the wallet holds none of the merchant's configured tokens, the response still returns 200. The codes, applied and rejected arrays are all empty: the discount is automatic, so an ineligible wallet is simply one the automatic discount did not apply to, not a rejected code. A verification code is still generated and signed. When a read does not complete, the answer is 503 rpc_failure, never a discount of zero: retry. A frozen XRPL trust line earns no tier.

200 OK (no match)
{
  "ok": true,
  "data": {
    "protocol": "acp",
    "version": "2026-04-17",
    "discounts": {
      "codes": [],
      "applied": [],
      "rejected": []
    },
    "verification": {
      "code": "INSR-K9F2L",
      "expiresAt": "2026-02-27T12:30:01Z",
      "breakdown": [],
      "sig": "MEUCIQD...",
      "kid": "insumer-attest-v1",
      "walletProven": false
    }
  },
  "meta": { "creditsRemaining": 47, "creditsCharged": 0, "version": "1.0", "timestamp": "2026-02-27T12:00:01.000Z" }
}

The response is still ECDSA-signed regardless of eligibility. The signed payload includes verified: false so the attestation itself is verifiable proof the check was performed.

POST /v1/ucp/discount

UCP Discount

Same on-chain verification, Google UCP format. Uses a title string instead of Stripe coupon objects and includes a extension field for protocol identification.

Parameters

Parameter Type Required Description
merchantId string Required Merchant ID
wallet string Required* EVM wallet address (0x...). Required unless solanaWallet or xrplWallet is provided.
solanaWallet string Optional Solana wallet address. Use instead of wallet for Solana-based merchants.
xrplWallet string Optional XRPL wallet address (r-address). Use for XRP Ledger-based merchants. The checksum is verified; an address that fails it returns 400.
walletProof object Optional Proof that the caller controls wallet: {message, signature}, an EIP-4361 (Sign-In with Ethereum) message signed by that wallet within the last 5 minutes, with domain api.insumermodel.com or the store's own website, URI https://api.insumermodel.com/v1/merchants/{merchantId} and an unused nonce. A proven wallet gets the full discount its holdings earn, without the store's limits for unproven wallets. A proof object without a string message and signature returns 400; a proof that does not verify returns 401. Neither uses a credit. EVM only: send it with wallet, not with solanaWallet or xrplWallet.
items array Optional Cart items with path and amount (minor units). Supply items or subtotal to receive an applied discount: with neither, applied is empty even for a qualifying wallet, and the discount reaches you through verification.
subtotal number Optional Order-level base in minor units (a fraction is truncated), for callers that do not send line items. Ignored when items is supplied.

Request

curl
curl -X POST \
  https://api.insumermodel.com/v1/ucp/discount \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "merchantId": "merchant_abc123",
    "wallet": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "items": [
      { "path": "$.line_items[0]", "amount": 12000 }
    ]
  }'

merchant_abc123 is a placeholder: use the ID of a merchant you created (see Merchant Onboarding). An unknown merchantId returns 404 Merchant not found.

Response

200 OK
{
  "ok": true,
  "data": {
    "protocol": "ucp",
    "version": "2026-08-25",
    "extension": "dev.ucp.shopping.discount",
    "discounts": {
      "codes": [],
      "applied": [
        {
          "title": "Token Holder Discount \u2014 15% Off",
          "amount": 1800,
          "automatic": true,
          "method": "across",
          "priority": 10,
          "allocations": [
            { "path": "$.line_items[0]", "amount": 1800 }
          ]
        }
      ]
    },
    "verification": {
      "code": "INSR-M9X2P",
      "expiresAt": "2026-02-27T12:30:00Z",
      "sig": "MEUCIQD...",
      "kid": "insumer-attest-v1",
      "walletProven": false
    }
  },
  "meta": { "creditsRemaining": 47, "creditsCharged": 0, "version": "1.0", "timestamp": "2026-02-27T12:00:00.000Z" }
}
GET /v1/codes/{code}

Validate Code

Public endpoint. No API key required. Validate an INSR-XXXXX discount code. Returns valid or invalid status with discount percentage, merchant, and expiration details.

Path Parameter

Parameter Type Required Description
code string Required Discount code in INSR-XXXXX format

Request

curl
curl https://api.insumermodel.com/v1/codes/INSR-A7B3K

Response (valid)

200 OK
{
  "ok": true,
  "data": {
    "valid": true,
    "code": "INSR-A7B3K",
    "merchantId": "merchant_abc123",
    "discountPercent": 15,
    "expiresAt": "2026-02-27T12:30:00Z",
    "createdAt": "2026-02-27T12:00:00Z",
    "walletProven": false
  },
  "meta": { "version": "1.0", "timestamp": "2026-02-27T12:00:05.000Z" }
}

Response (invalid)

200 OK
{
  "ok": true,
  "data": {
    "valid": false,
    "code": "INSR-A7B3K",
    "reason": "expired"
  },
  "meta": { "version": "1.0", "timestamp": "2026-02-27T12:35:00.000Z" }
}

Possible reason values: not_found, expired, already_used

ACP vs UCP

Feature ACP UCP
Protocol OpenAI Google
Format Stripe coupon objects Title + extension
Version 2026-04-17 2026-08-25
Discount shape coupon.percent_off title string
Start/end times Yes No
Extension field No dev.ucp.shopping.discount

Both share: same on-chain verification, same ECDSA signature, same INSR-XXXXX discount codes, same cost (1 credit from the store's owner key when the code carries a discount).

Reference integration

AsterPay KYA uses POST /v1/attest for ERC-8183 agent trust scoring with 4 conditions in a single call. DJD Agent Score integrates wallet auth into its agent trust scoring architecture in the Coinbase x402 ecosystem. Fork either as a starting point for ACP or UCP commerce integration.

DJD on GitHub AsterPay on GitHub

Related articles

See how this endpoint fits the full API → API Topology

← Compliance Next: Merchant Onboarding →