Skip to main content

Search with Marqo

This guide shows you how to search your product catalog using Marqo's powerful ecommerce search API. Learn how to perform text search, composite search, search by image, sort and filter results, implement faceted search, and "search as you type".

Prerequisites

  • A Marqo Cloud account (sign up here)
  • Your Marqo index ID (used for the x-marqo-index-id header)
  • An existing ecommerce index with products (add products guide)

Search Requests

Search requests are made via a POST /search request with a search body containing your query and search parameters.

Example

curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "wireless headphones",
"limit": 25
}'

Note: Replace {index_name} with your actual index name and {index_id} with the ID provided for your ecommerce deployment.

Response

{
"hits": [
{
"productTitle": "Premium Wireless Bluetooth Headphones",
"variantTitle": "Premium Wireless Bluetooth Headphones - Black",
"price": 199.99,
"variantImageUrl": "https://cdn.example.com/headphones-black.jpg",
"color": "Black",
"productCollections": ["electronics", "audio"],
"_id": "headphones-black-001",
"_score": 1.23456
},
{
"productTitle": "Wireless Earbuds Pro",
"variantTitle": "Wireless Earbuds Pro - White",
"price": 149.99,
"variantImageUrl": "https://cdn.example.com/earbuds-white.jpg",
"color": "White",
"productCollections": ["electronics", "audio"],
"_id": "earbuds-white-002",
"_score": 1.15432
}
],
"limit": 25,
"offset": 0,
"totalHits": 138,
"totalMatches": 138,
"processingTimeMs": 42,
"query": "wireless headphones",
"facets": {},
"availableOptionFacets": []
}

Response fields

FieldTypeDescription
hitsArrayThe matching products, each with its retrieved fields plus _id and _score.
queryString or ObjectThe query that was searched. This is the query after synonym substitution and any query prefix configured for your index, so it can differ from the text the shopper typed. For a weighted query it echoes the object.
limit, offsetIntegerThe pagination values applied to the request.
totalHitsIntegerThe number of matching products reachable via pagination. Use this to drive the pagination control (for example, "page X of Y"). Capped at 10,000. When the request includes sortBy, this is the number of sort candidates rather than the full match count.
totalMatchesIntegerThe total number of products matching the search criteria, uncapped. Use this to display a headline count (for example, "12,457 results"). When totalMatches exceeds totalHits, only the first totalHits products can be paged through.
processingTimeMsIntegerSearch engine processing time in milliseconds.
facetsObjectFacet counts, keyed by field. Always present; an empty object when no facets were requested or configured. See Faceted Search.
fieldLabelsObjectDisplay names for the facet fields in facets, keyed by field name, for example {"brand": "Brand"}. Present only when display names are configured for your index and at least one returned facet field has one.
availableOptionFacetsArray of stringsThe facet fields configured as product options for your index, for example ["size", "color"]. Always present; an empty array when none are configured.
relevanceScoreNumberA 0 to 10 estimate of how relevant the result set is to the query. Present only when the request sets relevanceScore: true and relevance scoring is configured for your index. Not computed for image, wildcard or weighted queries, or when there are fewer than three hits.
personalizedBooleanWhether the results were personalized for the userId sent with the request. Present whenever a userId was sent. It is false when personalization did not apply, including when personalization is not enabled for your index.

Response headers

HeaderValuesDescription
x-marqo-cache-hittrue or falseWhether the response was served from the results cache.
x-marqo-results-personalizedtrue or falsePresent whenever the request carried a userId. false means personalization did not apply to this request.

For the full list of response headers and error responses, see Responses and errors.

Search redirects

If the query matches a redirect rule configured in the console, the search returns 200 with a redirect object instead of results. Send the shopper to redirect.url.

