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
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.
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.
Response includes an INSR-XXXXX discount code wrapped in the protocol-native format. ACP returns Stripe coupon objects. UCP returns Google commerce extensions.
Merchant backend calls GET /v1/codes/{code} to confirm the code is valid, unexpired, and unused before applying the 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.
| 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. |
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.
{
"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" }
}
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.
{
"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.
Same on-chain verification, Google UCP format. Uses a title string instead of Stripe coupon objects and includes a extension field for protocol identification.
| 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. |
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.
{
"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" }
}
Public endpoint. No API key required. Validate an INSR-XXXXX discount code. Returns valid or invalid status with discount percentage, merchant, and expiration details.
| Parameter | Type | Required | Description |
|---|---|---|---|
code |
string | Required | Discount code in INSR-XXXXX format |
curl https://api.insumermodel.com/v1/codes/INSR-A7B3K
{
"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" }
}
{
"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
| Feature | ACP | UCP |
|---|---|---|
| Protocol | OpenAI | |
| 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).
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.
See how this endpoint fits the full API → API Topology