---
title: "Configure NFT collections"
method: PUT
path: "/v1/merchants/{id}/nfts"
tags: ["Merchant Setup"]
---

# Configure NFT collections

`PUT /v1/merchants/{id}/nfts`

## Request

- Base URL: `https://api.insumermodel.com`
- URL: `https://api.insumermodel.com/v1/merchants/{id}/nfts`
- Auth: API key in header `X-API-Key`

Set NFT collections that grant discounts. Max 4 collections. Must be called by the API key that created the merchant.

## Path parameters

- `id` string, required

## Request body

- object
  - `nftCollections` NftConfig[], required
    - `name` string, required
    - `contractAddress` string, required: Collection contract address, validated per chain: 0x + 40 hex on EVM chains; a mint address on Solana (base58, 32 to 44 characters; "native" is refused); the issuer r-address on XRPL, whose base58 checksum is verified. A malformed address returns 400.
    - `chainId` union, required: Chains supported for merchant token/NFT configuration: all 31 EVM chains (same integer IDs as ChainId) plus Solana ("solana") and XRP Ledger ("xrpl"). Bitcoin, Tron, Stellar, and Sui are not available for merchant registry configuration, though they remain queryable via /v1/attest and /v1/trust.
      - 1 | 56 | 8453 | 43114 | 137 | 42161 | 10 | 88888 | 1868 | 98866 | 146 | 100 | 5000 | 534352 | 59144 | 324 | 81457 | 167000 | 2020 | 42220 | 88 | 204 | 480 | 130 | 57073 | 1329 | 80094 | 33139 | 50 | 4663 | 5042
      - 'solana' | 'xrpl'
    - `taxon` integer: XRPL NFToken taxon filter. Optional, for filtering NFTs by collection under the same issuer. An integer from 0 to 4294967295; anything else is a 400. The XRPL issuer address is checksum-verified, so a mistyped issuer is a 400.
    - `benefitType` 'discount' | 'recognition': What holding the collection grants. "discount" applies the configured percentage; "recognition" only marks the pass as recognized (door access) and carries no discount.
    - `discount` integer: Discount percentage: a whole number from 1 to 50, as a JSON number or its digits as a string. A value with a fraction (10.5) is a 400; "10.0" is accepted as 10. Required only when benefitType is "discount" (the default); ignored for "recognition".
    - `enabled` boolean: Merchant's on/off toggle for this collection. Absent means enabled; only an explicit false disables it. A value that is not a boolean is a 400.

## Response `200`

NFTs configured

- object
  - `ok` true
  - `data` object
    - `nftCollections` object[]
      - `name` string
      - `discount` integer
      - `chainId` union: EVM chain ID (integer), or one of "solana", "xrpl", "bitcoin", "tron", "stellar", "sui" (string). Supported chains: Ethereum (1), BNB Chain (56), Base (8453), Avalanche (43114), Polygon (137), Arbitrum (42161), Optimism (10), Chiliz (88888), Soneium (1868), Plume (98866), Sonic (146), Gnosis (100), Mantle (5000), Scroll (534352), Linea (59144), zkSync Era (324), Blast (81457), Taiko (167000), Ronin (2020), Celo (42220), Viction (88), opBNB (204), World Chain (480), Unichain (130), Ink (57073), Sei (1329), Berachain (80094), ApeChain (33139), XDC Network (50), Robinhood Chain (4663), Arc (5042), Solana ("solana"), XRP Ledger ("xrpl"), Bitcoin ("bitcoin"), Tron ("tron"), Stellar ("stellar"), Sui ("sui"). Bitcoin only supports token_balance with contractAddress "native". Tron, Stellar, and Sui support token_balance only. Moonbeam (1284) and Moonriver (1285) were retired on 2026-09-20 after both networks stopped producing blocks. GLMR and MOVR now live on Base (chainId 8453) as ERC-20s and are read with an ordinary token_balance condition; a request naming either retired chain returns 400.
        - 1 | 56 | 8453 | 43114 | 137 | 42161 | 10 | 88888 | 1868 | 98866 | 146 | 100 | 5000 | 534352 | 59144 | 324 | 81457 | 167000 | 2020 | 42220 | 88 | 204 | 480 | 130 | 57073 | 1329 | 80094 | 33139 | 50 | 4663 | 5042
        - 'solana' | 'xrpl' | 'bitcoin' | 'tron' | 'stellar' | 'sui'
    - `totalCollections` integer
    - `maxCollections` integer
  - `meta` Meta
    - `version` string
    - `timestamp` string, date-time

## Other responses

- `400`: Validation error
- `401`: Invalid or missing API key
- `403`: API key does not own this merchant
- `404`: Merchant not found
- `429`: Rate limit exceeded. API-key requests count against the key's daily limit; every authenticated response carries X-RateLimit-Limit and X-RateLimit-Remaining headers, and a 429 additionally carries Retry-After (seconds until the window resets).
- `500`: Unexpected server error. Safe to retry; no credits are charged on a 500. Router endpoints return the standard error envelope; standalone endpoints (the ones whose 200 is a flat object) return a flat {"error": "..."} object.

---

[API](https://skmtc.dev/insumermodel/apis/insumerapi.md) · [All operations](https://skmtc.dev/insumermodel/apis/insumerapi/llms.txt) · [OpenAPI document](https://skmtc.dev/insumermodel/apis/insumerapi/revisions/91f56fe9e3d8?raw)
