Settings and features
Read your store's settings, discover writable fields, and apply a small patch. These endpoints use the Public API base URL, without the /chat prefix.
Who can use this feature?
API keys require Pro or Plus. Every request needs X-Api-Key: sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and the scope listed below. Legacy full-access keys do not grant these settings permissions; use a key with explicit scopes. Product Quiz and spam protection also need the store to be on Pro or higher.
Shared request and response rules
Send JSON with Content-Type: application/json on writes. Successful requests return HTTP 200. GET requests have no body. Read responses use data, except the field catalog, which returns fields and total. Settings PATCH responses return changed, an array of actual differences:
{
"changed": [
{"field": "enableLiveChat", "before": false, "after": true}
]
}An unchanged patch returns {"changed":[]}. A field that was not stored can omit before. Settings PATCH requests accept at most 50 fields. Use the field catalog to check types, enum values, ranges, and write permissions before sending a patch. Do not send an entire GET response as a widget patch.
The error table at the end applies to all endpoints below. All routes in this page use the Pro / Plus API-key access described above.
Widget settings
| Method | Path | Scope | Request | Response example |
|---|---|---|---|---|
| GET | /settings | settings:read | No body | {"data":{"enableLiveChat":true,"enableAIAssistant":false}} |
| GET | /settings/:domain | settings:read | Example: /settings/root | {"data":{"enableLiveChat":true,"enableAIAssistant":false}} |
| PATCH | /settings | settings.widget:write | {"enableLiveChat":true} | {"changed":[{"field":"enableLiveChat","before":false,"after":true}]} |
Read examples show a subset of stored fields. /settings returns public widget settings only; the collection endpoints below return the other settings. Missing stored fields are omitted rather than filled with catalog defaults.
Supported widget domains are root, appearance, aiAgent, availability, prechatContact, tracking, and internalFlags (inbox, team and email options). ai-agent and prechat-contact are accepted aliases. An unknown domain returns {"data":{}}.
Use flat V2 field paths for widget writes:
curl -X PATCH 'https://app.chatty.net/v1/settings' \
-H 'X-Api-Key: sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
-H 'Content-Type: application/json' \
-d '{"aiAgent.persona.name":"Store assistant"}'{
"changed": [
{"field": "aiAgent.persona.name", "before": "Assistant", "after": "Store assistant"}
]
}Object-valued fields are merged into the stored object: sending only {"aiAgent.storeAvailability":{"outOfStockMessage":"Ask us about stock"}} keeps the stored enabled value. Arrays inside them, and top-level arrays, are replaced.
Some widget fields have extra rules:
| Field | Rule |
|---|---|
aiAgent.pricing | Price display rules. display is label or hide; labelPhrase is Call for Price, Contact for pricing, Price on request or Request a quote; when.tags and when.productTypes hold up to 100 values of up to 200 characters. |
aiAgent.storeAvailability | Only enabled (boolean) and outOfStockMessage (up to 1,000 characters). |
internalFlags.emailSubjectTemplate | Up to 500 characters, using only the tokens page_name, customer_name, customer_email, shop_name, case_tag and status. "" restores the default. |
internalFlags.inbox.assignableMemberIds | IDs of members of this store. |
internalFlags.inbox.maxOpen | Whole number, 0 for no limit. |
internalFlags.enableSpamProtection | Turning it on needs Pro or higher, or the route returns 403 PLAN_LIMIT. Turning it off works on any plan. |
Enabling enableAIAssistant also enables enableLiveChat. Disabling enableLiveChat also disables the AI assistant. A patch that enables the AI assistant while disabling live chat fails with COUPLING_CONFLICT. The response includes coupled fields that actually changed.
Discover fields
GET /settings/fields — scope settings:read, Pro / Plus. Optional query parameters:
| Parameter | Meaning |
|---|---|
collection | Exact collection name, such as widgetSettings or similarMatchingSettings |
domain | Domain name; accepts the same aliases as widget reads |
q | Case-insensitive substring search across field paths and descriptions |
For example, request /settings/fields?collection=similarMatchingSettings with no body:
{
"fields": [
{
"collection": "similarMatchingSettings",
"domain": "shop",
"path": "similarMatchingSettings.forceSimilarByTags",
"type": "boolean",
"default": false,
"description": "Limits similar-product matching to configured priority tags.",
"affects": "agent-behavior",
"writeScope": "settings.shop:write",
"public": true
}
],
"total": 1
}The catalog lists 257 fields. A filter with no matches returns {"fields":[],"total":0}. A field without a writeScope is read-only. The catalog also contains fields owned by other resources; use the matching resource endpoint, not /settings, to write them.
Collection settings
Each GET below requires settings:read. Each PATCH requires its own scope. All use Pro / Plus. Read examples and object-valued before/after examples are excerpts: retain existing values when editing object settings.
| Method | Path | Scope |
|---|---|---|
| GET | /settings/shop | settings:read |
| PATCH | /settings/shop | settings.shop:write |
| GET | /settings/similar-matching | settings:read |
| PATCH | /settings/similar-matching | settings.shop:write |
| GET | /settings/notifications | settings:read |
| PATCH | /settings/notifications | settings.notifications:write |
| GET | /settings/satisfaction | settings:read |
| PATCH | /settings/satisfaction | settings.satisfaction:write |
| GET | /settings/product-quiz | settings:read |
| PATCH | /settings/product-quiz | settings.product-quiz:write |
| GET | /settings/faq-page | settings:read |
| PATCH | /settings/faq-page | settings.faq-page:write |
Collection writes accept the nested shape inside the GET response's data, or dotted catalog field names. Do not include the data wrapper. Do not supply the same field in both forms; that fails validation.
| Resource | GET response example | PATCH request example | PATCH response example |
|---|---|---|---|
shop | {"data":{"shopSettings":{"markets":[]}}} | {"shopSettings":{"markets":[]}} | {"changed":[]} when already empty |
similar-matching | {"data":{"similarMatchingSettings":{"forceSimilarByTags":false}}} | {"similarMatchingSettings.forceSimilarByTags":true} | {"changed":[{"field":"similarMatchingSettings.forceSimilarByTags","before":false,"after":true}]} |
notifications | {"data":{"notificationSettings":{"emails":[]}}} | {"notificationSettings":{"emails":["[email protected]"]}} | {"changed":[{"field":"notificationSettings","before":{"emails":[]},"after":{"emails":["[email protected]"]}}]} |
satisfaction | {"data":{"satisfactionSurveys":{"intro":"How did we do?"}}} | {"satisfactionSurveys":{"intro":"Rate your experience"}} | {"changed":[{"field":"satisfactionSurveys","before":{"intro":"How did we do?"},"after":{"intro":"Rate your experience"}}]} |
product-quiz | {"data":{"productQuizSettings":{"enabled":false}}} | {"productQuizSettings":{"enabled":true}} | {"changed":[{"field":"productQuizSettings.enabled","before":false,"after":true}]} |
faq-page | {"data":{"faqPageSetting":{"customUrl":"avada-faqs"}}} | {"faqPageSetting":{"customUrl":"store-faqs"}} | {"changed":[{"field":"faqPageSetting.customUrl","before":"avada-faqs","after":"store-faqs"}]} |
Arrays replace the previous array. In particular, an empty shopSettings.markets clears the market list, and an empty notification emails array clears recipients. Read first and send the complete intended array. Notification and satisfaction settings are object-valued catalog fields; their changed entries compare the whole stored object, including stored metadata. Object fields are merged into the stored object, as for widget writes.
- Product quiz needs the store on Pro or higher, or the PATCH returns
403 PLAN_LIMIT. Writable fields areenabled,collectionScope({"type":"all"}or{"type":"specific","collectionIds":[...]}),maxQuestions(3, 5 or 7),numRecommendations(1, 2 or 3) andintentTriggers(phrases that offer the quiz). - FAQ page accepts its content and appearance fields, such as
header,description, the color fields,theme,layout, banner fields andfaqPageCustomCss, as well ascustomUrland SEO fields.contactUstakesheaderandurl(up to 500 characters),description(up to 1,000),action(chatboxoranotherTab) anddisplay. A change is translated into your languages and published to the storefront. - Similar matching also accepts
similarityPriorityTags, a list of tags that is trimmed and kept to the first 50. Unset fields read as their defaults.
Use the field catalog for the full list of paths, types and defaults.
Shop preferences and store locations
| Method | Path | Scope | Request | Response example |
|---|---|---|---|---|
| GET | /settings/shop-preferences | settings:read | No body | {"data":{"emailFooterName":"Store support","hideChatLinkInEmail":false,"enableChatbox":true}} |
| PATCH | /settings/shop-preferences | settings.shop:write | {"enableChatbox":true} | {"changed":[{"field":"enableChatbox","before":false,"after":true}]} |
| GET | /settings/store-availability/locations | settings:read | No body | {"data":[{"id":"location_123","name":"Main warehouse","city":"Hanoi"}]} |
Shop preferences hold store-wide email and widget options. PATCH accepts any of these fields, and at least one:
| Field | Type |
|---|---|
emailFooterName | string, up to 500 characters |
emailReplyHint | string, up to 500 characters; Chatty translates it for your languages |
hideChatLinkInEmail | boolean |
showEmailSignature | boolean |
enableChatbox | boolean; updates the storefront widget |
pushOpenStandalone | boolean |
GET also returns emailSender, which is read-only. An empty body, an unknown field or a wrong type returns 400 VALIDATION_FAILED.
The locations route lists the store's active Shopify locations, so you can pick them for the AI agent's store availability answers (aiAgent.storeAvailability). city appears when the address has one. The list is cached for 10 minutes. If Shopify cannot be reached, the route returns 502 UPSTREAM_ERROR; retry later.
Market overrides
Use overrides to give a Shopify market a different AI name or shop name. Only aiAgent.persona.name and appearance.shopName can be overridden. Other settings continue to use their store-wide values.
| Method | Path | Scope | Request |
|---|---|---|---|
| GET | /settings/market-overrides | settings:read | No body |
| PUT | /settings/market-overrides/:marketId | settings.widget:write | Flat field patch; example below |
| DELETE | /settings/market-overrides/:marketId | settings.widget:write | No body |
All three routes use Pro / Plus. GET returns the markets, current overrides, and supported fields. Example excerpt:
{
"data": {
"markets": [{"marketId":"market_123","handle":"international","name":"International","primary":false}],
"overrides": [],
"overridableFields": ["aiAgent.persona.name", "appearance.shopName"]
}
}Replace market_123 with a marketId returned by GET. PUT merges the supplied fields into that market's existing override and leaves other markets unchanged:
PUT /settings/market-overrides/market_123
X-Api-Key: sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{"aiAgent.persona.name":"Store assistant"}{"success":true,"marketId":"market_123","updatedFields":["aiAgent.persona.name"]}PUT requires a known market and a nonempty patch. It returns MARKET_NOT_FOUND if the market is missing or the stored market list needs to be refreshed. Refresh the shop's market configuration before retrying.
DELETE /settings/market-overrides/market_123 removes that override so the market uses store-wide settings again:
{"success":true,"marketId":"market_123","removed":true}Deleting an absent override succeeds with removed: false.
Product recommendations
Recommendations tell the AI which products to suggest for given search terms. These routes use knowledge:read for reads and knowledge:write for writes, with a Pro / Plus key. Bodies and queries are strict: an unknown field returns 400 VALIDATION_FAILED.
| Method | Path | Scope | Request example | Response example |
|---|---|---|---|---|
| GET | /recommendations | knowledge:read | ?limit=20&sort=updatedAt_desc | {"data":[{"id":"rec_123","title":"Gifts","searchTerms":["gift"],"conditions":{"productIds":["123"]},"enabled":true,"isCustom":true}],"count":1,"pagination":{"hasPre":false,"hasNext":false}} |
| GET | /recommendations/{id} | knowledge:read | No body | {"data":{"id":"rec_123","title":"Gifts","enabled":true}} |
| POST | /recommendations | knowledge:write | {"title":"Gifts","searchTerms":["gift","present"],"products":["123"],"enabled":true} | 201 {"data":{"id":"rec_123","title":"Gifts","isCustom":true}} |
| PATCH | /recommendations/{id} | knowledge:write | {"searchTerms":["gift"]} | {"success":true} |
| DELETE | /recommendations/{id} | knowledge:write | No body | {"success":true} |
| POST | /recommendations/toggle | knowledge:write | {"ids":["rec_123","best_selling"],"enabled":false} | {"success":true} |
| GET | /recommendations/meta-tags/{metaTag} | knowledge:read | No body | {"data":{"metaTag":"best_selling","enabled":true,"smartSyncEnabled":true}} |
| PUT | /recommendations/meta-tags/{metaTag} | knowledge:write | {"smartSyncEnabled":false} | {"success":true} |
| GET | /recommendations/shopify-settings | knowledge:read | No body | {"data":{"enableRelated":true,"enableComplementary":true}} |
| PATCH | /recommendations/shopify-settings | knowledge:write | {"enableComplementary":false} | {"success":true} |
Examples are excerpts.
- Create and update.
titleis required on creation (1–500 characters).searchTermsholds up to 50 terms.productsandcollectionsare lists of up to 1,000 IDs; they are stored inconditions.productIdsandconditions.collectionIds. PATCH needs at least one field and mergesconditionswith the stored value. - List.
limitis 1–100 (default 20).sortisupdatedAt,createdAtortitlewith_ascor_desc(defaultupdatedAt_desc). Page withafter(the last ID of this page) orbefore.hasCount=trueaddstotalandpagination.totalPage. Only your own recommendations are listed. - Templates.
special_occasionsandsale_promotionare built-in templates. GET returns the template until you save it; PATCH saves it with your changes; DELETE hides it. - Toggle. Turns up to 200 recommendations, templates or meta tags on or off at once. If any ID is unknown, nothing changes and the route returns
404 NOT_FOUND. - Meta tags.
best_sellingandnewestare the two supported tags; any other value returns404 NOT_FOUND. A tag that was never saved starts withenabledandsmartSyncEnabledset totrue; reading it saves those defaults. - Shopify settings.
enableRelatedandenableComplementaryturn Shopify's related and complementary product suggestions on or off. Unset values read astrue.
An unknown or foreign recommendation ID returns 404 NOT_FOUND. Every write is recorded in the audit log.
Feature toggles
Features group the setting fields needed for one capability. Use these endpoints when you want to turn a capability on or off without assembling its patch yourself.
| Method | Path | Scope | Request |
|---|---|---|---|
| GET | /features | settings:read | No body |
| GET | /features/:key | settings:read | Example: /features/live_chat; no body |
| POST | /features/:key/enable | settings.widget:write | Example: /features/live_chat/enable; no body |
| POST | /features/:key/disable | settings.widget:write | Example: /features/live_chat/disable; no body |
All four routes use Pro / Plus. Available keys:
| Key | Setting fields |
|---|---|
ai_assistant | enableAIAssistant |
live_chat | enableLiveChat |
faq_lookup | aiAgent.knowledge.enableFaqs |
product_lookup | aiAgent.knowledge.enableProducts |
shipping_quote | aiAgent.knowledge.enableShippingQuote |
discounts | aiAgent.knowledge.enableDiscounts, aiAgent.knowledge.discountsAutoSync |
multi_currency | aiAgent.knowledge.enableMultiCurrency |
order_tracking | aiAgent.scenarios.enableOrderTrackingTool |
after_sale_support | aiAgent.scenarios.enableAfterSaleSupport |
human_agent_transfer | aiAgent.scenarios.enableHumanAgentRequest |
size_guide | aiAgent.scenarios.enableSizeGuide |
follow_up_questions | aiAgent.enableFollowUpProductQuestions, aiAgent.scenarios.followUp.enabled |
ai_mode | Shop field enableAiMode |
GET /features/live_chat returns:
{"data":{"key":"live_chat","enabled":false,"fields":["enableLiveChat"],"settings":{"enableLiveChat":false}}}GET /features returns data as an array of these objects, one per key. A multi-field feature is enabled only when all of its fields are true.
POST /features/live_chat/enable, when live chat was off, returns:
{"changed":[{"field":"enableLiveChat","before":false,"after":true}]}POST /features/live_chat/disable, when live chat was on and the AI assistant was already off, returns:
{"changed":[{"field":"enableLiveChat","before":true,"after":false}]}The AI/live-chat coupling described above also applies to these actions. ai_mode changes the shop field enableAiMode and returns the same changed format. An unknown key returns 404 NOT_FOUND.
Errors
Error responses use {"error":{"code":"…","message":"…"}}, optionally with details. See Errors and rate limits for shared version and rate-limit behavior.
| HTTP | Code | Applies to / action |
|---|---|---|
| 401 | UNAUTHENTICATED, INVALID_API_KEY | All routes: provide a valid X-Api-Key |
| 403 | FORBIDDEN | All routes: grant the required scope |
| 403 | FIELD_NOT_PERMITTED | Settings, feature, and override writes: unknown, read-only, wrong-collection, or non-overridable fields |
| 400 | VALIDATION_FAILED | Writes: invalid types, enum values, ranges, conflicting nested/dotted fields, or more than 50 PATCH fields |
| 400 | VALIDATION_ERROR | Widget/feature writes: invalid field-specific values |
| 400 | MISSING_PARAMS | Empty widget patch or market-override patch; missing required override identifier |
| 400 | COUPLING_CONFLICT | Widget/feature writes: conflicting AI and live-chat settings |
| 403 | PLAN_LIMIT | Product Quiz writes, or turning on spam protection, below Pro |
| 502 | UPSTREAM_ERROR | Store locations could not be loaded from Shopify; retry later |
| 404 | MARKET_NOT_FOUND | Override PUT: market is not available in the shop's stored market list |
| 404 | NOT_FOUND | Unknown feature key, missing shop for AI Mode, missing widget settings during an override write, or an unknown recommendation or meta tag |
| 429 | RATE_LIMITED | All routes: wait before retrying |
| 500 | INTERNAL_ERROR | Unexpected failure; retain the response for support |
A validation error can identify each rejected field:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "One or more settings fields are invalid",
"details": {
"fields": [{"field":"enableLiveChat","code":"INVALID_TYPE","expected":"boolean"}]
}
}
}MCP and audit records
MCP exposes widget patches through update_settings, collection updates through update_settings_resource, shop preferences through update_shop_preferences, market overrides through manage_market_overrides, feature changes through set_feature, and recommendations through manage_recommendations. get_settings_resource reads shop preferences (shop_preferences) and store locations (store_availability_locations). Each tool/action enforces the same scope as its REST operation. Settings, preference, override and recommendation writes carry the authenticated actor into mutation audit records, including failed attempts; clients do not supply their own actor identity. See MCP tool reference for inputs and authentication availability.
Chatty Help Center