WooCommerce catalog API for AI shopping agents

A free WooCommerce plugin that exposes your live catalog as a structured REST API for AI shopping agents. No LLM, no cloud, no external service — everything runs on your server.

All catalog endpoints read directly from the WooCommerce database at query time. Price changes, stock updates and new products are immediately reflected — no sync, no snapshot, no delay.

Version1.0.120
RequiresWooCommerce 7.0+
Data sourceLive WooCommerce DB

Installation

  1. Download kalicart-bridge-1.0.120.zip
  2. Upload and activate from WP Admin → Plugins → Add New → Upload
  3. WooCommerce must be active — the plugin checks and alerts if it is not
  4. On activation, all signals are enabled by default (badge, robots.txt, sitemap)
  5. Visit WP Admin → KaliCart to see the catalog health dashboard

Endpoints

All endpoints under /wp-json/kalicart/v1/.

GET/discoverypublicEntry point. Merchant info, capabilities, all endpoint URLs, shipping policy, coupon policy, agent instructions.
GET/catalog/metapublicAccepted filter values: category slugs, price range, gender values, color families.
GET/catalog/categoriespublicFull merchant category tree (WooCommerce native). Each node includes has_products flag.
GET/catalog/searchpublicFull-text + structured filter search.
GET/catalog/productspublicPaginated product listing without text query. All filters apply.
GET/catalog/product/{id}publicSingle product with full normalized payload including shipping and active coupons.
GET/catalog/healthadmin onlyCatalog quality report. Add ?force=true to bust the 5-minute cache.
POST/checkout/sessionpublicCreate cart session — agent passes product_id or items[], receives cart_url and checkout_url for buyer handoff. WooCommerce is payment authority.
GET/ucppublicUCP profile (v2026-04-08) — declares catalog.search and catalog.lookup capabilities for UCP-compliant agents (ChatGPT, Copilot, Gemini). Always reachable, independent of how the host serves /.well-known/.
GET/.well-known/ucp.jsonpublicThe same UCP profile as a physical .json mirror, served application/json on every host.
GET/.well-known/kalicart-bridge.jsonpublicKaliCart Bridge discovery entry point — pointer to the UCP profile and discovery document. Physical .json mirror, served application/json on every host.

Discovery document

The single entry point. Key fields an agent must read:

  • kalicart_agent_catalog.taxonomy — always merchant_native_woocommerce. Read /catalog/categories to enumerate them.
  • public_catalog.query_construction — critical rules for building search queries correctly.
  • public_catalog.search_filters — accepted parameters with allowed values.
  • merchant_shipping_policy — declarative shipping zones, methods and free-shipping thresholds.
  • coupon_policy.price_rule — coupons are always conditional checkout savings; never replace price.current.
  • agent_instructions — ordered steps the agent must follow.
// Minimal agent bootstrap
GET /wp-json/kalicart/v1/discovery
 read public_catalog.* for all endpoint URLs
 read merchant_shipping_policy for shipping reasoning
 read agent_instructions for query rules

Product payload

Price

  • price.encoding: decimal_major_units — values are decimal floats in full currency units (e.g. 29.99 = 29.99 EUR). Not ISO 4217 minor units.
  • price.display: plain-text formatted string (e.g. "29,99 €") — unambiguous, use for presentation.
  • price.vat_included: whether prices include VAT per WooCommerce tax settings.
  • price.price_type: STATIC for standard products. Aligned with KaliCart Global format.
  • list_price: original list price before discounts (simple products only).
  • price.current — the authoritative catalog price. Always use this for commerce decisions.
  • price.on_sale, price.discount_pct — sale state and percentage off regular price.
  • Variable products return price.type: "range" with min_regular, max_regular, min_sale, max_sale.

Stock

  • stock.in_stock — boolean, check before presenting any offer.
  • stock.availability_status — UCP-standard values: in_stock, out_of_stock, backorder.
  • stock.quantity — numeric if the merchant manages stock quantity; null otherwise.
  • stock.quantity_tracked — boolean, whether merchant manages numeric stock.
  • stock.backorder_allowed — boolean, true if backorder is notify or yes.
  • stock.confidencenumeric_stock_quantity (exact count), availability_status_only (merchant does not expose quantity — treat as available, not as confirmed inventory), or variant_dependent (select a variation first).
  • stock.agent_note — present when confidence is not numeric_stock_quantity. Read it before reporting availability.