{
"redirect": {
"url": "https://shop.example.com/pages/returns",
"query": "returns policy",
"matchType": "CONTAINS"
}
}
FieldTypeDescription
urlStringThe absolute URL to send the shopper to.
queryStringThe normalized shopper query that matched the rule.
matchTypeStringPresent only when a keyword rule matched a single word of the query, in which case it is CONTAINS. Whole-query matches omit it.

A redirect response has no hits and carries none of the response headers listed above. Redirects are evaluated after synonym substitution, so a synonym can cause a query to match a rule. They are not evaluated for image queries or weighted queries. On /composite-search they are evaluated against originalQuery and never fire when it is omitted.

Search Parameters

Here is a full list of parameters available for /search:

ParameterTypeDefaultDescription
qString or ObjectrequiredThe search query. A string searches for that text; "*" matches every product (useful with filter and sortBy). A recognised image URL or a data:image/... URL searches by image; see Search by Image for which URLs qualify. An object of {"term": weight} pairs runs a weighted multi-term query, which is semantic only and may use negative weights; see Composite Search. Image queries and weighted queries skip synonyms, redirects, query-level rules, merchandising rules and dynamic facets. Must not be empty.
limitIntegerIndex settingMaximum number of products to return. The default is the search limit configured for your index (12 when none is configured). limit + offset must not exceed 10,000.
offsetInteger0Number of products to skip (for pagination)
filterStringnullFilter string using Marqo's query DSL to narrow search results. Combined with any filter configured for your index using AND; wrap a filter whose top level is OR in parentheses.
attributesToRetrieveArray of stringsIndex settingSpecific product fields to return. If not specified, returns the attribute list configured for your index. parentProductId is always included in the returned fields.
facetsObjectIndex settingFacet configuration for aggregated results. Replaces the facets configured for your index. Mutually exclusive with useDynamicFacets; sending both returns 422. See Faceted Search.
useDynamicFacetsBooleanfalseOpt in to merchandised, dynamically ordered facets configured in the console. Mutually exclusive with facets; sending both returns 422. When true, the facets configured for your index are not used, even if no merchandised facets resolve. Not applied to image or weighted queries. Requires the Dynamic Facets feature to be enabled on your account. See Dynamic Facets.
sortByObjectIndex settingSort configuration for results ordering. Merged over the sort configured for your index. See Sorting for the interactions with personalization and merchandising.
collapseFieldsArrayIndex settingFields to group results by, so that only one hit per group is returned. Each entry is a field name string or an object {"name": "field", "sortBy": {...}} that chooses which variant represents the group. Replaces the collapse configured for your index; an empty array disables collapsing for this request. See Deduping Variants.
profileIdStringnull(optional) The ID of a named configuration profile to use for the request. Profiles allow fine-tuned configurations tailored to specific use cases. If the specified profile does not exist, Marqo will fallback to the default configuration. Please contact your Marqo representative to set up profiles for your requirements. Example: summer-sale-2026
userIdStringnullUser ID for personalization. When personalization is configured for your index, results are reranked toward the shopper's recent activity; a request with sortBy is never personalized. See Personalization.
sessionIdStringnullSession identifier. Sent alongside userId it refines personalization, and it is used to keep a shopper in the same variant of a merchandising experiment. On its own it does not personalize results.
geoLocationObjectnull(optional) Geographic context for the request, e.g. { "country": "US", "region": "Georgia" }. country is required when geoLocation is supplied; region is optional. Used to tailor ranking by location when geo-aware ranking is configured for your index. Please contact your Marqo representative to enable this. See Geo-Aware Ranking.
sizeAffinityArray of strings or ObjectnullSizes the shopper prefers, either as a list with equal weight (["S", "M"]) or as a map of size to weight ({"S": 1.0, "M": 0.5}). Boosts products available in those sizes when size-aware ranking is configured for your index; otherwise it has no effect. List entries must be non-empty strings and weights must be finite numbers, or the request returns 400.
languageStringIndex settingISO 639-1 language code used for text analysis of the query, for example de. Supported codes: ar, ca, da, de, el, en, es, fi, fr, ga, hu, id, it, nb, nl, pt, ro, ru, sv, tr. Unsupported codes are ignored and the language is detected automatically.
relevanceScoreBooleanfalseSet to true to include a relevanceScore field in the response. Requires relevance scoring to be configured for your index; otherwise the field is omitted.
disableMerchandisingBooleanfalseSkip all merchandising rules for this request. Must be enabled for your index; otherwise the flag is ignored. Non-boolean values return 422. It suppresses merchandising rules only: useDynamicFacets, redirects, synonyms and query-level rules are unaffected.

