Responses & Errors
This page covers the behaviour that every endpoint under
https://ecom.marqo-ep.ai/api/v1 shares: which credential to send, what an
error looks like, which response headers to expect, how caching works, and the
limits that apply. Endpoint-specific parameters and responses are on each
endpoint's own page.
Authentication
There are two credentials. Every request needs exactly one of them. Sending both changes how the request is authenticated, so see Sending both credentials before you do.
| Credential | Header | Use it for |
|---|---|---|
| API key | Authorization: Bearer {api_key} | Every endpoint. Required for management endpoints (index configuration, adding and updating products, jobs, profiles, analytics, webhooks). Keep it server-side. |
| Index ID | x-marqo-index-id: {index_id} | Shopper-facing endpoints only: search, composite search, collections, get documents, instant search, recommendations, reverse image search and the agentic discovery endpoints that support it. Safe to ship in storefront code. |
The index ID is not a secret. It identifies the index and grants read-only access to the shopper-facing endpoints, so it can be embedded in a website or mobile app. Your API key must never appear in client-side code. Find both in the Marqo Console (see Find Your API Key).
Notes on the Authorization header:
- The
Bearerprefix is optional.Authorization: {api_key}is accepted. - The prefix is case-sensitive.
bearer {api_key}is not recognised and the request fails with401. - An empty value returns
401.
The credential also decides which product fields you get back. API key callers receive every stored field of a product. Index ID callers receive only the fields allowed for storefront display, as configured for the index. If a field you expect is missing from a storefront response, check the index's field settings rather than the request.
Sending both credentials
Send one credential per request. If a request carries both x-marqo-index-id
and Authorization, the index ID authenticates it and the API key is never
validated. Two consequences follow:
- A key that is unknown or has been revoked does not return
401 Failed to authenticate API key. It is forwarded to the search engine as supplied, and any rejection comes back as a search engine error such asSearch failed: .... - Field filtering is switched off by the presence of the header alone, so the response carries every stored field rather than the fields configured for storefront display.
An empty Authorization value is still rejected with 401 even when
x-marqo-index-id is present.
This matters most when storefront code reuses an HTTP client that was set up for
server-side calls. Strip the Authorization header from requests you make from
a browser.
Error envelope
Every error response has Content-Type: application/json and a body with a
single error key:
{
"error": "Invalid JSON payload"
}
Management endpoints validate request bodies against a schema. When that
validation fails they return 422 and error holds an array of validation
issues instead of a string:
{
"error": [
{
"type": "literal_error",
"loc": ["body", "metricSets", 0],
"msg": "Input should be 'request_latency', 'index_stats' or 'jobs'",
"input": "latency",
"ctx": { "expected": "'request_latency', 'index_stats' or 'jobs'" }
}
]
}
Status codes
| Status | error message | When |
|---|---|---|
400 | Invalid JSON payload | The request body is not valid JSON. |
400 | Unrecognized param(s): 'a', 'b' | The body contains fields the endpoint does not accept. Only endpoints with strict bodies return this; see Unknown fields. |
400 | 'limit' + 'offset' must not exceed 10000 | Search-family request paging past the result window. See Limits. |
400 | Endpoint-specific | Other request validation, for example a missing required parameter. The message names the parameter. |
401 | Unauthorized | No credential was sent, the Authorization value is empty, or the credential is not recognised as a valid token. |
401 | Failed to authenticate API key | An API key was sent but it is unknown or has been revoked. |
403 | Insufficient API key scope | An agentic discovery endpoint rejected the key because its scope is too narrow. |
403 | This operation requires a read-scoped API key. | A management endpoint that enforces scope rejected the key. The message names the scope needed, one of read, read_write or admin. |
404 | Marqo settings not found for shop {system_account_id}-{index_name} | The index does not exist, belongs to a different account than the API key, or is not ready to serve requests yet. This is the 404 for a misspelled index name and for a newly created index that is still being provisioned, on both shopper-facing and management endpoints. |
404 | Endpoint-specific | A feature that is not enabled for the index, or a record that does not exist. |
422 | 'useDynamicFacets' and 'facets' cannot both be set | Search-family request that sets both. |
422 | 'disableMerchandising' must be a boolean | Search-family request where disableMerchandising is not true or false. |
422 | Array of validation issues | Management endpoint schema validation, as shown above. |
429 | See Reverse Image Search | Only reverse image search is rate limited. The 429 body has a different shape. |
500 | Internal server error | Unexpected failure. Retry, and contact support if it persists. |
502 | Bad gateway | A backing service could not be reached. Safe to retry. |
503 | Service misconfigured | The API is temporarily unable to serve requests. Retry later. |
Scope is not yet enforced on every endpoint. See Find Your API Key for where it applies today.
Errors from the search engine
When the search engine rejects a request, its status code is returned as-is and its message is prefixed with the operation that failed:
| Prefix | Endpoints |
|---|---|
Search failed: … | Search, composite search, collections, instant search, for-you recommendations |
Get documents failed: … | Get documents |
Suggestions failed: … | Search suggestions |
Similar recommendations failed: … | Similar recommendations |
Complementary recommendations failed: … | Complementary recommendations |
Complete-the-look recommendations failed: … | Complete-the-look recommendations |
Custom recommendations failed: … | Recommendation widgets |
Unknown fields
Endpoints differ in how they treat body fields they do not recognise.
| Behaviour | Endpoints |
|---|---|
Rejected with 400 Unrecognized param(s): '…' | Similar, complementary, complete-the-look and for-you recommendations, recommendation widgets, search suggestions, instant search, get documents |
| Silently ignored | Search, composite search, collections, reverse image search |
The second group builds the outgoing search from the documented parameters
only. Fields such as searchMethod, hybridParameters or scoreModifiers in
a search body have no effect and produce no error, so a typo in a parameter
name fails silently on these endpoints.
Response headers
Responses carry Content-Type: application/json. The exception is the streaming
agentic discovery endpoints, which return text/event-stream while a stream is
open. Some endpoints add the headers below.
| Header | Values | Endpoints |
|---|---|---|
x-marqo-cache-hit | true or false | Search, composite search, collections, instant search, get documents, search suggestions. Whether the response was served from the cache. |
x-marqo-cache-hit-count, x-marqo-cache-miss-count | Integers | Similar, complementary, complete-the-look and for-you recommendations, recommendation widgets, instant search. These endpoints run more than one search; the counts say how many were cache hits and misses. |
x-marqo-results-personalized | true or false | Search, collections, instant search, similar, complementary and for-you recommendations, recommendation widgets. Present whenever the request included userId. false means the request carried a userId but the results were not personalised, for example because no events have been tracked for that shopper yet. |
Retry-After | 60 | Reverse image search 429 responses only. |
Reading headers from a browser
The API allows requests from any origin (Access-Control-Allow-Origin: *),
so storefront code can call it directly. Browsers only let scripts read the
response headers the API explicitly exposes. These are:
cf-ray
cf-placement
content-encoding
x-marqo-cache-hit
x-marqo-cache-hit-count
x-marqo-cache-miss-count
x-marqo-results-personalized
Retry-After is not on this list. A browser script sees the 429 status on a
rate-limited reverse image search but cannot read the header; use the
extra.window_seconds value in the body instead.
Caching
Responses from the search family and recommendations may be served from a cache. Whether an endpoint is cached, and for how long, is configured per index for each of these endpoints:
- Search
- Composite search
- Collections
- Get documents
- Similar recommendations
- Complementary recommendations
- Search suggestions
- Recommendation widgets
A response that was personalised is never served from the cache. Sending a
userId does not on its own bypass the cache. If the request was not
personalised, for example because a sort was applied or because the index is not
configured for personalisation, the response can still be a cache hit. The
x-marqo-results-personalized header says which of the two happened, and
x-marqo-cache-hit (or the hit and miss counts on multi-search endpoints)
reports whether the cache was used. There is no way for a caller to bypass the
cache on a per-request basis; if you need fresh results for a specific
integration, ask for the cache to be adjusted for your index.
Propagation of changes
Changes you make are not always visible on the next request:
| Change | Takes effect within |
|---|---|
| Creating, revoking or changing an API key | 1 minute |
| Search and collection profiles | 1 minute |
| Index configuration and search settings | 2 minutes |
| Merchandising rules | 5 minutes |
| Synonyms | 5 minutes |
| Recommendation widget rules | 5 minutes |
| Search redirects | 10 minutes |
| Query-level rules | 20 minutes |
Query-level rules are merchandising rules targeted at one specific search query. They are cached more aggressively than index-wide merchandising rules, so allow longer when you are testing a change to one.
Index creation is asynchronous, and a settings lookup that finds nothing is cached for the same minute as one that succeeds. A newly created index can therefore stay unavailable to the API for up to a minute after it is otherwise ready.
Limits
| Limit | Applies to | On exceeding |
|---|---|---|
limit + offset must not exceed 10000 | Search, composite search, collections | 400 'limit' + 'offset' must not exceed 10000 |
| At most 100 document IDs per request | Get documents | 400 |
| At most 10 seed document IDs per request | Similar and complementary recommendations | 400 |
| 200 requests per minute per index | Reverse image search | 429 with Retry-After: 60. See Reverse Image Search for the body. |
Silent fallbacks worth knowing
Some invalid or unsupported input does not produce an error. The request succeeds with default behaviour instead:
- Unknown
profileId. A search or collections request naming a profile that does not exist runs with the index's default configuration. - Unsupported
language. Alanguagevalue the search engine does not support is dropped and the language is auto-detected. disableMerchandising. The flag is only honoured for indexes that have it enabled. On other indexesdisableMerchandising: trueis accepted and ignored, and merchandising rules still apply.- No searchable fields. A search on an index whose configuration leaves no
lexically searchable fields returns
200with an emptyhitsarray rather than an error.