Docs
Dashboard

AI Commerce

Every GullyPay merchant is automatically agent-native. GullyPay publishes a merchant.ai.json config — generated from the merchant's real stores and products — so AI agents can discover merchants, search their catalog, and open checkout sessions without ever loading a website.

Base path

All AI Commerce endpoints live under the /ai base path on the GullyPay API.

How It Works

AI discovery & checkout flow
Agent                         GullyPay AI Commerce
|                                   |
|  1. GET /ai/merchants             |
|---------------------------------->|   discover agent-ready merchants
|  [{ id, name, slug, status }]     |
|<----------------------------------|
|                                   |
|  2. GET /ai/merchants/:id/config  |
|---------------------------------->|   fetch merchant.ai.json
|  { config: {...} }                |
|<----------------------------------|
|                                   |
|  3. GET /ai/search?q=monitor      |
|---------------------------------->|   search active products
|  { results: [...], total }        |
|<----------------------------------|
|                                   |
|  4. POST /ai/sessions             |
|---------------------------------->|   open an AI checkout session
|  { id, agentId, expiresAt, ... }  |
|<----------------------------------|

Endpoints

GET/ai/merchantsList AI-discoverable (active) merchants — public
GET/ai/merchants/:merchantId/configGet the merchant.ai.json config (generated on first read) — public
POST/ai/merchants/:merchantId/config/generateRegenerate the config from live stores & products — requires merchant JWT
GET/ai/searchAgent product search across active products — public
POST/ai/sessionsOpen an AI checkout session for an agent — requires a scoped API key
Authentication

The discovery reads (GET /ai/merchants, GET /ai/merchants/:id/config, GET /ai/search) are public so autonomous agents can discover and browse without a platform login. Regenerating a merchant's config is a state-changing write, so POST /ai/merchants/:merchantId/config/generate requires the merchant's JWT (the dashboard "Regenerate config" button sends it automatically). POST /ai/sessions is machine-facing and requires a scoped API key (Authorization: Bearer rk_…), the same credential the x402 SDKs send.

GET /ai/merchants

Returns the merchants that are active and therefore discoverable by agents.

Response
[
{
  "id": "b3f1c2a4-...",
  "name": "Northwind Coffee",
  "slug": "northwind-coffee",
  "status": "active"
}
]

GET /ai/merchants/:merchantId/config

Returns the persisted merchant_ai_configs row for the merchant. If no config exists yet, one is generated from the merchant's live catalog and returned.

Response
{
"id": "9a7e...",
"merchantId": "b3f1c2a4-...",
"version": "1.0",
"publishedAt": "2026-07-18T12:00:00.000Z",
"createdAt": "2026-07-18T12:00:00.000Z",
"updatedAt": "2026-07-18T12:00:00.000Z",
"config": {
  "merchant": { "id": "b3f1c2a4-...", "name": "Northwind Coffee", "slug": "northwind-coffee" },
  "stores": [
    { "id": "s_1...", "name": "Main Store", "currency": "USD" }
  ],
  "products": [
    { "id": "p_1...", "title": "House Blend 1lb", "type": "physical", "status": "active" }
  ],
  "capabilities": ["search", "purchase", "refund"],
  "version": "1.0"
}
}

merchant.ai.json schema

The config object is the merchant.ai.json document. Its fields are built directly from the merchant's real records — no data is fabricated.

FieldTypeDescription
merchantobject{ id, name, slug } of the merchant
storesarrayOne entry per store: { id, name, currency }
productsarrayOne entry per product in the first store: { id, title, type, status }
capabilitiesstring[]Agent actions this merchant supports: search, purchase, refund
versionstringConfig schema version (currently 1.0)

POST /ai/merchants/:merchantId/config/generate

Rebuilds the merchant.ai.json from the merchant's current stores and products and persists a new row. Call this after adding, editing, or archiving products so agents see an up-to-date catalog. Returns the same shape as GET .../config.

Keep it fresh

The config is a snapshot, not a live view. Regenerate it whenever your catalog changes — the merchant dashboard exposes a Regenerate config button that calls this endpoint.

GET /ai/search

Agent-facing product search. Matches the query (case-insensitive substring) against the titles of active products across the platform.

Request
GET /ai/search?q=coffee
Query paramTypeRequiredDescription
qstringNoSearch term; empty returns all active products
Response
{
"results": [
  {
    "id": "p_1...",
    "storeId": "s_1...",
    "title": "House Blend 1lb",
    "type": "physical",
    "status": "active",
    "price": 1800,
    "sku": "HB-1LB"
  }
],
"total": 1
}
Prices are in minor units

price is an integer in the store currency's smallest unit (e.g. cents). 1800 = $18.00.

POST /ai/sessions

Opens an AI checkout session for an agent against a merchant. The session expires 30 minutes after creation.

Request Body
{
"agentId": "agent_shopping_01",
"merchantId": "b3f1c2a4-..."
}
FieldTypeRequiredDescription
agentIdstringYesIdentifier of the agent opening the session
merchantIdstringYesMerchant the session targets
Response
{
"id": "sess_...",
"agentId": "agent_shopping_01",
"merchantId": "b3f1c2a4-...",
"sessionData": {},
"status": "active",
"expiresAt": "2026-07-18T12:30:00.000Z",
"createdAt": "2026-07-18T12:00:00.000Z"
}
Session scope (sandboxed)

Sessions today establish an authenticated agent context (id, merchant, 30-minute expiry). Executing the purchase itself is completed through the standard Checkout and Payments flows — the session object does not yet carry a cart or capture funds on its own.

Example: an agent buying flow

agent-buy.ts
1const API = 'https://gullypay.xyz/api';
2
3// 1. Discover merchants
4const merchants = await fetch(`${API}/ai/merchants`).then((r) => r.json());
5const merchant = merchants[0];
6
7// 2. Read the merchant.ai.json
8const { config } = await fetch(
9`${API}/ai/merchants/${merchant.id}/config`,
10).then((r) => r.json());
11
12// 3. Search the catalog
13const { results } = await fetch(
14`${API}/ai/search?q=${encodeURIComponent('coffee')}`,
15).then((r) => r.json());
16
17// 4. Open a checkout session (machine-facing — send your scoped API key)
18const session = await fetch(`${API}/ai/sessions`, {
19method: 'POST',
20headers: {
21  'Content-Type': 'application/json',
22  Authorization: `Bearer ${process.env.GULLYPAY_API_KEY}`,
23},
24body: JSON.stringify({ agentId: 'agent_shopping_01', merchantId: merchant.id }),
25}).then((r) => r.json());
26
27console.log(session.id, config.capabilities, results.length);

Next Steps