Query string parameters

ParameterTypeDefaultDescription
flattenMapsBooleanfalseBy default, map fields are returned as nested objects ({"specs": {"weight": 1}}). Set ?flattenMaps=true on the request URL to receive dotted keys instead ({"specs.weight": 1}).

Validation errors

Validation failures return a JSON body of the form {"error": "..."}. The messages specific to /search are:

StatusError
400'q' required in body
400'q' must not be empty
400'q' cannot be an empty object for multi-term queries
400'q' must be an object with only numeric values for multi-term queries
400'collectionName' not allowed in body for search requests
400'limit' + 'offset' must not exceed 10000
400'geoLocation' must be an object, 'geoLocation.country' must be a string, 'geoLocation.country' must not be empty, 'geoLocation.region' must be a string, 'geoLocation.region' must not be empty
400'sizeAffinity' must be a list of sizes or an object mapping sizes to weights, 'sizeAffinity' list entries must be non-empty strings, 'sizeAffinity' weights must be finite numbers
400sortBy supports a maximum of 3 fields, but N were provided (only for "q": "*" searches that use lexical retrieval)
422'useDynamicFacets' and 'facets' cannot both be set
422'disableMerchandising' must be a boolean

Errors shared by all endpoints, such as authentication failures, are listed in Responses and errors.

:::warning Known limitation A filter that is not a string, or an attributesToRetrieve that is not an array, is not type-checked by the API. These requests currently fail with 500 {"error": "Internal server error"} instead of a 400. Send the documented types to avoid it. :::

Behaviour notes

  • Hits never include internal fields. Fields whose names start with _merch_, _pixel_ or _mq_ are removed, along with the internal scoring fields _price_norm_steep, _top_queries_rank_score, _top_query_modifiers_last_updated_at, _pre_rerank_score, _tensor_score and _lexical_score. _id, _score, _highlights and _found are always kept, even when your index restricts which fields storefront callers receive.
  • _highlights is not returned unless highlighting is enabled for your index.
  • The response query is the query after synonym substitution and any query prefix configured for your index, not the text the shopper typed. A query-level rule can also replace the query, in which case query reports the replacement. Redirects are matched against the same substituted query.
  • The request filter is combined with the filter configured for your index as <index filter> AND <request filter>. Wrap a request filter whose top level is OR in parentheses so it is grouped as intended.
  • totalHits reports the number of sort candidates instead of the full match count when the request includes sortBy.
  • limit and offset must be positive integers. Other values are not validated by the API and are rejected by the search engine as Search failed: ....
  • popularitySettings cannot be set per request. Ordering facet values by popularity always uses the settings configured for your index.
  • Unknown body fields are ignored rather than rejected.

Query-level rules

Merchandisers can attach a rule to a specific shopper query in the console. When a request's query matches a rule, the rule can:

  • Replace the query with a representative one, so that related phrasings retrieve the same results. The response query reports the replacement rather than the text the shopper typed.
  • Supply a search configuration for the request. A query-level configuration takes precedence over profileId: when a rule matches and carries a configuration, the named profile is not applied.

Query-level rules must be enabled for your index. Contact your Marqo representative to use them. They are not applied to image queries or weighted queries.

Filtering

You can use Marqo's filter string DSL to refine search results. Filter strings can be used with all search methods and use a syntax based on Lucene with some differences. For complete filter syntax and examples, see our Filter DSL Guide.

