Log inShow my feed
Docs

Feed and checkout API

Everything an agent needs to find your products and send a shopper to pay. Replace STORE_ID with the id in your dashboard under Feed & docs.

Quickstart

From your store URL to a first test order in five steps. No code needed.

  1. Paste your store addressOn the home page, enter your store URL and press Show my feed. We read your product pages.
  2. Check the preview, then create a free accountYou see every product we found and what blocks a sale. The account keeps that catalog.
  3. Fix what blocks sales and publishRed issues (no price, unreadable price, duplicate SKU) stop checkout. Publish makes your feed public at /feeds/STORE_ID.
  4. Turn on channelsPick the agents and add the cart widget to your site. Copy the feed URL and skill.md for agents.
  5. Place a test orderOpen your agent link, pay with the test card 4242 4242 4242 4242. The order shows in Orders with the agent that sent it.

Feed spec

Every published store has a public JSON feed. CORS is open, no key needed. Fields follow the OpenAI Product Feed Spec, plus a BMOS checkout block. “Always” fields are never null.

GET/feeds/STORE_ID
curl https://bmos-app.apps.art-and-see.com/feeds/STORE_ID

Top level

FieldTypeRequiredExample
feed_versionstringAlways"0.2"
Version of this spec.
generated_atstring (ISO 8601)Always"2026-09-24T17:51:40.245Z"
When the feed was built. Feeds are cached 60 s.
merchant.idstringAlways"7o62d9SQ9T0g"
Store id. Use it as store_id in checkout.
merchant.namestringAlways"Excalibur Brothers"
merchant.urlstring (URL)Always"https://www.excaliburbrothers.com"
The store’s own website.
merchant.currencystring (ISO 4217)Always"USD"
merchant.return_policystring (URL) | nullNullable"https://…/faqs/"
merchant.terms_of_servicestring (URL) | nullNullablenull
merchant.privacy_policystring (URL) | nullNullablenull
capabilities.human_checkoutstring (URL)Always"…/c/STORE_ID"
Base of the agent checkout link.
capabilities.agent_checkoutstring (URL)Always"…/api/checkout_sessions"
Checkout API endpoint.
capabilities.payment_methodsstring[]Always["card","apple_pay","google_pay","paypal","crypto"]
crypto only when the store has a USDC rail.
capabilities.crypto_railsstring[]Always["base"]
Any of base, solana, tempo, coinbase.
capabilities.test_modebooleanAlwaystrue
Nothing is charged while true.
productsProduct[]Always[…]
Hidden products are left out.

Product

FieldTypeRequiredExample
idstringAlways"lJY0B7QjtBV5Uw"
Use this in items[].id.
item_idstringAlways"75-PS2012"
Merchant SKU, or id when there is none. Checkout accepts it too.
titlestringAlways"12 in 1 Phillips, Flathead and Socket Pocket"
descriptionstringAlways"Durable and extremely useful…"
Empty string when missing.
linkstring (URL)Always"https://…/product/…"
Product page on the store. Can be empty.
image_linkstring (URL)Always"https://…/75-PS2012.png"
Empty string when missing.
additional_image_linkstring[]Always[]
Up to 5 more images.
pricestring | nullNullable"23.97 USD"
Amount and currency. null when unknown.
availabilitystringAlways"in_stock"
in_stock, out_of_stock or preorder.
brandstringAlways"Excalibur Brothers"
Falls back to the store name.
seller_namestringAlways"Excalibur Brothers"
gtinstring | nullNullable"0012345678905"
8, 12, 13 or 14 digits.
mpnstring | nullNullablenull
product_categorystring | string[] | nullNullable"Tools > Screwdrivers"
item_group_idstring | nullNullablenull
Groups variants of one product.
variantstring | nullNullable"Blue / Large"
is_eligible_searchbooleanAlwaystrue
Always true: agents may show it.
is_eligible_checkoutbooleanAlwaystrue
Only these can be bought here.
channels_excludedstring[]Always[]
Agents this product is hidden from, e.g. ["grok"].
externalbooleanAlwaysfalse
true = sold elsewhere (affiliate). Recommend, do not buy.
external_linkstring (URL) | nullNullablenull
Where an external product is sold.
checkoutobject | nullNullable{ "type": "bmos_checkout_session", … }
Ready-made request: endpoint, method, body, and human_url for the shopper. null when not buyable.

skill.md

Plain instructions an agent can follow: where the feed is, which products can be bought, and how to open a checkout. Markdown, CORS open.

GET/feeds/STORE_ID/skill.md
curl https://bmos-app.apps.art-and-see.com/feeds/STORE_ID/skill.md

Checkout API

Sessions follow the Agentic Checkout states: not_ready_for_payment → ready_for_payment → completed or canceled. Amounts are in cents. All routes are JSON with CORS open.

POST

/api/checkout_sessions

Create a session from feed product ids (or SKUs). Returns 201. Items that cannot be bought come back in errors; if none can be bought you get 422.

POST/api/checkout_sessions
curl -X POST https://bmos-app.apps.art-and-see.com/api/checkout_sessions \
  -H 'content-type: application/json' \
  -d '{"store_id":"STORE_ID","items":[{"id":"PRODUCT_ID","quantity":1}],"agent":"Claude"}'

