Askagento API
Install, uninstall, status, recommendations, search, chatbot, BYOK, label, filter, MCP, plan, usage, revenue attribution.
AI Agents & MCP
MCP 2024-11-05 over HTTP. Every request is a JSON-RPC 2.0 POST.
Supported methods:
initialize— server capabilities and protocol version.notifications/initialized— acknowledged silently (empty 200 body).tools/call— execute a tool (see tool list below).tools/list— catalogue of available tools.
tools/call tools (alphabetical):
chat_with_shop— conversational shop assistant (message, optionalhistory); delegates toPOST /chatbotwithaction=chat(product retrieval + LLM). Debitslimits.tokenslike/chatbot.get_catalogue_stats— orientation summary: total and published product count, price range, number of distinct categories and tags, featured and on-sale counts (no arguments). Reads the stored S3 catalogue; no quota debit.get_featured_products— curated product list:list_typeone offeatured(merchant-starred),on_sale(active discounts), ornew_arrivals(sorted bydate_createddescending);limit1–50 (default 12). Reads the stored S3 catalogue; no quota debit.get_product_by_id— full detail for one product by numericproduct_id: title, URL, image, price, categories, tags, description (up to 400 chars). Reads the stored S3 catalogue; no quota debit.get_shop_status— install status, plan, and remaining usage quotas (no arguments).get_similar_products— cross-sell and/or upsell neighbors for oneproduct_id(optionalrecommendation_type,limit). Reads the same precomputed similarity bundle as/recommend/*(install-time catalogue similarity index, no LLM); no quota debit.list_categories— all product categories in the catalogue with name, slug, and product count. No quota debit.list_tags— all product tags in the catalogue with name, slug, and product count. No quota debit.search_products— semantic search bytext,image, orboth(textand/orimage_base64, optionalmodality,limit); debitslimits.searcheswhen tracked.
Successful tool calls and protocol errors (initialize, unknown method, etc.) return HTTP 200 with a
JSON-RPC 2.0 body. Auth and site lookup failures also use HTTP 200 with JSON-RPC error objects
(codes -32001 unauthorized, -32004 site not found) so MCP clients can always parse the envelope.
HTTP 400 is reserved for a non-JSON or non-JSON-RPC request body at the transport layer.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> can be the public key or the secret key; use the public key in browser code and AI agent configs.
AI Agents & MCP › Request Body
jsonrpcmethodOne of: initialize, notifications/initialized, tools/call, tools/list
Request id (omit for notifications)
For tools/call: {"name": "chat_with_shop"|"get_catalogue_stats"|"get_featured_products"|"get_product_by_id"|"get_shop_status"|"get_similar_products"|"list_categories"|"list_tags"|"search_products", "arguments": {...}}
AI Agents & MCP › Responses
JSON-RPC 2.0 response (result or error)
jsonrpcerrorAI Chatbot
Sends a conversation to a configured chat model.
action=chat — The last user message drives semantic product search against the site's
catalogue (up to 12 matches). Matching products are injected as a system message before the LLM
request. Retrieval does not debit limits.searches. If search or catalogue load fails, the chat
continues without product context.
action=health — Minimal connectivity check: messages is ignored, completion is capped
at 3 tokens, and products_retrieved is always 0. Upstream usage.total_tokens is still
debited from limits.tokens when that limit is tracked (typically a few tokens), unless BYOK
is active (see below).
BYOK — If the site has a merchant key stored via POST /byok, that key is used instead of
the shared AskAgento LLM credentials. Token preflight and limits.tokens debit are skipped
while BYOK is active (usage.billed_tokens is 0).
Token preflight (429 when limits.tokens is present and <= 0) applies when BYOK is not active.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> can be the public key or the secret key; use the public key in browser code and AI agent configs.
AI Chatbot › Request Body
actionchat — full conversation; last user turn drives product retrieval (see POST /chatbot).
health — connectivity probe; messages optional and ignored; max_completion_tokens ignored.
Required when action=chat (non-empty after normalization); omitted or ignored for health. Up to 24 turns; each content truncated to 12 000 chars.
max_completion_tokensAlias max_tokens also accepted; capped at 4096. Ignored when action=health (server uses 3).
Optional. The product page the shopper is asking from (AI Assistant). Its synced details (price, attributes, variants, description) are given to the assistant, so questions like "is it waterproof?" are answered about that product. Ignored when the product is not in the last catalogue sync.
AI Chatbot › Responses
Chat reply with usage and limit information
site_idactionlatency_msRound-trip latency to the chat provider in milliseconds
replyText reply from the model
products_retrievedNumber of catalogue products injected as context for action=chat; always 0 for health
limits_tokens_remainingRemaining token quota for the site after this call; null if no quota is set
AI Recommend (cross-sell)
Precomputed cross-sell recommendations for the registered catalogue (stored in object storage). Built during installation from install-time catalogue similarity indexes (no LLM).
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
AI Recommend (cross-sell) › Responses
Recommendations JSON from object storage
site_idgenerated_atISO 8601 timestamp (UTC) with Z suffix
Map of source product id to cross-sell targets (similarity-ranked)
Map of source product id (string) to ranked neighbor list
AI Recommend (upsell)
Precomputed upsell recommendations for the registered catalogue (stored in object storage). Built during installation from install-time catalogue similarity indexes (no LLM).
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
AI Recommend (upsell) › Responses
Recommendations JSON from object storage
site_idgenerated_atISO 8601 timestamp (UTC) with Z suffix
Map of source product id to cross-sell targets (similarity-ranked)
Map of source product id (string) to ranked neighbor list
AI Search
Search endpoint for text, image and voice search.
Omit modality to infer from the body: text only → text, image_base64 only → image,
both present → both, audio_base64 only → voice. Setting both requires text (≥2 chars) and image_base64.
Prefer setting modality explicitly for MCP contracts so the search mode is declared rather than inferred.
Voice search (modality: voice): send a short spoken query as audio_base64 — a WAV file,
16-bit PCM, mono, 8–48 kHz (16 kHz recommended), at most 15 seconds — and optionally language
(e.g. en-US, de_DE, fr; default en-US). The speech is converted to text and searched like a
typed query; the response echoes it as transcript.
Each successful text, image or hybrid search debits one from limits.searches when that limit is tracked.
A voice search debits 100 (speech-to-text is metered per second of audio), including when no speech
is recognized. Monthly searches are spent first, then add-on pack searches. When fewer than 100 remain,
a voice search returns 429 before any audio is processed.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> can be the public key or the secret key; use the public key in browser code and AI agent configs.
AI Search › Request Body
textSearch text, at least 2 characters
image_base64Base64-encoded image bytes. A leading data:image/...;base64, prefix is stripped if present. Never fetched over the network.
audio_base64Voice query: base64-encoded WAV (16-bit PCM, mono, 8–48 kHz, ≤15 s). A leading data:audio/...;base64, prefix is stripped if present. Costs 100 searches.
languageSpoken language for voice (e.g. en-US, de-DE, de_DE, fr). Default en-US.
modalityOmit to infer from the body: text only → text, image_base64 only → image,
both present → both, audio_base64 only → voice. Setting both requires text (≥2 chars) and image_base64.
limitmerchandiseApply the shop's merchandising (see POST /merchandising). Set false when your own code reorders the results.
AI Search › Responses
Ranked product hits
site_idmodalityqueryEchoed text query when modality is text or both; the transcript for voice
transcriptVoice only. Recognized speech that was searched (may be empty).
languageVoice only. Spoken language used for recognition (e.g. en-US).
search_credit_costVoice only. Searches debited for this request (100).
Present when the shop redirects this text or voice search to a page; results is then empty. Open redirect.url instead of showing results.
Autocomplete
Product suggestions for a search box, meant to be called while a shopper types (debounced, from the
2nd character). Each typed word must match the start of a word in the product title, category, tag,
attribute value or SKU; one typo is tolerated in words of 4 or more letters, and words no product
contains (e.g. "need" in "i need watch") are left out. The shop's synonyms (POST /merchandising)
widen the match. No AI is involved and suggestions are not counted against limits.searches;
run POST /search for the full AI search (e.g. on Enter).
Besides products, the answer lists popular searches that continue the typed text and the shop's
search redirect for it, if any (the redirect also matches a redirect phrase that starts with the
typed text, from 3 characters). An empty q (the shopper focused the empty search box) answers with
trending searches of the last 7 days and the shop's best sellers.
Suggestions come from the catalogue of the latest sync (POST /install or POST /update). Answers
may be cached by the browser for 60 seconds. A 1-character query returns nothing.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> can be the public key or the secret key; use the public key in browser code.
query Parameters
qWhat the shopper has typed so far (trimmed and lower-cased; at most 100 characters are used). Empty for trending searches and best sellers.
limitMaximum number of products (1–10, default 6).
Autocomplete › Responses
Matching products (best first), popular searches and the search redirect
site_idqueryThe query as matched (trimmed, lower-cased).
searchesPopular searches that continue the typed text (most frequent first); for an empty q, the trending searches of the last 7 days.
Auto Filter
Auto Filter pipeline (no LLM). analyze lists attribute names found in the synced catalog;
generate echoes the merchant-selected canonical_filters; upload stores the selection on the catalog snapshot.
Accepts action or filter_action (analyze, generate, upload, export). Optional canonical_filters
is an alias for canonical_attributes.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Auto Filter › Request Body
actionfilter_actionAlias for action; supply either action or filter_action.
canonical_filtersAlias for canonical_attributes when generating attribute filters.
Auto Filter › Responses
Filter action result (analyze / generate / upload / export).
site_idmodeactionAuto Label
Loads the site's product JSON, then runs analyze (suggest canonical names), generate (LLM proposals stored on products and catalogue), upload (persist generated labels into the catalogue in object storage), or export (download-ready payload). Debiting token quota uses the same mechanism as chat/search.
Modes: attributes, categories, tags. Actions: analyze, generate, upload, export.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Auto Label › Request Body
modeactioncanonical_attributescanonical_categoriescanonical_tagsAuto Label › Responses
Success shape varies by mode and action (counts, previews, keys, catalogue upload status).
site_idmodeactionBring-your-own-key (BYOK) LLM credentials
Store or clear a merchant-supplied OpenAI or OpenRouter API key on the install record.
When a BYOK key is stored, POST /chatbot uses that key for inference and does not
debit limits.tokens (the merchant pays their provider directly). Clearing removes the
key and restores the shared AskAgento LLM path with normal token metering.
Providers: openai, openrouter only (OpenAI-compatible chat completions).
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Bring-your-own-key (BYOK) LLM credentials › Request Body
actionset stores the merchant key; clear removes BYOK credentials from the install record.
providerRequired when action=set.
api_keyMerchant LLM API key. Required when action=set. Never logged by the API.
modelOptional model id for action=set (e.g. gpt-5-mini for OpenAI, or an OpenRouter
model id). When omitted, the chatbot uses the server default (OpenRouter ids are
prefixed with openai/ when needed).
Bring-your-own-key (BYOK) LLM credentials › Responses
BYOK config stored or cleared
statussite_idbyokTrue when a BYOK key is stored after this request; false after clear.
providerPresent when byok is true (the provider just stored).
Current subscription plan
Returns the current plan slug and display label for the site. Every API capability is available on every plan; the plan sets catalogue capacity and included monthly usage only.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Current subscription plan › Responses
Plan response
site_idplanPlan slug (free, basic, pro); null if no plan is set
plan_labelHuman-readable plan label
Installation status
Retrieve installation metadata.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Installation status › Responses
Install status response
site_idinstalled_atstatus_messagestatusInstall plugin
Install the plugin.
Local (test) shops. A shop our servers cannot reach (localhost, .local,
.test and similar names, private IP addresses, or a name that does not resolve
publicly) installs in local mode, for testing:
- at most 100 products (
403,local_too_many_productsotherwise); - each product's main image is sent inline as
image_base64(JPEG, PNG, WebP or GIF, at most 512 KB decoded; the plugin sends about 300 px JPEGs), because the service cannot download images from the shop. Without any readable image the install is rejected with422(no_product_images); - variation images are not indexed;
- the catalogue is never re-indexed automatically:
POST /updatekeeps the stored product data current, but changes reach search only after a reinstall.
Whether a shop is local is decided by the service from domain. Inline images
from a shop that turns out to be reachable are ignored and its images are
downloaded as usual.
Install plugin › Request Body
domainsystemwoocommerce — full catalogue with image + text data.
knowledge_base — text-only Confluence/article chunks for askagento.com chat.
plugin_versionwoocommerce_versiontotal_productsshop_ipOptional IPv4 string for the shop host (plugin may send DNS resolution result).
Install plugin › Responses
Installation accepted for async processing
statussite_idNew site identifier; send it in X-Askagento-Site-Id on every authenticated call.
api_keySecret key; accepted on every authenticated route. Keep it on your server and never expose it in a web page.
public_keyPublic key; accepted only on POST /chatbot, GET /suggest, POST /search and POST /mcp. Safe to embed in storefront pages and AI agent configs.
messageInstall verify
Check that a shop can be reached from our servers before sending its catalogue to
POST /install.
Installation reads product pages and images directly from the shop, so a shop that is local, resolves to a private address, or refuses image requests cannot be installed. Calling this first turns that into an immediate, explainable answer instead of a failure part-way through installation.
Send the shop domain and the URL of one product image. The check is a name check, a DNS lookup, and a single image fetch, so it returns in about a second.
verdict is one of:
pass— proceed withPOST /install.blocked— the install cannot succeed as configured;reasonsays why.inconclusive— the shop could not be judged (timeout, rate limit). Offer a retry rather than treating it as a failure.
A blocked verdict is a normal, successful response: the check ran and the answer
is no. Only malformed requests return 4xx.
code | verdict | Meaning |
|---|---|---|
reachable | pass | The shop and its product images can be read. |
local_domain | blocked | A local development address (localhost, .local, .test). |
private_ip | blocked | The domain resolves to a private address. |
dns_unresolved | blocked | The domain does not resolve on the public internet. |
tls_invalid | blocked | The shop's certificate could not be verified. |
password_protected | blocked | The shop asks our servers for a password. |
image_forbidden | blocked | Image requests are refused (hotlink protection or a firewall). |
no_product_images | blocked | No product has an image; products are indexed by their images. |
connection_refused | blocked | The shop refused the connection. |
tls_error | blocked | The TLS handshake with the shop failed. |
unsupported_scheme | blocked | The image URL is not http or https. |
non_standard_port | blocked | The image URL uses a port other than 80 or 443. |
invalid_domain | blocked | No usable shop domain was supplied. |
image_not_found | inconclusive | The sampled image 404s, but the shop answered. |
image_not_an_image | inconclusive | The image URL returned a page, not an image file. |
rate_limited | inconclusive | The shop rate-limited the request. |
timeout | inconclusive | The shop did not answer in time. |
network_error | inconclusive | The shop could not be contacted. |
shop_error | inconclusive | The shop returned a 5xx for the sampled image. |
unexpected_status | inconclusive | The image returned an unexpected status. |
bad_redirect | inconclusive | The shop redirected without a destination. |
too_many_redirects | inconclusive | The image URL redirected too many times. |
Treat unknown codes by their verdict — codes may be added.
No API key: this runs before POST /install issues one.
Install verify › Request Body
domainShop host name, e.g. shop.example.com. A full URL is also accepted.
image_urlURL of one product image, picked at random from the catalogue about to be
installed. Products are indexed by their images, so a catalogue without
one cannot be installed: omitting it yields blocked
(no_product_images).
Install verify › Responses
Reachability verdict (including blocked, which is a normal result)
okTrue only when verdict is pass.
verdictcodeMachine-readable outcome, e.g. reachable, local_domain, private_ip,
dns_unresolved, tls_invalid, password_protected, image_forbidden,
image_not_found, no_product_images, rate_limited, timeout.
reasonSentence suitable for display to the shop administrator.
localTrue when the shop is local (local_domain, private_ip, dns_unresolved):
it can still install in local mode with up to local_max_products products
and its product images sent inline (see POST /install).
local_max_productsPer-check detail, in the order the checks ran.
Lost-demand insights
What shoppers asked for and did not find, over the last days full UTC days
(at most 30; today is not included).
searches— AI text searches whose best product match was too weak (or that found nothing), grouped by identical wording, most frequent first.chat_topics— chatbot questions grouped into topics such as "Ring sizing".unmatchedcounts the questions for which no matching product was found.chat_topics_sourceisaiwhen topics were grouped by the AI model,exactwhen only identical questions could be grouped,nonewithout chat questions.
Only queries and topics asked at least twice are listed (up to 50 each). Email addresses, URLs and long numbers (phone or order numbers) are removed from the text before it is stored. Figures are rebuilt once a day shortly after midnight UTC.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
query Parameters
daysLost-demand insights › Responses
Lost-demand report
site_iddaysfromtodata_daysDays in the window with any search or chat activity.
chat_topics_sourceReport a storefront session
Sent from the storefront once when a shopper session starts and once more when that
session first uses AskAgento (search, chatbot or an AI recommendation), with
ai: true. Each session_id is counted once; a session becomes AI-engaged at most
once. These counts are the denominators of the conversion rates in
GET /attribution/summary. session_id is a random identifier; it carries no
personal data.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> may be the public key or the secret key.
Report a storefront session › Request Body
session_id^[A-Za-z0-9_-]+$ · requiredaiReport a storefront session › Responses
Session recorded
statusresultReport an order
Called from the shop's server when an order is paid, and again if it is later refunded
or cancelled. A paid order is counted once per order_id (repeat reports return
result: duplicate). A refunded or cancelled report takes a previously counted
order back out of the day it was paid (result: reversed), or does nothing
(result: not_found). Include attribution only when the shopper reached the order
through AskAgento. Send no customer personal data.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Report an order › Request Body
statustotalOrder total (required when status is paid).
currencypaid_atUnix time the order was paid (defaults to now; at most ~13 months old).
Report an order › Responses
Order recorded
statusresultorder_idRevenue attribution summary
Revenue influenced by AskAgento for the last days days (UTC, today included), read
from daily figures kept up to date as orders and sessions are reported. An order is
AskAgento-assisted when the shopper clicked a product in AI search, the chatbot or an
AI recommendation within the shop's attribution window before checking out.
ai_aov/site_aov— average order value of assisted orders vs. all orders.ai_conversion_rate— assisted orders per AI-engaged session.baseline_conversion_rate— other orders per session without AI engagement.roi_multiple— assisted revenue divided byplan.period_cost;nullon the free plan or when the plan is billed in a different currency than the orders.
plan is what the site pays for AskAgento, read from its Stripe subscription
(price, interval and active coupons, cached up to an hour) and spread over the
window as period_cost. It is null when the cost cannot be determined.
Ratios are null when their denominator is zero. Refunded and cancelled orders are
removed from the day they were paid.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
query Parameters
daysRevenue attribution summary › Responses
Attribution summary
site_iddaysfromtocurrencyISO 4217 code of the reported order totals.
tracking_sinceFirst day with any attribution data for this site.
planSave merchandising
Stores the shop's merchandising: search rules that pin, boost or bury products, whether
out-of-stock products go last, and ranking weights that blend shop data into the search
ranking. Each call replaces the stored settings. They are applied to /search, /chatbot,
/mcp and the AskAgento app for ChatGPT.
Out-of-stock status and the ranking signals (sales, average rating, on sale, newness) come from the catalogue the shop last synced.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Save merchandising › Request Body
Search rules, applied in order; when a product appears in several matching rules, the earliest rule decides. Rules with no phrases or no products are ignored.
out_of_stock_lastMove out-of-stock products below in-stock ones. They are not removed.
0 (ignored) to 10 (counts as much as how well a product matches the search). Omitted signals are 0.
Words that mean the same in this shop. They are added to the search text of /search (text, voice, text + image), the chatbot and agents, and widen /suggest.
Searches that open a page instead of showing results. /search answers a text or voice search matching one with redirect and no results (a redirected text search is not counted against limits.searches); /suggest lists the redirect while typing.
Save merchandising › Responses
Merchandising saved
statusrulesNumber of search rules stored
out_of_stock_lastsynonymsNumber of synonym groups stored
redirectsNumber of search redirects stored
Uninstall plugin
Uninstall the plugin and remove all indexed data for the site.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Uninstall plugin › Request Body
systemdomainplugin_versionwoocommerce_versionUninstall plugin › Responses
Uninstall completed
statusUpdate product data
Push the shop's current product catalogue for an installed site (scheduled or manual sync). Stores product JSON in object storage and updates the install record's product-data hash.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Update product data › Request Body
systemdomainplugin_versionwoocommerce_versiontotal_productsUpdate product data › Responses
Product data accepted
statussite_idsynced_productsupdate_neededTrue when the catalogue hash changed on this sync (re-embed required). Unchanged-hash syncs do not clear a previously true flag.
messageUsage limits
Returns the current plan, remaining per-site limits (tokens, searches), the tier-level
maximums, and the catalogue product count against the number of products the plan
indexes. Every API capability is available on every plan; a plan sets only catalogue
capacity and included monthly usage. When the catalogue is larger than the plan
indexes (over_product_limit: true), catalogue-backed endpoints return 403 with
code: product_limit_exceeded until the catalogue is covered by a larger plan or
reduced in size.
Authentication: Send X-Askagento-Site-Id: <site_id> and X-Askagento-Api-Key: <api_key> headers. <api_key> must be the secret key; the public key is rejected with 401.
Usage limits › Responses
Usage response
site_idplanPlan slug; null if no plan is set
plan_labelRemaining monthly plan allowance for this site; null if no limits are tracked. Reset to the tier maximum each billing period. Does not include add-on packs.
Unspent one-time add-on pack credits, omitted keys meaning zero; null when the site has none. These do not expire and are only spent once limits reaches zero, so the site's true remaining balance is limits + pack_units.
Tier-level maximums for the current plan; null if no plan is set. Includes a products field (how many products the plan indexes) in addition to tokens/searches.
product_countNumber of products in the shop's catalogue; null if not yet recorded
max_productsNumber of products the service indexes on the current plan; null if no plan is set.
over_product_limitTrue when the catalogue is larger than the current plan indexes. While true, catalogue-backed endpoints return 403 (code: product_limit_exceeded) until the catalogue is covered by a larger plan or reduced in size.