VetoVetoDocs
Hosted REST API

Catalog

CRUD the products an agent can buy. Prices are exact decimal strings; deletes are soft. Every write invalidates the manifest cache.

The catalog is the list of CatalogItems an agent sees at /agent/catalog. All catalog routes are tenant-resolved: they target the merchant named by ?merchant_id=, or the project's default merchant when omitted.

Tenant resolution

Pass ?merchant_id=mrch_… to target a specific merchant. Without it, the route falls back to the project's first/default merchant. An id from another project or mode resolves to 404 NOT_FOUND.

The CatalogItem

{
  "sku": "widget",
  "name": "Widget",
  "description": "An optional blurb",
  "price": { "amount": "25.00", "currency": "USD" },
  "available": true,
  "category": "hardware",
  "unit": "each",
  "metadata": { "any": "json" }
}

price.amount is an exact decimal string (≤ 8 dp). Every catalog write invalidates the merchant's manifest cache so the next discovery serve rebuilds.


GET /v1/catalog

List products for the resolved merchant, ordered by category then name.

AuthAPI key · scope products:read
Querymerchant_id (optional), available=true (optional — only available items)
200
{ "items": [ /* CatalogItem[] */ ] }
curl "https://api.veto-ai.com/v1/catalog?merchant_id=mrch_01J…&available=true" \
  -H "Authorization: Bearer veto_test_8f2c…"

POST /v1/catalog

Create a product. The sku is unique per merchant.

AuthAPI key · scope products:write

Request

{
  "sku": "widget",
  "name": "Widget",
  "price": { "amount": "25.00", "currency": "USD" },
  "available": true,
  "description": "An optional blurb",
  "category": "hardware",
  "unit": "each",
  "metadata": {}
}
FieldRequiredRule
skuMatches ^[A-Za-z0-9._-]{1,128}$; unique per merchant.
name
price.amountDecimal string, ≤ 8 dp.
price.currencyStored upper-cased.
availableoptionalDefaults to true.

Status codes

StatusReason codeMeaning
201Created; returns { id, ...CatalogItem }.
400VALIDATION_FAILEDMissing/invalid sku, name, or currency.
400PRICE_AMOUNT_INVALIDprice.amount not a ≤8-dp decimal string.
409PRODUCT_SKU_TAKENSKU already exists for this merchant.
create a product
curl -X POST "https://api.veto-ai.com/v1/catalog?merchant_id=mrch_01J…" \
  -H "Authorization: Bearer veto_test_8f2c…" \
  -H "Content-Type: application/json" \
  -d '{ "sku": "widget", "name": "Widget", "price": { "amount": "25.00", "currency": "USD" } }'

PATCH /v1/catalog/:sku

Update price, availability, or metadata of a product by SKU. Only present fields change.

AuthAPI key · scope products:write
request
{ "price": { "amount": "29.99", "currency": "USD" }, "available": false }
StatusReason codeMeaning
200The updated CatalogItem.
400PRICE_AMOUNT_INVALIDBad price.amount.
404NOT_FOUNDNo such SKU for this merchant.

DELETE /v1/catalog/:sku

Soft-delete — flips available to false so existing orders and receipts keep pointing at a real row. The product still exists; it just won't be offered.

AuthAPI key · scope products:write
StatusMeaning
204Soft-deleted (no body).
404NOT_FOUND — no such SKU.
curl -X DELETE "https://api.veto-ai.com/v1/catalog/widget?merchant_id=mrch_01J…" \
  -H "Authorization: Bearer veto_test_8f2c…"