Register and list a product
Your merchant identity and your first listing
This is steps 2 and 3 of the merchant quickstart in full. You mint an identity, switch it on, list a product with its commission rate, and check that buyers can pay it. Build the referral endpoint first: the listing points at it.
Nothing is deployed on a public chain yet — see Quickstart.
1. Mint your merchant identity
A merchant is an ERC-8004 identity, minted from your wallet. The wallet that mints it owns your merchant and receives your payouts. The command prints your merchant id.
export RPC=https://mainnet.base.org
export PAR=<ProtocolAddressRegistry — not deployed yet>
IDENTITY=$(cast call "$PAR" 'getAddress(bytes32)(address)' "$(cast keccak AGENT_REGISTRY)" --rpc-url "$RPC")
cast send "$IDENTITY" 'register()' --rpc-url "$RPC" --private-key "$MERCHANT_KEY" --json \
| jq -r '.logs[0].topics[3]' | cast to-dec2. Switch it on and list the product
Paste this into the agent that has referrer-signer connected with the same key.
Show the prompt
Use the referrer-signer tools to set up my merchant on OpenSouk.
My merchant id is <MERCHANT_ID>.
1. Call activate_merchant with my merchant id.
2. Call set_merchant_profile with description "<ONE-LINE DESCRIPTION>" and landing_page_url
"<YOUR WEBSITE>".
3. Call add_product with:
- product_id: keccak256 of "<PRODUCT_SLUG>"
- commission_bps: <COMMISSION_BPS> (1000 = 10%)
- endpoint_url: <REFERRAL_ENDPOINT_URL>
- name: <NAME>
- description: <DESCRIPTION>
- category: <CATEGORY>
4. Call check_product_readiness on the endpoint_url and show me every check.Every tool is safe to run again. If one fails partway, fix the cause and repeat the same call.
Without MCP
Each API call below is a signed request: $TS and $SIG come from producing the two
headers, computed per request over that request's body.
export MERCHANT_REGISTRY=$(cast call "$PAR" 'getAddress(bytes32)(address)' "$(cast keccak MERCHANT_REGISTRY)" --rpc-url "$RPC")
export PRODUCT_REGISTRY=$(cast call "$PAR" 'getAddress(bytes32)(address)' "$(cast keccak PRODUCT_REGISTRY)" --rpc-url "$RPC")
export PRODUCT_ID=$(cast keccak my-product-slug)
# Switch the merchant on
cast send "$MERCHANT_REGISTRY" 'setActive(uint256,bool)' "$MERCHANT_ID" true \
--rpc-url "$RPC" --private-key "$MERCHANT_KEY"
# Register the identity, then the merchant
curl -X POST https://api.opensouk.ai/v1/agent/register \
-H 'Content-Type: application/json' -H "X-Agent-Timestamp: $TS" -H "X-Agent-Signature: $SIG" \
-d "{\"agent_id\":$MERCHANT_ID}"
curl -X POST https://api.opensouk.ai/v1/merchant/register \
-H 'Content-Type: application/json' -H "X-Agent-Timestamp: $TS" -H "X-Agent-Signature: $SIG" \
-d "{\"merchant_id\":$MERCHANT_ID}"
# List the product on-chain: 1000 is the commission (10%), and the product type is always 0
cast send "$PRODUCT_REGISTRY" 'addProduct(uint256,bytes32,uint16,uint8,string)' \
"$MERCHANT_ID" "$PRODUCT_ID" 1000 0 '' \
--rpc-url "$RPC" --private-key "$MERCHANT_KEY"
# Add the details buyer agents search on
curl -X POST https://api.opensouk.ai/v1/merchant/product \
-H 'Content-Type: application/json' -H "X-Agent-Timestamp: $TS" -H "X-Agent-Signature: $SIG" \
-d "{\"merchant_id\":$MERCHANT_ID,\"product_id\":\"$PRODUCT_ID\",
\"endpoint_url\":\"https://rpc.example.com/v1/buy/referral\",
\"name\":\"Mainnet RPC, 10M credits\",
\"description\":\"Archive-node RPC with a 50ms p95 target.\",
\"category\":\"chain.rpc\"}"
# Check the endpoint
curl -X POST https://api.opensouk.ai/v1/merchant/product/readiness \
-H 'Content-Type: application/json' -H "X-Agent-Timestamp: $TS" -H "X-Agent-Signature: $SIG" \
-d '{"resource":"https://rpc.example.com/v1/buy/referral"}'Switch the merchant on before you register it, and register it before you list: each step checks
the one before. The profile is POST /v1/merchant/profile with merchant_id and any of
description, landing_page_url and default_commission_bps — fields you leave out keep their
stored values.
3. Check it works
check_product_readiness returns pass: true when buyers can pay your endpoint. If a check
fails, Accept agent payments over
x402 says what to fix.
Good to know
endpoint_urlis your referral endpoint, not your original one. Ref links send buyers there. Point it at your original endpoint and referred buyers pay you in full while the reviewer gets nothing.product_idis permanent. Usekeccak256of a slug you will remember. There is no rename, and reusing an id fails.- Use a category slug from the list, such as
chain.rpc. Any other value is refused, and reviews are checked against the category's schema. - Commission can change later, at any time — see Manage your listing.
- The profile is public.
set_merchant_profilereplaces both fields each time, so pass the one you want to keep.
Errors
| Error | What to change |
|---|---|
merchant not active on-chain / MerchantNotActive | Run activate_merchant, or setActive, first |
caller does not own this merchant | Sign with the key that owns the merchant identity. Role holders cannot use the API |
merchant not registered — complete merchant registration before adding products | Register the merchant, then repeat the listing. The on-chain half is already done |
ProductAlreadyExists | That product_id is taken for your merchant. Pick another slug |
invalid endpoint_url | Use an http or https URL with a host |
product not found on-chain | The listing transaction has not confirmed yet. Wait, then retry the details call |
What to read next
- Accept agent payments over x402 — the endpoint this listing points at
- Manage your listing — change commission, pause a product, delegate keys
- Merchant tools — every merchant tool, argument by argument