Key Filter Features

  • Fielded searches - All term filters must be connected to a field, e.g., brand:Nike
  • Range filters - Efficient range filters for numeric types, e.g., price:[50 TO 300]
  • Boolean operators - Support for AND, OR, NOT with proper grouping
  • Array filtering - Filter over array fields like collections or tags

Examples

# Price range and availability filters
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "headphones",
"filter": "price:[50 TO 300] AND is_available:true"
}'

# Logical operators with grouping
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "shoes",
"filter": "(brand:Nike AND collections:athletic) OR (brand:Adidas AND price:[* TO 150])"
}'

# Array field filtering
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "electronics",
"filter": "collections:audio OR collections:wireless"
}'

# Boolean and exact match
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "*",
"filter": "is_featured:true AND brand:(Apple OR Samsung)"
}'

Common Filter Patterns

Filter TypeExampleDescription
Price Rangeprice:[50 TO 300]Products between $50-$300
Open Rangeprice:[100 TO *]Products $100 and above
Exact Matchbrand:NikeProducts with exact brand match
Booleanis_available:trueProducts that are available
Array Containscollections:electronicsProducts in electronics collection
Logical ANDbrand:Nike AND price:[* TO 200]Nike products under $200
Logical ORbrand:(Nike OR Adidas)Products from either brand
Complex Expression(brand:Nike AND collections:athletic) OR (price:[* TO 50] AND is_sale:true)Nike athletic items OR sale items under $50
NOT Operatorcollections:electronics AND NOT brand:AppleElectronics excluding Apple products

Facets allow you to aggregate data from your documents based on specific fields. This can be useful for creating filters, showing data distributions, or implementing drill-down search functionality.

Parameters

ParameterTypeDefaultDescription
fieldsObjectnullFields to facet on and their configuration
maxResultsInteger100Maximum facet results per field (max: 10000)
maxDepthIntegernullMax documents to consider for aggregation
orderString"desc"Order of facet results: asc or desc
useAutomaticExcludeTermsBooleanfalseDerive each facet field's exclusions from the request filter. Cannot be combined with excludeTerms
sortByStringnullOrdering of facet values for every field: count, alphanumeric or popularity. popularity orders values by shopper engagement using settings configured for your index

A facets object in the request replaces the facets configured for your index for that request. To use the merchandised facets configured in the console instead, send useDynamicFacets: true and omit facets.

Field Parameters

ParameterTypeDescription
typeStringFacet type: string, number, or array
sortByStringOrdering of this field's values: count, alphanumeric or popularity. Overrides the top-level sortBy
maxResultsIntegerMaximum values for this field. Overrides the top-level maxResults
orderStringasc or desc for this field. Overrides the top-level order
rangesArrayFor numeric fields: define value ranges
excludeTermsArrayRemove specific filter terms while calculating this facet

Range Parameters (Numeric Fields)

ParameterTypeDefaultDescription
fromNumbernullLower bound (inclusive), -Inf if not specified
toNumbernullUpper bound (exclusive), Inf if not specified
nameStringnullCustom range name (defaults to "from:to")

Excluding Filter Terms

By default, every term in the request's filter restricts every facet calculation. If a shopper selects color:Black and product_type:Shoes, the color facet is restricted to black and the product_type facet is restricted to shoes.

Use excludeTerms to remove each field's own selected term from that field's facet calculation. This changes the facet values and counts without changing the returned products:

{
"q": "casual wear",
"filter": "color:Black AND product_type:Shoes",
"facets": {
"fields": {
"color": {
"type": "string",
"excludeTerms": ["color:Black"]
},
"product_type": {
"type": "string",
"excludeTerms": ["product_type:Shoes"]
}
}
}
}

The returned products still match both filter terms. The color facet ignores color:Black but keeps product_type:Shoes, so it shows the colors available for shoes. The product_type facet ignores product_type:Shoes but keeps color:Black, so it shows the product types available in black.

