VetoVetoDocs
Getting Started

Overview

Make your store buyable by AI agents – set it up once, mostly no code.

Veto makes your store buyable by AI agents. You set it up once – for most people, with no code – and Veto handles how each agent discovers your products, pays you, and settles the money into your own wallet. You describe what you sell and where the money goes; Veto does the rest (discovery, the payment handshake, signed receipts).

New here? Read this first.

How Veto works – discover, pay, deliver is the whole model in plain English: an agent discovers your store, pays you USDC (a dollar-pegged stablecoin) over x402 (the "pay-per-request" web-payments standard agents speak), and then you deliver the goods – triggered by a signed webhook on every sale.

The no-code path (most people)

If you own a store and just want agents to be able to buy from it, you never touch code. Sign in to the dashboard and click through it:

  1. Sign in at https://merchants.veto-ai.com (magic link).
  2. Create your store – a name, a slug, your storefront domain.
  3. Add a product – a name and a price.
  4. Set where your money goes – your own wallet address on Base (Coinbase's low-fee network), paid in USDC (the dollar-pegged stablecoin). Veto is non-custodial: the money lands in your wallet, never Veto's.
  5. Publish. Your store is now discoverable and buyable by agents.

The full click-by-click walkthrough – including watching a real AI agent buy your product – is in Set up Veto end-to-end (hosted). Most merchants never open a terminal.

The API path (for developers)

Prefer to script it? Every dashboard action is a plain REST call against the hosted platform at https://merchants.veto-ai.com. Authenticate with an API key from Dashboard → Developers – a veto_test_… key for the sandbox (no real money) or a veto_live_… key for real money – and send it as a Bearer token:

who am I
curl https://merchants.veto-ai.com/v1/me \
  -H "Authorization: Bearer veto_test_..."

The two core calls – create a store and add a product – in the language you already use. Prices are always exact decimal strings (e.g. "5.00"), never floats, so money stays exact end to end.

1. Create your store – POST /v1/merchants

curl -X POST https://merchants.veto-ai.com/v1/merchants \
  -H "Authorization: Bearer veto_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "acme",
    "name": "Acme Corp",
    "domain": "shop.acme.example",
    "receiving": {
      "x402": {
        "chain": "base-sepolia",
        "address": "0x1111111111111111111111111111111111111111",
        "asset": "USDC"
      }
    }
  }'
create-merchant.mjs
const res = await fetch("https://merchants.veto-ai.com/v1/merchants", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VETO_API_KEY}`, // veto_test_... or veto_live_...
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    slug: "acme",
    name: "Acme Corp",
    domain: "shop.acme.example",
    receiving: {
      x402: {
        chain: "base-sepolia", // "base" for real money
        address: "0x1111111111111111111111111111111111111111",
        asset: "USDC",
      },
    },
  }),
});

const merchant = await res.json();
console.log(merchant.id); // mrch_... – use this to add products
create_merchant.py
import os
import requests

res = requests.post(
    "https://merchants.veto-ai.com/v1/merchants",
    headers={
        "Authorization": f"Bearer {os.environ['VETO_API_KEY']}",  # veto_test_... or veto_live_...
        "Content-Type": "application/json",
    },
    json={
        "slug": "acme",
        "name": "Acme Corp",
        "domain": "shop.acme.example",
        "receiving": {
            "x402": {
                "chain": "base-sepolia",  # "base" for real money
                "address": "0x1111111111111111111111111111111111111111",
                "asset": "USDC",
            }
        },
    },
)

merchant = res.json()
print(merchant["id"])  # mrch_... – use this to add products

The response includes your merchant id (mrch_…). The receiving block is where settled USDC lands – your wallet, validated at write time so a bad address fails for you now, not for an agent mid-checkout. A veto_test_ key makes a test store on base-sepolia (testnet, no real value); a veto_live_ key makes a live store – set chain to base and use your real address.

2. Add a product – POST /v1/catalog

Pass ?merchant_id= to say which store you're adding to (use the id from step 1).

curl -X POST "https://merchants.veto-ai.com/v1/catalog?merchant_id=mrch_..." \
  -H "Authorization: Bearer veto_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "sku": "rpt-001",
    "name": "Market Report",
    "description": "Q3 market intelligence.",
    "price": { "amount": "5.00", "currency": "USD" },
    "available": true
  }'
add-product.mjs
const merchantId = "mrch_..."; // from step 1

const res = await fetch(
  `https://merchants.veto-ai.com/v1/catalog?merchant_id=${merchantId}`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.VETO_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      sku: "rpt-001",
      name: "Market Report",
      description: "Q3 market intelligence.",
      price: { amount: "5.00", currency: "USD" }, // exact decimal string
      available: true,
    }),
  },
);

console.log(await res.json());
add_product.py
import os
import requests

merchant_id = "mrch_..."  # from step 1

res = requests.post(
    "https://merchants.veto-ai.com/v1/catalog",
    params={"merchant_id": merchant_id},
    headers={
        "Authorization": f"Bearer {os.environ['VETO_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "sku": "rpt-001",
        "name": "Market Report",
        "description": "Q3 market intelligence.",
        "price": {"amount": "5.00", "currency": "USD"},  # exact decimal string
        "available": True,
    },
)

print(res.json())

Then publish (POST /v1/publish?merchant_id=…) to activate the config and rebuild the discovery manifest. The full sequence – receiving, publish, and connecting your own domain – is in Set up Veto end-to-end (hosted), and every endpoint is in the REST API reference.

Or just tell your coding agent

If you're in Cursor or Claude Code, you don't have to write any of the above yourself: point your agent at the @veto-protocol/mcp-merchant MCP server and describe your shop in plain English – it calls these same endpoints for you.

Then: an agent buys it

Once you've published, your store is live and self-describing. An AI agent discovers it at a single manifest URL, pays you USDC over x402, and you deliver the goods – triggered by a signed webhook on every sale. That whole arc is walked through in How Veto works – discover, pay, deliver.


Self-hosting the SDK – running the checkout on your own servers instead of the hosted platform – is an advanced option covered in the SDK reference. Most merchants should use the hosted path above.