agent is one of chatgpt, claude, gemini, perplexity, copilot, grok. It stamps the order so the merchant sees who sent it. Optional: buyer, fulfillment_address.

Response

201 Created
{
  "id": "cs_k3m9x2p0qa",
  "status": "not_ready_for_payment",
  "currency": "USD",
  "line_items": [
    { "id": "PRODUCT_ID", "item": { "id": "PRODUCT_ID", "quantity": 1 },
      "title": "12 in 1 Phillips, Flathead and Socket Pocket", "base_amount": 2397, "total": 2397 }
  ],
  "totals": [
    { "type": "subtotal", "amount": 2397 }, { "type": "fulfillment", "amount": 595 },
    { "type": "tax", "amount": 0 }, { "type": "total", "amount": 2992 }
  ],
  "fulfillment_options": [
    { "id": "standard", "title": "Standard", "subtitle": "3–5 business days", "total": 595 },
    { "id": "express", "title": "Express", "subtitle": "1–2 business days", "total": 1495 }
  ],
  "fulfillment_option_id": "standard",
  "buyer": null,
  "fulfillment_address": null,
  "messages": [{ "type": "info", "content": "Buyer email and delivery address are required before payment." }],
  "links": { "pay": "https://bmos-app.apps.art-and-see.com/pay/cs_k3m9x2p0qa", "terms_of_use": null, "return_policy": "https://…" },
  "order": null,
  "test_mode": true,
  "errors": []
}
GET

/api/checkout_sessions/:id

Read status, line items, totals and delivery options.

GET/api/checkout_sessions/SESSION_ID
curl https://bmos-app.apps.art-and-see.com/api/checkout_sessions/SESSION_ID
POST

/api/checkout_sessions/:id

Add the buyer, the delivery address, a delivery option, or replace items. When email and address are set, status becomes ready_for_payment.

POST/api/checkout_sessions/SESSION_ID
curl -X POST https://bmos-app.apps.art-and-see.com/api/checkout_sessions/SESSION_ID \
  -H 'content-type: application/json' \
  -d '{"buyer":{"email":"sam@example.com","name":"Sam Lee"},"fulfillment_address":{"line1":"1 Main St","city":"Austin","state":"TX","zip":"78701","country":"US"},"fulfillment_option_id":"standard"}'
POST

/api/checkout_sessions/:id/complete

Complete the order. payment.method: card, applepay, googlepay, paypal or crypto (crypto needs payment.rail). Response has status: "completed" and order.id. Test mode: nothing is charged.

POST/api/checkout_sessions/SESSION_ID/complete
curl -X POST https://bmos-app.apps.art-and-see.com/api/checkout_sessions/SESSION_ID/complete \
  -H 'content-type: application/json' \
  -d '{"payment":{"method":"card"}}'
POST

/api/checkout_sessions/:id/cancel

Cancel a session that was not paid. A completed session stays completed.

POST/api/checkout_sessions/SESSION_ID/cancel
curl -X POST https://bmos-app.apps.art-and-see.com/api/checkout_sessions/SESSION_ID/cancel

Most agents should not pay for the shopper. Give the shopper links.pay so they confirm the exact total and pay on the store’s checkout.

Widget

One script tag adds the cart drawer and checkout to your site. It reads your feed, so prices always match.

HTML · before </body>
<script src="https://bmos-app.apps.art-and-see.com/widget.js" data-store="STORE_ID" defer></script>

Your own buttons

Mark any button with a feed product id (or SKU). The widget wires the click.

HTML
<button data-bmos-add="PRODUCT_ID">Add to cart</button>

From JavaScript

JavaScript
window.BMOS.add('PRODUCT_ID', 2); // add 2 to the cart and open it
window.BMOS.open();               // open the cart drawer
window.BMOS.products;             // the feed products the widget loaded

On a product page the feed knows, with no data-bmos-add button, the widget adds its own buy box with price and variants.

Errors

Errors are JSON { "error": "message" }. The message is written for a person; show it as is.

StatusWhenMessage
200Read, update, complete or cancel worked—
201Session createdMay include errors[] for items left out: “Unknown product”, “This product cannot be bought here”
303Agent link openedRedirects to /pay/SESSION_ID
404Feed of an unknown or unpublished store“Feed not found or not published”
404Create with an unknown or unpublished store_id“Unknown or unpublished store”
404Session id does not exist“Not found”
422None of the items can be bought“None of the items can be bought here”, plus errors[]
422Complete with no email or address“Email and delivery address are required before payment”
422Complete with an empty cart“Cart is empty”
422Crypto payment without a network“Pick a crypto network”
500Our fault“Something went wrong on our side. Try again.”

Test mode & test card

Every store runs in test mode today. Payments are simulated end to end, nothing is charged, and orders are real records in the dashboard. Feeds and sessions say test_mode: true.

Test card 4242 4242 4242 4242 · any future date · any 3 digits. Apple Pay, Google Pay, PayPal and USDC (Base, Solana, Tempo, Coinbase) are simulated too.

Changelog

  • 24 Sep 2026 · Feed 0.2

    Current version. The feed includes a per-product checkout block with a ready request and human_url, channels_excluded, external and external_link for affiliate items, and capabilities.crypto_rails.