Automatically Deriving Exclusions

For filters that change with each shopper interaction, set useAutomaticExcludeTerms to true and remove all field-level excludeTerms:

{
"q": "casual wear",
"filter": "color:Black AND product_type:Shoes",
"facets": {
"useAutomaticExcludeTerms": true,
"fields": {
"color": {"type": "string"},
"product_type": {"type": "string"}
}
}
}

This request produces the same exclusions as the manual example. If the shopper changes color:Black to color:White, update only the filter; Marqo derives the new color:White exclusion automatically.

Automatic mode derives equality and range terms. It does not derive IN or CONTAINS terms. It cannot be combined with field-level excludeTerms. Combining both modes returns HTTP 422.

Examples

# Price ranges and category facets
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "electronics",
"facets": {
"fields": {
"price": {
"type": "number",
"ranges": [
{"to": 50},
{"from": 50, "to": 100},
{"from": 100, "to": 200},
{"from": 200, "name": "$200+"}
]
},
"brand": {"type": "string"},
"collections": {"type": "array"}
}
}
}'

# Simple string facet
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "shoes",
"facets": {
"fields": {
"brand": {"type": "string", "maxResults": 10}
}
}
}'

Response

{
"hits": [...],
"totalHits": 10000,
"totalMatches": 43210,
"facets": {
"price": {
"0.0:50.0": {
"count": 15,
"min": 19.99,
"max": 49.99,
"avg": 34.50,
"sum": 517.50
},
"$200+": {
"count": 8,
"min": 200.00,
"max": 599.99,
"avg": 325.00
}
},
"brand": {
"Nike": {"count": 25},
"Adidas": {"count": 18},
"Apple": {"count": 12}
},
"collections": {
"electronics": {"count": 120},
"audio": {"count": 45}
}
}
}

Sorting

sortBy allows you to sort the search results based on specific numerical fields. This can be useful for ordering results by price, rating, or any other numerical attribute.

Parameters

ParameterTypeDefaultDescription
fieldsArray of objectsNo defaultA list of fields to be sorted on, with sort order and missing policy
sortDepthIntegernullThe number of documents to be sorted in the global phase
minSortCandidatesIntegernullThe minimum number of documents to be sorted on

Field Parameters

ParameterTypeDefaultDescription
fieldNameStringNo defaultThe field to be sorted on
orderString"desc"The sort order: "desc" or "asc"
missingString"last"Missing value policy: "first" or "last"

How sorting interacts with other features

  • A request sortBy is merged over the sort configured for your index, with the request taking precedence.
  • Entries without a fieldName are dropped. If no entries remain, the request is treated as unsorted.
  • A sorted request is never personalized, even when a userId is sent.
  • While a sort is applied, merchandising rules that reorder results (pins, boosts and recency) are suspended so the requested order is preserved.
  • totalHits reports the number of sort candidates rather than the full match count.
  • For "q": "*" searches that use lexical retrieval, at most three sort fields are accepted; more return 400.

Examples

# Sort by price descending
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "shoes",
"sortBy": {
"fields": [{"fieldName": "price"}]
}
}'

# Multi-field sort with missing value handling
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "electronics",
"sortBy": {
"fields": [
{"fieldName": "rating", "order": "desc", "missing": "last"},
{"fieldName": "price", "order": "asc", "missing": "first"}
]
}
}'

# Performance optimization with minSortCandidates
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "laptops",
"sortBy": {
"fields": [{"fieldName": "price", "order": "desc"}],
"minSortCandidates": 1000,
"sortDepth": 60
}
}'

Pagination

Handle large result sets with pagination using limit and offset parameters.

Parameters

ParameterTypeDefaultDescription
limitIntegerIndex settingMaximum number of documents to return. Defaults to the search limit configured for your index (12 when none is configured)
offsetInteger0Number of documents to skip