Computed attributes

  • gender — inferred from pa_gender attribute, category path keywords, tags, product name. null if indeterminate.
  • colors[] — color families mapped from pa_color / pa_colore. Each entry has family and raw.
  • sizes — extracted from pa_size / pa_taglia. Type auto-detected: clothing, numeric or shoes.

Purchase readiness

  • purchase_readiness.statusdirect_cart_possible (simple in-stock product, use checkout_url directly) or variant_selection_required (variable product, user must select a variant first).
  • purchase_readiness.blocking_fields[] — attributes the user must choose before checkout (e.g. ["size"]).
  • purchase_readiness.can_add_to_cart_directly — boolean shortcut.

Variants & Variations

  • variants[] — always an array, never null. Product detail: variable products expose all variations with attributes, price, in_stock, availability_status, sku, barcodes; simple products expose a single entry with the product's own data. List and search responses: simple products keep their single entry, variable products return an empty array for performance — fetch /catalog/product/{id} for the full variants list.
  • variations[] — alias for variable products only (backward compat).
  • Pass variation_id in checkout session payload when creating a session for a variable product.
  • availability_status — UCP-standard values: in_stock, out_of_stock, backorder. Present on both product stock and each variant.
  • list_price — original list price before discounts (strikethrough). Present on simple products; null on variable (price varies per variant).
  • barcodes[] — industry-standard identifiers (EAN, GTIN, UPC) read from WooCommerce product meta. Empty array if not set by merchant.

Metadata

  • metadata.purchase_readiness — same as top-level purchase_readiness, exposed here for UCP-compatible agents that read metadata.
  • metadata.stock_confidence — confidence level of stock data.
  • metadata.bridge_version — plugin version that generated this response.

Shipping zones

shipping.zones[] exposes the full WooCommerce shipping configuration: zone name, country/region codes, methods (free_shipping, flat_rate, local_pickup) with costs and free shipping threshold. Computed once per request and cached. Authoritative shipping cost is always WooCommerce checkout.

Checkout

checkout_url — direct add-to-cart for simple in-stock products. Product page for variable products where variant selection is required.

For multi-product flows use Checkout Sessions below.

Shipping & coupons

Shipping

The discovery document contains merchant_shipping_policy — a snapshot of the WooCommerce shipping zones, methods and free-shipping thresholds. Each product also carries a shipping field with product-level context (class, weight, free-shipping eligibility at current price). WooCommerce checkout is the final authority for destination-specific costs.

Coupons

Each product carries active_coupons[] — active coupons applicable to that product or category. Never replace price.current with a coupon-adjusted value. Present the catalog price; offer the code as a conditional saving at checkout.

Each coupon entry includes combinable_with_sale: "unknown — verify at checkout" and verification_required: true. A coupon is confirmed only after the WooCommerce cart/checkout accepts it and changes totals. Coupons may be combinable with sale prices, but only checkout can confirm this.

// Correct agent presentation
"Price is €89. Use code SAVE20 at checkout for 20% off (≈ €17 saving)."

// Wrong
"Price is €71.20"  ← never compute coupon into price

Checkout sessions (optional)

When enabled by the merchant, agents can create checkout sessions containing one or more products. Each session returns two URLs for the user — no OAuth, no PII, no payment on the agent side.

POST/checkout/sessionpublicCreate session — single product or items[] array (max 20)
GET/checkout/session/{id}publicRetrieve session — items, subtotal, cart_url, checkout_url, status
DELETE/checkout/session/{id}publicCancel session

Session response

  • cart_url — one click: adds all items to cart, lands on WooCommerce cart page. User reviews before paying.
  • checkout_url — one click: adds all items to cart, redirects directly to checkout.
  • subtotal — sum of all item totals at catalog prices. Does not include shipping or coupons.
  • Session expires in 30 minutes. Status transitions: pendingcart_loaded.
// Multi-product session
POST /checkout/session
{
  "items": [
    { "product_id": 1326, "quantity": 1, "variation_id": 1477 },  // required for variable products
    { "product_id": 1307, "quantity": 2 }
  ]
}
 { "cart_url": "...", "checkout_url": "...", "subtotal": 651 }

Agent signals

All four signals are injected automatically on activation — no manual code required.

