Overview
Start hereChatAxon supports full feature parity across all e-commerce platforms — not just WooCommerce. The integration is split into two layers:
Product Catalog
Feed URL or webhook — point ChatAxon at your product catalog. Supports Google Merchant XML, Shopify JSON, or a custom endpoint.
Transactional
Add to cart, apply discounts, and track orders — via a JSON endpoint you expose and configure in the widget.
| Feature | WooCommerce | Other platforms |
|---|---|---|
| Product search & AI chat | ✅ Auto | ✅ Feed sync |
| Add to cart | ✅ Native | ✅ JSON endpoint |
| Apply discount code | ✅ Native | ⚠️ Copy code (or JSON endpoint) |
| Order tracking (WIMO) | ✅ Native | ✅ Server endpoint |
| Real-time stock updates | ✅ Webhook | ✅ Webhook |
Feed URL Setup
DashboardIn the ChatAxon dashboard, open Store Settings → Product Feed Integration and paste your feed URL. Select a format or leave it on Auto-detect.
Paste your feed URL
Accepts any publicly accessible URL. The feed must return XML or JSON. No authentication on the feed URL is supported yet.
Click "Test Feed"
We fetch the first 5 products and show them in a preview table. Confirm the format is correct.
Click "Sync Now"
A background job fetches all products, generates AI embeddings, and indexes them. Large catalogs may take a few minutes.
Embed the widget
Copy your chataxon_ API key and follow the instructions below.
Google Merchant Center XML
RecommendedThe most widely supported format. If you already run Google Shopping ads, you already have this feed. Both RSS 2.0 (<rss><channel><item>) and Atom (<feed><entry>) are supported.
Platforms with built-in export
- PrestaShop — built-in Google Shopping module
- Magento / Adobe Commerce — native data feed
- Wix eCommerce — Marketing → Google Shopping
- BigCommerce — Channel Manager → Google Shopping
- WooCommerce — plugins: Product Feed PRO, WOOSEA
Minimal example
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>My Store</title>
<item>
<g:id>SKU-001</g:id>
<g:title>Nike Air Max 90</g:title>
<g:description>Classic everyday sneaker.</g:description>
<g:price>129.99 USD</g:price>
<g:image_link>https://mystore.com/img/nike.jpg</g:image_link>
<g:link>https://mystore.com/products/nike-air-max-90</g:link>
<g:product_type>Sneakers</g:product_type>
<g:availability>in stock</g:availability>
</item>
</channel>
</rss>Recognized fields
| Field | Required | Description |
|---|---|---|
| g:id | required | Unique product identifier |
| g:title | required | Product name shown in chat |
| g:description | optional | Long text used for AI search |
| g:price | optional | Numeric price with currency code (e.g. 29.99 USD) |
| g:image_link | optional | Primary product image URL |
| g:link | optional | Product page URL |
| g:product_type | optional | Category label |
| g:availability | optional | "in stock" or "out of stock" |
ChatAxon JSON
For custom platformsThe simplest option if your developer is building a custom endpoint. Serve a JSON response at any URL — we handle the rest.
Content-Type: application/json.Format
{
"products": [
{
"id": "123",
"name": "Nike Air Max 90",
"description": "Classic everyday sneaker, available in 5 colors.",
"price": 129.99,
"image": "https://mystore.com/img/nike.jpg",
"url": "https://mystore.com/products/nike-air-max-90",
"category": "Sneakers",
"in_stock": true,
"variant_id": "123-42"
}
]
}| Field | Required | Description |
|---|---|---|
| id | required | Unique product identifier (string or number) |
| name | required | Product name |
| description | optional | Product description (HTML stripped automatically) |
| price | optional | Numeric price (no currency symbol) |
| image | optional | Primary image URL |
| url | optional | Product page URL |
| category | optional | Category string |
| in_stock | optional | Boolean or "in stock" / "out of stock" |
| variant_id | optional | Variant identifier passed to addToCart hook (size, color, etc.) |
// GET /chataxon-feed.json
app.get('/chataxon-feed.json', async (req, res) => {
const products = await db.query(
'SELECT id, name, description, price, image_url, slug FROM products WHERE active = 1'
);
res.json({
products: products.map(p => ({
id: String(p.id),
name: p.name,
description: p.description,
price: parseFloat(p.price),
image: p.image_url,
url: `https://mystore.com/products/${p.slug}`,
in_stock: true,
}))
});
});Shopify — Product Feed
Zero configEvery Shopify store exposes a public /products.json endpoint. No plugin or app install required.
Enter your store URL
Paste https://your-store.myshopify.com — or your custom domain — into the Feed URL field. Select Auto-detect or Shopify.
That's it
ChatAxon automatically calls /products.json?limit=250&page=N, paginates through all pages (up to 5 000 products), and indexes everything including variant IDs.
/products.json is public by default. If you have a password-protected store (development mode), the endpoint will return 401 and the sync will fail.For add-to-cart, discounts, and order tracking on Shopify, see
Cart Integration
JSON endpointThe ChatAxon widget can add products directly to your cart on any platform by calling a JSON endpoint you host. If cart.addToCartUrl isn't configured, the widget falls back to WooCommerce's own ajax cart (?wc-ajax=add_to_cart), so WordPress stores need no configuration here at all.
window.ChatAxonConfig.cart before the ChatAxon widget script executes.Config shape
window.ChatAxonConfig.cart = {
// Required to activate the cart adapter at all.
addToCartUrl: 'https://yourstore.com/api/cart/add',
// Extra headers merged into every request — this is where you pass your
// platform's own session id / CSRF token. Read them fresh at page-load
// time (e.g. from a cookie) since the config is built once per page load.
headers: { 'X-Session-ID': '...' },
};What the widget sends
POST https://yourstore.com/api/cart/add
Content-Type: application/json
<...your configured headers>
{ "product_id": "123", "quantity": 1 }A 2xxresponse is treated as success (the widget shows “Added!” and does not need any particular response body). Any other status is treated as a failure.
Implementation example
// Read whatever your framework already uses for session/CSRF at page-load
// time, then wire it into the widget config before the script tag loads.
window.ChatAxonConfig = {
apiKey: 'chataxon_YOUR_API_KEY',
apiUrl: 'https://api.chataxon.com',
cart: {
addToCartUrl: '/api/cart/add',
headers: { 'X-Session-ID': getMySessionId() },
},
};fetch()call, it does not read cookies or inject CSRF tokens for you the way a framework's HTTP client might.Discount Codes
WooCommerce[COUPON:CODE] mechanism requires WooCommerce API keys — the AI fetches active coupons live from your WooCommerce admin (/wp-json/wc/v3/coupons) and only offers codes it finds there. There is currently no way to configure a coupon list for non-WooCommerce stores, so the AI will not proactively offer discounts on custom/feed-based integrations.When the AI offers a discount, it embeds a tag in its response: [COUPON:CODE] (e.g. [COUPON:SUMMER20]). The widget intercepts this tag and renders a code card instead of showing it as plain text. What happens when the shopper clicks it depends on whether you've configured cart.applyCouponUrl (see ):
- Not configured (default for non-WooCommerce): clicking the code copies it to the clipboard. This covers most custom storefronts, which usually have their own promo field at checkout rather than a live-apply endpoint.
- WooCommerce: applied directly to the live WooCommerce cart via the plugin's own ajax handler — no configuration needed.
cart.applyCouponUrlconfigured: the widget POSTs{ code }as JSON to your endpoint instead of copying.
applyCouponUrl config
window.ChatAxonConfig.cart = {
addToCartUrl: '/api/cart/add', // required for the cart adapter to activate
applyCouponUrl: '/api/cart/coupon', // optional — omit to use copy-to-clipboard instead
headers: { 'X-Session-ID': getMySessionId() },
};Your endpoint receives POST { code: "SUMMER20" } and should return a 2xx for a successfully applied code, any other status otherwise. The widget does not require a specific response body — it does not parse discount amounts back out today.
Order Tracking API
WooCommerce-shapedWhen a customer asks “Where is my order?”, the AI collects an order ID and email in chat, then calls the same store endpoint used for real-time product sync — there is no separate order-tracking URL to configure. It requests GET {store_url}/wp-json/wc/v3/orders/{orderId}, authenticated with HTTP Basic Auth using the same consumer key/secret pair from your Connect Store step.
feed_url and have no store_url + consumer key/secret setup, set order_lookup_url on your store instead and we call that endpoint rather than the WooCommerce-shaped one. It takes ?order_id=&email=, is authenticated with an X-ChatAxon-Secret header carrying the same secret as GET /api/store/feed/webhook-secret, and answers with { status, email?, tracking_number?, carrier?, shipped_at?, estimated_delivery? } — or 404 / { found: false } for an unknown order. Only status is required, and the same status mapping and carrier links described below apply.Expose one endpoint per order
GET {store_url}/wp-json/wc/v3/orders/{orderId} — the exact path WooCommerce itself uses. orderId is whatever the customer typed (their order number), not necessarily numeric.
Authenticate the same way as product sync
HTTP Basic Auth: Authorization: Basic base64(consumer_key:consumer_secret).
Return billing.email — it's the security check
ChatAxon compares the email the customer typed in chat against billing.emailin your response (case-insensitive). A mismatch is treated as “not your order” and nothing is disclosed.
Request
GET https://your-store.com/wp-json/wc/v3/orders/ORD-12345
Authorization: Basic base64(consumer_key:consumer_secret)Response — order found
{
"id": 12345,
"status": "shipped",
"billing": { "email": "customer@email.com" },
// Everything below is optional. A plain WooCommerce order never has
// these fields — the AI only mentions tracking info when present.
"tracking_number": "1Z999AA10123456784",
"carrier": "ups",
"status_description": "In Transit",
"shipped_at": "2026-06-08T14:30:00Z",
"estimated_delivery": "2026-06-15T18:00:00Z"
}Response — order not found
Return an HTTP 404 — there is no found: false body to construct.
| Field | Required | Description |
|---|---|---|
| id | required | Order identifier (echoed back, not otherwise used) |
| status | required | Any string — combined with your store's configured status-message mapping in the ChatAxon dashboard |
| billing.email | required | Used for the security check against what the customer typed in chat |
| tracking_number | optional | Carrier tracking number |
| carrier | optional | e.g. "ups", "fedex" — shown uppercased next to the tracking number |
| status_description | optional | Human-readable carrier status ("In Transit", "Delivered"…) |
| shipped_at | optional | ISO 8601 — when the AI mentions a ship date |
| estimated_delivery | optional | ISO 8601 — when the AI mentions an ETA |
Implementation examples
// GET /wp-json/wc/v3/orders/:orderId
app.get('/wp-json/wc/v3/orders/:orderId', requireBasicAuth, async (req, res) => {
const order = await db.orders.findOne({ where: { number: req.params.orderId } });
if (!order) return res.status(404).json({});
res.json({
id: order.id,
status: order.status,
billing: { email: order.customerEmail },
// Optional — only include what you actually have:
tracking_number: order.trackingNumber ?? undefined,
carrier: order.carrier ?? undefined,
status_description: order.carrierStatusText ?? undefined,
shipped_at: order.shippedAt?.toISOString(),
estimated_delivery: order.estimatedDelivery?.toISOString(),
});
});Shopify: Cart & Orders
Proxy requiredShopify's Ajax Cart API (/cart/add.js) expects { id: variantId, quantity }, but the ChatAxon widget always POSTs { product_id, quantity } to whatever URL you configure — the field name doesn't match, so you need a small proxy function rather than pointing addToCartUrl straight at Shopify.
Add to cart — proxy function
Deploy this as a small serverless function (Vercel/Netlify/Cloudflare Worker) on your own domain, then set cart.addToCartUrl to it. It forwards to Shopify's storefront using the customer's own session — the widget request must run through the shopper's browser (so it needs credentials: 'include', which the widget already sends).
// /api/shopify-cart-add.js — deployed on your own domain, proxied to Shopify
export default async function handler(req, res) {
const { product_id, quantity } = req.body; // product_id = Shopify variant ID
// (set this as the feed's product id for Shopify stores)
const shopifyRes = await fetch(`https://${process.env.SHOPIFY_SHOP_DOMAIN}/cart/add.js`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Cookie': req.headers.cookie ?? '' },
body: JSON.stringify({ id: Number(product_id), quantity }),
});
res.status(shopifyRes.ok ? 200 : 422).json({});
}window.ChatAxonConfig.cart = {
addToCartUrl: 'https://yourdomain.com/api/shopify-cart-add',
};Discount codes
Shopify has no same-domain endpoint to apply a code without a redirect. The simplest reliable option: leave cart.applyCouponUrl unconfigured so the widget copies the code to the clipboard, and tell shoppers to paste it at checkout — or redirect via /discount/{code}, which sets the code as a cookie Shopify auto-applies at checkout.
Order tracking on Shopify
Same contract as — a GET {store_url}/wp-json/wc/v3/orders/{orderId} endpoint with Basic Auth. For Shopify, that endpoint is a proxy function that queries the Shopify Admin API server-side:
// GET /wp-json/wc/v3/orders/:orderId (route this path on your own domain/proxy)
export default async function handler(req, res) {
// 1. Basic Auth check (same consumer key/secret as Connect Store)
const auth = Buffer.from((req.headers.authorization || '').split(' ')[1] || '', 'base64').toString();
if (auth !== `${process.env.CHATAXON_CONSUMER_KEY}:${process.env.CHATAXON_CONSUMER_SECRET}`) {
return res.status(401).end();
}
// 2. Query Shopify Admin API — order name e.g. "#1234"
const sfRes = await fetch(
`https://${process.env.SHOPIFY_SHOP_DOMAIN}/admin/api/2024-01/orders.json?name=%23${req.query.orderId}`,
{ headers: { 'X-Shopify-Access-Token': process.env.SHOPIFY_ADMIN_TOKEN } }
);
const { orders } = await sfRes.json();
const order = orders?.[0];
if (!order) return res.status(404).end();
const fulfillment = order.fulfillments?.[0];
res.json({
id: order.order_number,
status: order.fulfillment_status ?? order.financial_status ?? 'pending',
billing: { email: order.email },
tracking_number: fulfillment?.tracking_number,
carrier: fulfillment?.tracking_company,
});
}SHOPIFY_ADMIN_TOKEN is a private Admin API access token — it stays server-side in this function, never in the widget config.Real-time Webhook
Instant syncWhen products change on your platform, fire a POST to our webhook endpoint. ChatAxon immediately re-fetches your feed and re-indexes it — your AI assistant stays up to date within seconds.
Endpoint
POST https://api.chataxon.com/api/store/feed/webhook
Headers:
x-api-key: chataxon_YOUR_API_KEY
Content-Type: application/json
X-ChatAxon-Signature: <your_webhook_secret> # optional but strongly recommended
Body (all fields optional):
{
"event": "product.updated" // product.created | product.deleted | catalog.updated
}X-ChatAxon-Signature header is optional — if omitted, the request is still accepted when the API key is valid. If included, it must be the pre-computed HMAC-SHA256 hex value tied to your store. Retrieve it once from GET https://api.chataxon.com/api/store/feed/webhook-secret (authenticated with your API key) and store it as an environment variable on your server. Do not compute it per-request — just send the static value you retrieved.Get your webhook secret (one-time setup)
# Run once. Store the returned webhook_secret in your server's environment variables.
curl -s https://api.chataxon.com/api/store/feed/webhook-secret \
-H "x-api-key: chataxon_YOUR_API_KEY"
# Response:
# { "webhook_secret": "a3f1c8...64 hex chars..." }Accepted
Sync job queued successfully
Unauthorized
Invalid API key or signature
Unprocessable
No feed URL configured for this store
Rate limit
Max 20 calls per hour per API key. For catalogs that change frequently, batching is fine — the queue deduplicates rapid calls. If you exceed the limit, you receive a 429 Too Many Requests response.
Code examples
Replace chataxon_YOUR_API_KEY with your actual API key and CHATAXON_WEBHOOK_SECRET with the value returned by the /webhook-secret endpoint above.
# Set these in your environment first:
# CHATAXON_API_KEY=chataxon_YOUR_API_KEY
# CHATAXON_WEBHOOK_SECRET=<value from /api/store/feed/webhook-secret>
curl -X POST https://api.chataxon.com/api/store/feed/webhook \
-H "x-api-key: $CHATAXON_API_KEY" \
-H "X-ChatAxon-Signature: $CHATAXON_WEBHOOK_SECRET" \
-H "Content-Type: application/json" \
-d '{"event": "catalog.updated"}'CSAT Rating
OptionalShow a satisfaction prompt at the end of a conversation (👍 / 👎) and send the result to ChatAxon. The rating appears in your analytics dashboard under CSAT Score.
Fire the event from your widget UI (after the user clicks 👍 or 👎) using the POST /api/store/track endpoint:
Endpoint
POST https://api.chataxon.com/api/store/track
x-api-key: chataxon_YOUR_API_KEY
x-session-id: <current chat session UUID>
Content-Type: application/json
{
"event_type": "csat",
"metadata": {
"rating": "positive" // "positive" | "negative"
}
}JavaScript widget example
// Call this after showing the thumbs-up / thumbs-down prompt
async function sendCSAT(rating) {
await fetch('https://api.chataxon.com/api/store/track', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': window.ChatAxonConfig.apiKey,
'x-session-id': window.ChatAxon.getSessionId(), // exposed by the widget
},
body: JSON.stringify({
event_type: 'csat',
metadata: { rating }, // 'positive' | 'negative'
}),
});
}
// Wire up your buttons
document.getElementById('thumbs-up').addEventListener('click', () => sendCSAT('positive'));
document.getElementById('thumbs-down').addEventListener('click', () => sendCSAT('negative'));| Field | Required | Description |
|---|---|---|
| event_type | required | Must be exactly "csat" |
| metadata.rating | required | "positive" or "negative" |
x-session-id will be recorded but may skew averages — gate the prompt so it appears only once.Widget Embed
Non-WordPressAdd the ChatAxon chat widget to any website — no CMS required. Include the script tag before </body>.
<div id="chataxon-root"> must already be in the DOM before widget.js runs — it looks the element up once, synchronously, at load time (it does not wait for DOMContentLoaded). Placing the div and scripts together right before </body>, in this order, satisfies that.Minimal embed
<!-- ChatAxon Widget -->
<div id="chataxon-root"></div>
<script>
window.ChatAxonConfig = {
apiKey: 'chataxon_YOUR_API_KEY',
apiUrl: 'https://api.chataxon.com',
};
</script>
<script src="https://api.chataxon.com/widget.js" defer></script><link rel="stylesheet" href="…/widget.css">. The bundle renders into a shadow root and inlines its own styles there. Loading the stylesheet globally as well makes the shadow-DOM wrapper clone it into <head>while it also stays applied to your page, which has already collided with a host site's own Tailwind layer. The file is still served for older embeds; new integrations should leave it out.Full configuration
<script>
window.ChatAxonConfig = {
// Required
apiKey: 'chataxon_YOUR_API_KEY',
apiUrl: 'https://api.chataxon.com',
// Appearance
themeColor: '#1E364B', // hex color for buttons and accents
widgetPosition: 'bottom-right', // 'bottom-right' | 'bottom-left'
offsetBottom: 24, // pixels from bottom edge
offsetSide: 24, // pixels from side edge
// Mobile overrides (null = inherit from desktop)
mobileWidgetPosition: null,
mobileOffsetBottom: null,
mobileOffsetSide: null,
// Capabilities — REQUIRED to enable these features. Omit this object and
// the widget defaults both to false: order tracking and human handoff
// disappear with no error anywhere.
features: {
canWimo: true, // "where is my order" — needs Order Tracking API
canHandoff: true, // hand the conversation to a person
},
// Behaviour
defaultOpen: false, // open chat on page load
bubbleText: 'Need help?', // speech bubble above widget
welcomeMessage: 'Hi! How can I help you today?',
// Objects, not strings: label is the chip text, message is what gets sent.
// Entries missing either field as a string are dropped; max 8 chips.
quickReplies: [
{ label: 'Delivery & returns', message: 'What are your delivery and return terms?' },
{ label: 'Help me choose', message: 'Help me choose a product' },
],
// Visibility — 'everyone' (default) or 'admins' while you evaluate.
// See "Testing on a live site" below.
visibility: 'everyone',
// Internationalisation
currency: '€', // symbol passed to price display
// Cart adapter (optional) — see Cart Integration. Omit entirely on
// WordPress; the widget falls back to WooCommerce's own ajax cart.
cart: {
addToCartUrl: '/api/cart/add',
applyCouponUrl: '/api/cart/coupon', // optional
headers: { 'X-Session-ID': '...' },
},
};
</script>| Field | Required | Description |
|---|---|---|
| apiKey | required | Your chataxon_ store key (from the dashboard) |
| apiUrl | required | Always https://api.chataxon.com — also where /widget.js and /widget.css are served from |
| themeColor | optional | Hex color for the widget accent (#1E364B default) |
| widgetPosition | optional | "bottom-right" (default) or "bottom-left" |
| offsetBottom | optional | Pixels from bottom edge (default 24) |
| offsetSide | optional | Pixels from side edge (default 24) |
| mobileWidgetPosition | optional | Override position on mobile. null = use desktop setting |
| defaultOpen | optional | Open chat automatically on page load (default false) |
| bubbleText | optional | Short text in the speech bubble shown above the button |
| welcomeMessage | optional | First message shown in the chat window |
| currency | optional | Currency symbol used by the widget for price display only (default $). Not stored server-side — prices in the feed are used as-is. |
| features.canWimo | optional | Enables order tracking ("where is my order"). Needs one of the two endpoints in Order Tracking API wired first — switched on without one, the assistant gets a tool that cannot answer. Defaults to FALSE when the features object is omitted. |
| features.canHandoff | optional | Enables handing a conversation to a person. Also defaults to FALSE when features is omitted. The object is not merged with defaults — set both fields or the one you leave out stays off. |
| quickReplies | optional | Chips under the welcome message, as {label, message} objects — label is the button text, message is what is sent on click. Plain strings are ignored. Max 8; omit or pass an empty array to use the defaults for the widget language. |
| visibility | optional | "everyone" (default), or "admins" to keep the widget hidden until a page is opened with ?chataxon-preview=1 |
| cart.addToCartUrl | optional | See Cart Integration — enables non-WooCommerce add-to-cart |
| cart.applyCouponUrl | optional | See Discount Codes — omit to copy codes to clipboard instead |
apiKey is safe to include in client-side code. It is scoped to your store and only permits reading product data and sending chat messages — no write access.Testing on a live site without a staging domain
Set visibility: 'admins' and the widget stays dormant for everyone. Open any page with ?chataxon-preview=1 to reveal it; the browser remembers the flag so it survives navigation, and ?chataxon-preview=0 turns it off again. Switch to 'everyone' to launch.
https://yourstore.com/?chataxon-preview=1 # visible to you
https://yourstore.com/ # invisible to shoppers
https://yourstore.com/?chataxon-preview=0 # invisible to you toovisibility.Widget Settings API
Non-WordPressEverything under Appearance and Behaviour can come from your ChatAxon dashboard instead of being hardcoded, so changing the greeting, the accent colour or the quick replies does not need a deploy. This endpoint is also where the master on/off switch lives: turning the widget off in the dashboard returns widget_enabled: false, and your page should then skip the embed entirely.
const res = await fetch('https://api.chataxon.com/api/store/settings', {
headers: {
'x-api-key': 'chataxon_YOUR_API_KEY',
'x-store-url': window.location.origin,
},
});
const settings = await res.json();
if (settings.widget_enabled === false) return; // master switch is off
window.ChatAxonConfig = {
apiKey: 'chataxon_YOUR_API_KEY',
apiUrl: 'https://api.chataxon.com',
features: { canWimo: true, canHandoff: true },
currency: '€',
themeColor: settings.theme_color,
bubbleText: settings.bubble_text,
welcomeMessage: settings.welcome_message,
widgetPosition: settings.widget_position,
offsetBottom: settings.widget_offset_bottom,
offsetSide: settings.widget_offset_side,
defaultOpen: settings.default_open,
quickReplies: settings.quick_replies,
};| Field | Required | Description |
|---|---|---|
| widget_enabled | optional | Master switch from the dashboard. When false, do not embed the widget at all. |
| theme_color | optional | Hex accent colour |
| bubble_text | optional | Text in the speech bubble above the button |
| welcome_message | optional | First message in the chat window |
| widget_position | optional | "bottom-right" or "bottom-left" |
| widget_offset_bottom | optional | Pixels from the bottom edge |
| widget_offset_side | optional | Pixels from the side edge |
| default_open | optional | Whether the chat opens on page load |
| quick_replies | optional | Chips set in the dashboard, already in the {label, message} shape — pass straight through to quickReplies |
| isWhiteLabel | optional | Whether your plan removes the "Powered by ChatAxon" badge |
window.ChatAxonConfig. Values you set explicitly in the config always win, so you can pull most settings from the dashboard while pinning one or two in code.