The result window is capped at 10,000 documents: a request where limit + offset exceeds 10,000 returns 400 with the error 'limit' + 'offset' must not exceed 10000. Use totalHits to work out how many pages can be requested.

Examples

# Page 1 (first 20 results)
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "laptops",
"limit": 20,
"offset": 0
}'

# Page 2 (results 21-40)
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "laptops",
"limit": 20,
"offset": 20
}'

Search as You Type

Search as you type provides real-time search results as users input queries, creating an instant and responsive search experience.

tip

The dedicated Instant Search endpoint returns query suggestions and a result panel in a single request and never computes facets. Prefer it for new integrations. The approach below uses the standard search endpoint.

Implementation

Use the standard search endpoint with these considerations for optimal real-time performance:

  • Lower limits: Use smaller limit values (5-10) for faster response times
  • Minimal attributes: Only retrieve essential fields using attributesToRetrieve
  • No facets: Facets are not necessary for search as you type. If facets are configured for your index, override them with an empty fields object so none are computed
  • Client-side debouncing: Implement 200-300ms delays between requests
  • Minimum query length: Consider requiring 2-3 characters before triggering search

Example

# Real-time search with optimized parameters
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "iph",
"limit": 5,
"attributesToRetrieve": ["productTitle", "variantTitle", "price", "variantImageUrl"],
"facets": {"fields": {}}
}'

Best Practices

  1. Debouncing: Implement client-side delays to prevent excessive API calls
  2. Progressive loading: Start with minimal results and allow expansion
  3. Caching: Cache recent results to improve perceived performance
  4. Error handling: Gracefully handle timeouts and network issues
  5. Accessibility: Ensure screen readers can navigate real-time results

Search by Image

Search by image returns products that look similar to an image you provide. It uses the same /search endpoint, with the image as q.

Image requirements

A query is treated as an image query when it is either:

  • a data URL beginning data:image/ that carries a base64-encoded image, or
  • a single http or https URL, containing no whitespace, whose path ends in .jpg, .jpeg, .png, .webp, .tiff or .avif. The extension is matched case-insensitively and the query string is ignored.

A URL that carries the image format in a query parameter rather than the path, such as https://cdn.example.com/img/123?format=jpeg, does not meet the second rule. That request is not handled as an image query and no error is returned: synonyms, redirects, query-level rules and merchandising rules are applied to it as they would be to a text query. Use a URL whose path ends in one of the extensions above, or a data URL, when you want image search.

note

Image queries run as semantic (tensor) searches. Synonyms, redirects, query-level rules, merchandising rules such as pins, boosts and exclusions, dynamic facets and relevanceScore are not applied to them.

Example

With URL to an image:

curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "https://example.com/image.jpg"
}'

With data URL of a base64-encoded image:

curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gAMQX..."
}'

Composite search enables multi-term queries where each search term can have a different weight. The same weighted form can be sent to /search as an object q.

A weighted query is semantic only. Retrieval and ranking both use the vector index, keyword matching does not contribute to the result, and any keyword score modifiers configured for your index are not applied. Weights may be negative, which pushes results away from that term.

Example

curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/composite-search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"weightedQuery": {
"wireless headphones": 1.0,
"high quality": 0.5
},
"originalQuery": "wireless headphones",
"limit": 20
}'

Parameters