<link rel="kalicart-agent"> in <head>Points to the discovery document. Picked up by agents that parse the HTML head.
/.well-known/kalicart-bridge.json & /.well-known/agent-catalog.jsonPhysical .json mirrors, served Content-Type: application/json on every host. The extension-less forms (/.well-known/kalicart-bridge, /.well-known/agent-catalog) are also served via WordPress rewrite where the host routes /.well-known/ through WordPress; on hosts that serve /.well-known/ as a static directory they are unavailable, so agents should probe the .json forms. Both are exposed in the discovery document under well_known.*.
/.well-known/ucp.jsonUCP profile (Universal Commerce Protocol v2026-04-08) declaring dev.ucp.shopping.catalog.search and dev.ucp.shopping.catalog.lookup capabilities. Physical .json mirror served application/json on every host; the same profile is always reachable at the REST endpoint /wp-json/kalicart/v1/ucp. Picked up by UCP-compliant agents (ChatGPT, Copilot, Gemini). Includes pointer back to KaliCart Bridge discovery.
AI catalog badgeA speaking <a> anchor in the page body with rel="kalicart-agent", descriptive title and aria-label. Position configurable from wp-admin.
robots.txtAdds Allow: /wp-json/kalicart/v1/ and Sitemap: pointer via the WP robots_txt filter. No file written to disk.
[kalicart_agent_index] shortcodeOptional. Add to any WordPress page to publish a human+machine navigable directory of all endpoints and the live category tree. Once published, paste the page URL in WP Admin → KaliCart → Settings → Agent index page URL — it will appear in the discovery document as agent_index_url.
sitemap-agentic-bridge.xmlServed dynamically at /sitemap-agentic-bridge.xml. Lists all catalog endpoints with agent:role and agent:note annotations.

Federated Catalog

An optional, open discovery network. The Bridge makes your catalog readable by agents that are already on your domain; the Federated Catalog makes it discoverable by agents that don't know your store yet. Opt-in, separate service, revocable at any time.

Two distinct discovery paths — easy to conflate, so worth stating plainly:

Local signals (see Agent signals)The .well-known files, robots.txt entries and the rel="kalicart-agent" head link are first-contact hints for an agent that lands on your domain directly. They do not feed the federated index.
Federated indexA separate, cross-merchant index hosted by KaliCart Global. An agent can search it once and get structured results spanning every federated store, without knowing any of them in advance.

How it works, end to end:

1. Opt-inFrom WP Admin → KaliCart Bridge you tick the Global indexing consent box and click Activate Federated Catalog. The plugin sends one datum — your public site URL. No catalog data is pushed.
2. PullKaliCart Global reads your already-public catalog through the same /discovery and /catalog/* endpoints documented above. It only reads; it never writes to your store.
3. Index & searchYour products are normalized into the shared index. Agents query it through the public global search surface — including the keyless MCP tool global_search — and receive structured, cross-merchant results.
4. Route backWhen your products match, the result points the agent back to your store. The federated index is a discovery/routing layer — authoritative price, availability and checkout always stay on your site, served live by your Bridge.

Revoking is symmetric: untick consent and the plugin signals KaliCart Global to deregister; your catalog is parked and leaves federated results, while direct agent access to your store stays active.

Catalog health dashboard

Real-time catalog quality report from WP Admin → KaliCart.

  • Quality score — 0–100 weighted average across all products based on issue severity.
  • Quality signals — products with high or medium severity issues (missing description, zero price, no category). Nothing is blocked: these products stay fully served to agents, but the issues travel as declared quality flags and lower the score. Each entry links directly to the WP product edit screen.
  • Soft alerts — missing images and missing SKUs appear as low-priority suggestions and do not count as quality signals.
  • Suggestions — prioritized list of catalog improvements with affected product count.

Design rules

  • No LLM. No external service. No cloud. Everything runs on the merchant's server.
  • No custom patch on a single product. Every normalization must be generic and valid for any WooCommerce catalog.
  • Taxonomy is always merchant-native. Never assume a global category structure.
  • price.current is always the catalog price. Coupons are savings at checkout, never price replacements.
  • Shipping policy is declarative. WooCommerce checkout is the final authority for destination-specific costs.
  • The q parameter accepts only the bare product noun. Attributes must go in their own filters.