Docs / REST API

REST API

Every server route the plugin adds lives under the fahad-ai/v1 namespace. This page lists each endpoint, its method, the permission gate that protects it, and the shape of what it returns. Nothing here is invented; it mirrors the routes the plugin registers on your store.

Namespace and base URL

All routes are registered against the WordPress REST API under the fahad-ai/v1 namespace, so the base path on your site is:

https://your-store.com/wp-json/fahad-ai/v1/

The endpoints fall into four groups, each with a different security boundary: the storefront chat endpoints, the admin copilot endpoints, the WhatsApp webhook, and the store-as-an-agent gateway.

How the storefront endpoints are gated

The chat, cart, feedback, and visual search endpoints are intentionally public, because a storefront assistant has to answer guests who are not logged in. They are not left open, though. Each request passes through one shared gate that does two things:

Both limits are adjustable with filters, covered in Hooks & filters:

add_filter( 'fahad_ai_rate_limit', fn() => 40 );   // requests per window
add_filter( 'fahad_ai_rate_window', fn() => 30 );  // window length in seconds
A nonce alone is public, so it is never treated as authorization. The rate limit is what actually protects you from a single client running up provider cost or spamming cart changes.

Storefront chat endpoints

These are the routes the chat widget calls. All four share the gate above: wp_rest nonce plus the per client rate limit, returning 429 when the limit is exceeded.

POST /message

Runs one non streaming conversation turn. You send a messages array of { role, content } entries; the assistant answers using grounded store tools. The response is a JSON object:

{
  "message":    "Here are two options under $50 ...",
  "cards":      [ /* grounded product cards */ ],
  "comparison": [ /* optional side-by-side rows */ ]
}

An empty or malformed messages array returns 400. If every configured provider fails, the endpoint still returns 200 with a friendly fallback message rather than a raw error, so the shopper never hits a dead end.

POST /stream

The same turn as /message, but streamed as Server Sent Events (Content-Type: text/event-stream) so replies render token by token. Each event has a type and a small data payload:

POST /cart

Mutates the WooCommerce cart directly, so card buttons (add to cart, change quantity, remove) do not need an agent round trip. It takes an action plus product_id, quantity, variation_id, or cart_item_key as the action needs, reuses the same cart tools the assistant uses (including their stock and variation validation), and returns the verified cart state as JSON. An unknown action returns 400. It returns JSON rather than SSE so WooCommerce can set its session cookie and guest carts persist.

POST /feedback

Records a thumbs up or thumbs down on a bot reply. You send a rating of up or down, an optional short reason, and opaque conversation_ref and message_ref values. It is telemetry only and stores no personal data. The response confirms the stored row:

{ "ok": true, "id": "fb_a1b2c3" }

Any rating that is not up or down returns 400 before anything is stored.

Visual search

POST /visual-search

The "shop the look" route. It accepts a multipart upload with an image part and optional category, min_price, max_price, and limit filters, then returns visually similar in stock products. It uses the same gate as the chat endpoints (nonce plus rate limit), because a vision lookup is billable. The response shape is:

{ "available": true, "found": 3, "products": [ /* cards */ ] }

Image validation failures return 413 (too large), 415 (wrong type), or 400 (missing). The image ranking itself is a pluggable seam, so with no vision provider registered the route degrades gracefully to { "available": false, "found": 0, "products": [], "message": ... } rather than failing.

WhatsApp webhook

GET and POST /whatsapp

The omnichannel webhook for the WhatsApp channel. Its security boundary is not the chat nonce, because Meta cannot send one. Instead:

The outbound send is a pluggable seam (fahad_ai_whatsapp_send); no live Meta call ships in core.

Admin copilot endpoints

The merchant copilot routes live under /admin. They are gated by the manage_woocommerce capability, not the storefront nonce, so only store managers can reach them. Every one is read only or draft only; nothing here writes to your store. All are GET requests grounded in real WooCommerce data.

A caller without the manage_woocommerce capability is rejected by the permission gate before any handler runs.

Agent gateway endpoints

The store as an agent gateway lives under /agent. These are public read only routes so external AI agents can discover and shop your catalogue using the same grounded data a human shopper sees. They expose only published catalogue data, and the handoff only returns URLs; nothing here mutates the store or charges anyone. See Agent endpoints for the full walkthrough.

Summary table

METHOD  PATH                      GATE                     RETURNS
POST    /message                  nonce + rate limit       { message, cards, comparison }
POST    /stream                   nonce + rate limit       SSE: chunk, tool, products,
                                                           comparison, done, error
POST    /cart                     nonce + rate limit       verified cart state (JSON)
POST    /feedback                 nonce + rate limit       { ok, id }
POST    /visual-search            nonce + rate limit       { available, found, products }
GET     /whatsapp                 verify token             challenge echo
POST    /whatsapp                 X-Hub-Signature-256      delivery ack
GET     /admin/insights           manage_woocommerce       sales summary
GET     /admin/sale-candidates    manage_woocommerce       discount candidates
GET     /admin/product-context    manage_woocommerce       product context
GET     /admin/review-drafts      manage_woocommerce       draft review replies
GET     /agent/llms               public read              text usage policy
GET     /agent/catalog            public read              { count, products }
GET     /agent/search             public read              grounded card data
GET     /agent/product            public read              product details
GET     /agent/checkout-handoff   public read              { note, items }

Common status codes