ParameterTypeDefaultDescription
weightedQueryObjectrequiredMulti-term query as key-value pairs where keys are search terms and values are weights. Must be a non-empty object with numeric values
originalQueryStringnullThe original user query string. Include this if the user entered a single string that was transformed into the weightedQuery. It drives synonym substitution, redirects, merchandising rules and the response query. Must be a non-empty string when provided
limitIntegerIndex settingMaximum number of products to return. Defaults to the search limit configured for your index (12 when none is configured). limit + offset must not exceed 10,000
offsetInteger0Number of products to skip (for pagination)
filterStringnullFilter string using Marqo's query DSL. Combined with the filter configured for your index as described in Behaviour notes
sortByObjectIndex settingSort configuration for results ordering. See Sorting
attributesToRetrieveArray of stringsIndex settingSpecific product fields to return. Defaults to the attribute list configured for your index; parentProductId is always included
facetsObjectIndex settingFacet configuration for aggregated results. See Faceted Search. useDynamicFacets is accepted on this endpoint but does not attach merchandised facets; it only suppresses the facets configured for your index
collapseFieldsArrayIndex settingFields to group results by. See the /search parameter table
profileIdStringnull(optional) The ID of a named configuration profile to use for the request. On this endpoint it selects the search profile only: profile-scoped merchandising rules and merchandised facets are not applied. If the specified profile does not exist, Marqo will fallback to the default configuration. Please contact your Marqo representative to set up profiles for your requirements. Example: summer-sale-2026
userIdStringnullUser ID. Forwarded with the request but results are not personalized on this endpoint
sessionIdStringnullSession ID. Forwarded with the request but results are not personalized on this endpoint
geoLocationObjectnullGeographic context, e.g. { "country": "US", "region": "Georgia" }. See Geo-Aware Ranking
sizeAffinityArray of strings or ObjectnullPreferred sizes. See the /search parameter table
languageStringIndex settingISO 639-1 language code for query analysis. See the /search parameter table
relevanceScoreBooleanfalseInclude a relevanceScore in the response. Requires originalQuery and relevance scoring configured for your index
disableMerchandisingBooleanfalseSkip all merchandising rules for this request. Must be enabled for your index; otherwise ignored. Non-boolean values return 422

Validation errors specific to this endpoint:

StatusError
400'weightedQuery' required in body
400'weightedQuery' must be a multi-term query object
400'weightedQuery' cannot be an empty object
400'weightedQuery' must be an object with only numeric values
400'originalQuery' must be a non-empty string if provided

The limit, geoLocation, sizeAffinity, useDynamicFacets and disableMerchandising errors listed under Validation errors also apply.

note

Without originalQuery the response has no query field, redirects are never returned, and merchandising rules are not applied.

Response

{
"hits": [
{
"productTitle": "Premium Noise-Cancelling Wireless Headphones",
"variantTitle": "Premium Noise-Cancelling Wireless Headphones - Black",
"price": 249.99,
"variantImageUrl": "https://cdn.example.com/headphones-pro.jpg",
"productCollections": ["electronics", "audio", "wireless"],
"_id": "headphones-pro-001",
"_score": 1.85432
}
],
"limit": 20,
"offset": 0,
"totalHits": 57,
"totalMatches": 57,
"processingTimeMs": 38,
"query": "wireless headphones",
"facets": {},
"availableOptionFacets": []
}

The response has the same shape as /search (see Response fields). query echoes originalQuery after synonym substitution and is omitted when originalQuery was not sent. Redirect responses apply as described in Search redirects when originalQuery matches a rule.

Geo-Aware Ranking

When geo-aware ranking is configured for your index, pass a geoLocation object to tailor result ordering to the caller's location. Provide a country (required), and optionally a region, to boost products that perform well in that location. Requests without geoLocation are unaffected and continue to work unchanged.

geoLocation is supported on the /search, /collections and /composite-search endpoints. Invalid values return 400; see Validation errors for the messages.

Location codes

Both subfields follow ISO 3166-2, which is where the country codes and region (subdivision) names come from:

  • country — the two-letter ISO 3166-1 alpha-2 country code, e.g. US, GB, DE.
  • region — the subdivision name as listed for that country in ISO 3166-2, e.g. Georgia.

Example

# Country and region
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "wireless headphones",
"geoLocation": { "country": "US", "region": "Georgia" }
}'

# Country only (region omitted)
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/{index_name}/search \
-H "x-marqo-index-id: {index_id}" \
-H "Content-Type: application/json" \
-d '{
"q": "wireless headphones",
"geoLocation": { "country": "US" }
}'