Skip to main content

Marqo Conversational Agent API

Overview

The Conversational Agent API provides intelligent, conversational product discovery with query expansion, contextual recommendations, and real-time streaming responses. The system understands user intent, asks clarifying questions when needed, and organizes results into meaningful categories with natural language explanations.

Prerequisites

  • A Marqo Cloud account
  • Your x-marqo-index-id value for shopper-facing endpoints (copy it from the Quick Start code snippets for your index in the Marqo Console)
  • Your Marqo API key for settings and management endpoints (find your API key)
  • An existing ecommerce index with products (add products guide)
  • Access to the Conversational Agent API (contact Marqo for access). Until it is enabled, conversational search, Upload Images, Conversation Starters, Query Conversation Starters, and PDP Query Suggestions return 403 Agentic chat is not enabled for this index. The conversation endpoints (Get Conversation, Get Conversation Message, Submit Message Feedback, List Conversations, Delete Conversation) do not check this flag, so they answer normally for conversations that already exist

Authentication

Two credentials are used on this page:

  • x-marqo-index-id: {index_id} is the public credential for shopper-facing endpoints: conversational search, image upload, conversation starters, PDP query suggestions, and reading, listing, and giving feedback on conversations. It is safe to use from a browser or storefront.
  • Authorization: Bearer {api_key} is required by the management endpoints: catalog context settings, deleting a conversation, Reviews, and Help Center Content. These never accept x-marqo-index-id. Call them from your backend so the key is never exposed in client-side code.

A request with neither credential, or with an invalid one, returns 401 Unauthorized.

Requiring API keys on shopper-facing endpoints

On request, Marqo can configure your index so that the shopper-facing endpoints also require an API key. When that is on, each request must carry Authorization: Bearer {api_key} for the same index, and the key's scope must match the endpoint:

EndpointsMinimum key scope
Conversational search (/converse), Upload Images, Submit Message FeedbackRead-Write
Conversation Starters, Query Conversation Starters, PDP Query Suggestions, Get Conversation, Get Conversation Message, List ConversationsRead

A request with only x-marqo-index-id, or with a key that belongs to a different index, returns 401 Unauthorized. A key with insufficient scope returns 403 Insufficient API key scope. The management endpoints above always enforce these scopes: catalog context reads need a Read key, catalog context updates and deleting a conversation need a Read-Write key, and reindexing help-center content needs an Admin key. See Find Your API Key for the scopes.

Channels

Marqo can configure channel-specific conversational settings for your index (for example a mobile app with a different catalog context). The channel query parameter selects that configuration on conversational search, Upload Images, Conversation Starters, Query Conversation Starters, PDP Query Suggestions, the catalog context settings, and the Reviews endpoints. Use letters, numbers, hyphens, or underscores; maximum 64 characters. Omit it to use the default configuration. A channel inherits every setting it does not override from the default configuration, including the catalog context.

A channel that is malformed, or that Marqo has not configured, is rejected before the request is processed:

StatusMessageWhen
400Channel ID is required.channel is present but empty
400Channel ID must be at most 64 characters.The value is longer than 64 characters
400Channel ID must contain only alphanumerics, hyphens, and underscores.The value contains any other character
500Agentic config for channel "{channel}" is not configured.The value is well-formed but Marqo has not configured that channel for your index

The catalog context settings endpoints reject the same format errors with 422 rather than 400; see Catalog Context Settings.

Endpoints

Stream conversational search results with categorized products and intelligent messaging. This is the main endpoint for conversational product discovery.

Endpoint: GET /indexes/{index_name}/agentic-search/converse

Headers:

  • x-marqo-index-id: {index_id} (required)
  • x-marqo-shopify-customer-token: {customer_token} (optional) — the logged-in shopper's Shopify customer access token. When present, the agent can answer order-related questions (e.g. "where is my last order?") scoped to that shopper. See Order Lookup.

Query Parameters:

ParameterTypeRequiredDescription
payloadstringYesBase64-encoded JSON containing the request parameters (see below)
channelstringNoOptional channel identifier for routing the request through a channel-specific conversational experience. Use letters, numbers, hyphens, or underscores; maximum 64 characters. See Channels.

Payload Parameters (JSON, then base64-encoded):

ParameterTypeRequiredDefaultDescription
qstringYes-User query. Maximum 2048 characters by default
extraContextstringNo-Additional context to pass to the agent before the user query (see Extra Context). Maximum 2048 characters by default
sessionIdstringNonullSession identifier
userIdstringNonullUser identifier
conversationIdstringNo-Conversation identifier (returned from a previous response) for maintaining context
categoryResultLimitintegerNo6Number of results per category. Must be 1 or greater
maxCategoriesintegerNo4Maximum number of categories the agent will return. Must be 1 or greater
filterstringNo-Query filter using Marqo's filter DSL (e.g., "availability:true")
attributesToRetrievearrayNoDefault fieldsProduct fields to return (e.g., ["productTitle", "variantTitle", "price", "variantImageUrl", "_id"])
documentIdsarrayNo-Product document IDs to use as context (e.g., for PDP page questions)
contextFieldsarrayNoAll fieldsFields to include from the document context (e.g., ["material", "description"])
imageUrlsarrayNo-Publicly reachable image URLs to include in the query (must be valid URLs). imageUrls and imageIds together may hold at most 5 images
imageIdsarrayNo-IDs of images previously uploaded with Upload Images. Use this for images the shopper supplies from their device. Counted together with imageUrls toward the limit of 5
categoriesAfterMessagebooleanNofalseWhen true, category-hits events are always sent after the message events (see Response Event Ordering)
divisionSeedstringNo-Hint which product division the user is browsing from (see Division Seed)

The 2048-character limits on q and extraContext are defaults. Marqo can configure different limits for your index, and the 413 message reports the limit actually in force.

note

Marqo runs two generations of the conversational agent, and your index is on one of them. On indexes running the newer generation, q may be omitted when imageUrls or imageIds are supplied, so a shopper can send an image on its own; a turn with neither text nor images is rejected with 400 q: q or at least one image is required. On indexes running the earlier generation, q is always required. Send q whenever you have it and your integration works on both.

Example Request: With Product Context

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data-urlencode "payload=$(echo -n '{
"conversationId": "3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9",
"documentIds": ["1298739082732"],
"q": "I need outfits for a tropical vacation",
"sessionId": "session-xyz789",
"userId": "user-123",
"categoryResultLimit": 6,
"filter": "availability:true",
"attributesToRetrieve": [
"productTitle",
"variantTitle",
"price",
"variantImageUrl",
"_id"
]
}' | base64 | tr -d '\n')"

Example Request: Simple Query

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data-urlencode "payload=$(echo -n '{
"q": "red dress",
"sessionId": "session-001",
"userId": "user-456"
}' | base64 | tr -d '\n')"

Example Request: With Channel

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data-urlencode 'channel=mobile-app' \
--data-urlencode "payload=$(echo -n '{
"q": "red dress",
"sessionId": "session-001",
"userId": "user-456"
}' | base64 | tr -d '\n')"

Example Request: With Extra Context

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data-urlencode "payload=$(echo -n '{
"q": "show me matching bags",
"extraContext": "The customer is browsing vegan leather accessories.",
"sessionId": "session-001",
"userId": "user-456"
}' | base64 | tr -d '\n')"

Example Request: With Uploaded Images

Upload the shopper's images first with Upload Images, then pass the returned IDs:

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data-urlencode "payload=$(echo -n '{
"q": "find me a jacket that goes with these",
"imageIds": ["img_3f9c2a1b8d4e4c6f9a1b2c3d4e5f6a7b"],
"sessionId": "session-001",
"userId": "user-456"
}' | base64 | tr -d '\n')"

Error Responses

These errors are returned before the stream starts, with the standard error body {"error": "..."}:

  • 403 Agentic chat is not enabled for this index
  • 400 Query parameter 'payload' is required
  • 400 Invalid base64 JSON payload
  • 400 with a validation message such as q: q is required when a payload field fails validation
  • 400 Invalid filter syntax when filter is not valid filter DSL
  • 400 Too many images provided. Maximum is 5, got {n}.
  • 400 Invalid divisionSeed: "{value}". Allowed values: men, mens, women, womens, kids, kid, beauty
  • 400 Conversation not found for conversationId: {conversation_id} when the conversation does not exist or has been deleted
  • 400 This conversation has reached the maximum of 1000 user messages and cannot accept more. Start a new conversation to continue. (see Conversation Retention and Limits)
  • 413 Query 'q' is too long (max 2048 characters). The number in the message is the limit configured for your index
  • 413 extraContext is too long (max 2048 characters). The number in the message is the limit configured for your index
  • 400 with one of the malformed channel messages, or 500 for an unconfigured channel; see Channels
  • 401 Unauthorized and 403 Insufficient API key scope as described in Authentication

Once the stream has started the HTTP status is already 200; later failures arrive as an error event.

Response Events

The conversational search endpoint streams responses as Server-Sent Events (SSE). Each event has an event: field identifying its type and a data: field containing a JSON payload.

message

Text from the agent's conversational response. Depending on how your index is configured, the reply arrives either as a series of incremental deltas or as a single event containing the whole reply. Always concatenate every message event in order to build the full message; do not assume a fixed number of frames.

event: message
data: {"message":"I'd be happy to help you find the perfect jacket! "}
event: message
data: {"message":"To give you the best recommendations:\n\n- What type of jacket are you looking for?"}

Fields:

  • message (string): A text delta to append to the agent's response
suggestions

Follow-up query suggestions generated by the agent based on the current conversation context. Display these as clickable prompts to help users continue exploring.

event: suggestions
data: {"suggestions":["show me trending items for her","what are popular tech gifts?","something unique and trending"]}

Fields:

  • suggestions (array of strings): Suggested follow-up queries the user might want to ask
category-hits

Search results grouped by category.

event: category-hits
data: {"categoryHits":[{"category":"Summer Dresses","query":"summer floral dresses","confidence":0.9,"hits":[{"_id":"dress_001","productTitle":"Red Sequin Dress","price":89.99},{"_id":"dress_002","productTitle":"Black Silk Gown","price":129.99}]}]}

Fields:

  • categoryHits (array): Array of category groups
    • category (string): Category name (e.g., "Summer Dresses", "Casual Jackets")
    • query (string): The search query the agent used to retrieve products in this category
    • confidence (number): The agent's confidence score for this category (0–1)
    • hits (array): Array of product documents matching this category
    • appliedFilter (string, optional): The filter that was applied to this category's search
    • filterDropped (boolean, optional): true if the agent's filter was dropped due to producing zero results
    • originalFilter (string, optional): The filter that was dropped, present when filterDropped is true

If the search for one category fails, its entry contains category, status (the HTTP status of the failed search), and error instead of hits. Other categories are unaffected.

auth-required

Emitted when the shopper asked an order question that needs a logged-in customer but no valid x-marqo-shopify-customer-token was supplied (see Order Lookup). No message text follows for this turn. The stream still finishes normally with conversation-id and stream-end, so keep the conversationId, prompt the shopper to log in, and continue the conversation with a fresh token.

event: auth-required
data: {"reason":"missing_token","loginUrl":"https://my-store.myshopify.com/account/login"}

Fields:

  • reason (string): Why authentication is needed. One of missing_token (no token was sent), unauthorized_401 (the token was rejected, for example because it expired), or null_customer (the token did not resolve to a customer)
  • loginUrl (string): The store's login page
message-id

Emitted before conversation-id. Use this value when retrieving message details, submitting feedback for a specific agent reply, or correlating the reply in conversation history.

event: message-id
data: {"messageId":"9b4c4b6d-8bfe-4c66-b388-0d97d3ec1e2e"}

Fields:

  • messageId (string): Unique identifier for the agent message
conversation-id

Emitted near the end of the stream. Use this ID in subsequent requests to continue the conversation.

event: conversation-id
data: {"conversationId":"3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9"}

Fields:

  • conversationId (string): Unique identifier for this conversation
conversation-end

Emitted after conversation-id when the turn just completed was the last one the conversation can accept (see Conversation Retention and Limits). The reply for this turn is complete and has been saved, but the next request that reuses this conversationId returns 400. Start a new conversation by omitting conversationId.

event: conversation-end
data: {"reason":"This conversation has reached the maximum of 1000 user messages. Your next message in this conversation will return an error. Start a new conversation to continue."}

Fields:

  • reason (string): Human-readable explanation
error

Emitted when an error occurs after the stream has started. The HTTP status is already 200 at this point, so clients must watch for this event.

event: error
data: {"error":"Failed to retrieve document doc_123: not found","status":404}

Fields:

  • error (string): Error message
  • status (number, optional): HTTP status code of the underlying failure, when known

Some errors are recoverable and the stream continues, for example:

  • {"status": 404, "error": "Failed to retrieve document doc_123: ..."} when a documentIds entry cannot be fetched
  • {"error": "Image not found or expired: img_..."}, {"error": "Image has expired: img_..."}, or {"error": "Image cannot be used for this account: img_..."} when an imageIds entry is unusable. The turn continues without that image
  • {"status": 500, "error": "Failed to save conversation. Please try again."} when the reply was generated but could not be stored. No message-id or conversation-id follows

Others end the stream, and no stream-end follows:

  • {"status": 400, "error": "user location not supported"} when the request comes from a region the model does not serve
  • {"error": "Internal server error"} for any unexpected failure
stream-end

Marks the end of the SSE stream. No further events will be sent.

event: stream-end
data: {}

Response Event Ordering

By default, category-hits events are streamed as soon as search results are available, which means they may arrive before the message events. This allows clients to render product results immediately while the agent's text response is still being generated.

If you prefer to display category results after the agent's message (for example, to show the conversational text first), set categoriesAfterMessage to true in the payload. When enabled, category-hits events are buffered internally and sent after all message and suggestions events.

The stream emits message-id before conversation-id. conversation-end, when present, follows conversation-id. auth-required replaces the message events for that turn.


Upload Images

Upload images from the shopper's device so they can be attached to a conversational search turn. The response returns an ID per image; pass those IDs in the imageIds field of the /converse payload. Use imageUrls instead when the image is already hosted at a public URL.

Endpoint: POST /indexes/{index_name}/agentic-search/images

Headers:

  • Content-Type: application/json
  • x-marqo-index-id: {index_id} (required)

Query Parameters:

ParameterTypeRequiredDescription
channelstringNoChannel identifier; see Channels

Request Body:

ParameterTypeRequiredDescription
imagesarrayYes1 to 5 images to upload

Each entry in images has the following fields:

ParameterTypeRequiredDescription
dataUrlstringYesThe image as a base64 data URL: data:{mime_type};base64,{payload}. The MIME type must be an image/* type
clientImageIdstringYesYour own identifier for the image. It is echoed back in the response and used in error messages so you can match results to inputs

Limits:

  • Up to 5 images per request.
  • Supported formats: JPEG, PNG, WebP, BMP, TIFF, ICO, HEIC, and HEIF.
  • Maximum size per image (decoded bytes): 5 MB for JPEG, PNG, WebP, BMP, TIFF, and ICO; 1 MB for HEIC and HEIF.
  • Images are resized server-side before use. Uploading images larger than a few hundred pixels on the longest side does not improve results.
  • Uploaded images are kept for 24 hours and then deleted. Use the IDs within that window; an expired ID produces an error event on /converse and the turn continues without that image.
  • Image IDs are tied to your account and cannot be used with another account's index.

Example Request:

curl -X POST 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/images' \
--header 'Content-Type: application/json' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data '{
"images": [
{
"clientImageId": "camera-roll-1",
"dataUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD..."
}
]
}'

Example Response:

{
"images": [
{
"clientImageId": "camera-roll-1",
"imageId": "img_3f9c2a1b8d4e4c6f9a1b2c3d4e5f6a7b",
"mimeType": "image/jpeg",
"expiresAt": "2026-09-10T03:12:45.000Z"
}
]
}

Response Fields:

  • images (array): One entry per uploaded image, in request order
    • clientImageId (string): The identifier you supplied
    • imageId (string): The ID to pass in imageIds on /converse
    • mimeType (string): The MIME type of the stored image, which may differ from the uploaded type after processing
    • expiresAt (string): ISO 8601 timestamp after which the image is no longer available

Error Responses:

  • 403 Agentic chat is not enabled for this index
  • 400 Invalid JSON in request body
  • 400 images: At least one image is required, or another validation message when images has more than 5 entries or an entry is missing dataUrl or clientImageId
  • 400 Invalid dataUrl format for {clientImageId}. Expected data:<mime>;base64,<payload>
  • 400 Invalid dataUrl mimeType for {clientImageId}: {mime_type}. Expected an image/* MIME type.
  • 400 Image payload is empty: {clientImageId}
  • 400 Image too large for {clientImageId} ({size}KB > {limit}KB limit)
  • 400 Invalid base64 payload in dataUrl for {clientImageId}
  • 400 Image format {mime_type} is not supported: {clientImageId}. Supported formats: JPEG, PNG, WebP, BMP, TIFF, HEIC, HEIF.
  • 400 Failed to process image: {clientImageId} when the bytes cannot be decoded as the declared format
  • 500 Failed to upload images. Nothing from the request is stored

If any image in the request fails validation, no images from that request are stored.


Catalog Context Settings

Configure persistent catalog context for the conversational agent. Use this when you want the agent to consistently apply store, brand, merchandising, or catalog guidance without passing the same text in every /converse request.

These are server-side settings endpoints. They use your Marqo API key in the Authorization header instead of the x-marqo-index-id header used by shopper-facing conversational endpoints. Do not expose your API key in browser code.

Endpoints:

  • GET /indexes/{index_name}/agentic-search/settings/converse/catalog-context
  • PATCH /indexes/{index_name}/agentic-search/settings/converse/catalog-context

Headers:

  • Authorization: Bearer {api_key} (required)
  • Content-Type: application/json (required for PATCH)

Query Parameters:

ParameterTypeRequiredDescription
channelstringNoOptional channel scope. Omit it to read or update the default catalog context. Include it to read or update a channel-specific context. Use letters, numbers, hyphens, or underscores; maximum 64 characters.

Channel-specific catalog context is stored separately from the default scope. Use the same channel value that your clients pass to GET /indexes/{index_name}/agentic-search/converse?channel=... when you want a specific conversational experience to use that context. If no context is stored for the requested scope, catalogContext is null. At request time a channel without its own context uses the default context.

Reads need a Read key or higher; updates need a Read-Write key or higher. Updates can take up to about a minute to reach live conversational requests.

Get Catalog Context

Example Request: Default Scope

curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/settings/converse/catalog-context' \
--header 'Authorization: Bearer {api_key}'

Example Response:

{
"scope": "default",
"channel": null,
"catalogContext": "Use concise product language and prioritize in-stock items."
}

Update Catalog Context

PATCH replaces the catalog context for the selected scope while preserving other agentic search settings. The request body must use the catalogContext field. Send null to clear the stored context.

Request Body:

ParameterTypeRequiredDescription
catalogContextstring or nullYesPersistent context to provide to the conversational agent. Surrounding whitespace is trimmed before the value is stored. Send null, an empty string, or a whitespace-only string to remove the context for this scope.

Example Request: Channel Scope

curl -X PATCH 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/settings/converse/catalog-context?channel=mobile-app' \
--header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \
--data '{
"catalogContext": "Use mobile-specific merchandising copy and keep answers short."
}'

Example Response:

{
"scope": "channel",
"channel": "mobile-app",
"catalogContext": "Use mobile-specific merchandising copy and keep answers short."
}

Example Request: Clear Context

curl -X PATCH 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/settings/converse/catalog-context?channel=mobile-app' \
--header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \
--data '{"catalogContext": null}'

Error Responses:

  • 401: Missing or invalid API key.
  • 403 This operation requires a read-scoped API key. on GET, or This operation requires a read_write-scoped API key. on PATCH, when the key's scope is too low.
  • 404: The index does not exist under your account.
  • 422: Invalid request body, unsupported field name, or invalid channel value.

Conversation Starters

Generate conversation starters based on your most popular queries from your analytics data.

Endpoint: GET /indexes/{index_name}/agentic-search/conversation-starters

Headers:

  • x-marqo-index-id: {index_id} (required)

Query Parameters:

ParameterTypeRequiredDefaultDescription
maxStartersintegerNo4Number of conversation starters to return. Must be between 1 and 20
divisionstringNonullProduct division filter to generate division-specific starters. Allowed values: men, mens, women, womens, kid, kids. Matched case-insensitively, and surrounding whitespace is ignored
channelstringNo-Channel identifier; see Channels
invalidateCachestringNofalseSet to true to skip the cached starters and generate a fresh set. Case-insensitive
warning

invalidateCache=true regenerates the starters on every request it is sent with, which costs latency and AI usage. Use it for testing, never on live storefront traffic.

Example Request:

curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/conversation-starters?maxStarters=4&division=women' \
--header 'x-marqo-index-id: abc123-my-ecom-store'

Example Response:

[
"Show me running shoes for a marathon",
"Help me find a gift for a birthday",
"I'm looking for the perfect backpack",
"What's trending in sneakers right now?"
]

The response is an array of conversation starter strings. It is empty when the index has no analytics data to draw popular queries from.

Error Responses:

  • 403 Agentic chat is not enabled for this index
  • 400 maxStarters must be a number between 1 and 20
  • 400 Invalid division: "{value}". Allowed values: men, mens, women, womens, kid, kids
  • 400 with one of the malformed channel messages, or 500 for an unconfigured channel; see Channels

Query Conversation Starters

Generate follow-up prompts for a specific query, for example to show under a search box or beside search results as entry points into a conversation. Unlike Conversation Starters, the suggestions are specific to the query rather than to your popular searches.

This endpoint must be enabled for your index by Marqo. Until then it returns 403.

Endpoint: GET /indexes/{index_name}/agentic-search/query-conversation-starters

Headers:

  • x-marqo-index-id: {index_id} (required)

Query Parameters:

ParameterTypeRequiredDefaultDescription
qstringYes-The query to generate starters for. Maximum 2048 characters by default
maxStartersintegerNo4Number of starters to return. Must be between 1 and 20
channelstringNo-Channel identifier; see Channels

This endpoint applies the same input limit as conversational search rather than a limit of its own, so a different limit configured for conversational search on your index also applies here.

Example Request:

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/query-conversation-starters' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data-urlencode 'q=running shoes' \
--data-urlencode 'maxStarters=3'

Example Response:

[
"Which running shoes are best for flat feet?",
"Show me lightweight running shoes for racing",
"What running shoes do you have under $100?"
]

The response is an array of starter strings. Results for the same query are cached, so repeated requests return quickly and may return the same starters.

Error Responses:

  • 403 Agentic chat is not enabled for this index
  • 403 Query conversation starters are not enabled for this index
  • 400 q is required when q is missing or blank
  • 400 maxStarters must be a number between 1 and 20
  • 400 with one of the malformed channel messages, or 500 for an unconfigured channel; see Channels
  • 413 Query 'q' is too long (max 2048 characters). The number in the message is the limit configured for your index
  • 503 Query conversation starters are temporarily unavailable. Retry later

PDP Query Suggestions

Generate contextual search query suggestions based on a specific product. This endpoint helps users discover related products or learn more about a product they're viewing.

Endpoint: POST /indexes/{index_name}/agentic-search/chat-suggestions

Headers:

  • Content-Type: application/json
  • x-marqo-index-id: {index_id} (required)

Query Parameters:

ParameterTypeRequiredDescription
channelstringNoChannel identifier; see Channels

Request Parameters:

ParameterTypeRequiredDefaultDescription
documentIdstringYes-Product document identifier (_id field)
sessionIdstringNo-User session identifier
userIdstringNo-User identifier
maxSuggestionsintegerNo5Maximum number of suggestions to return. Must be between 1 and 10
minSuggestionsintegerNo1Minimum number of suggestions to return. Must be between 1 and 10, and not greater than maxSuggestions
contextFieldsstring[]No["productTitle", "variantTitle"]Document fields to include as context for suggestion generation. When provided, only matching fields (case-insensitive) are passed to the model. When omitted, defaults to productTitle and variantTitle. Image context (variantImageUrl/productMainImageUrl) is always included automatically when present.

The request body must not contain fields other than those listed; unknown fields return 400.

Example Request:

curl -X POST 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/chat-suggestions' \
--header 'Content-Type: application/json' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data '{
"documentId": "273301208",
"sessionId": "session-abc123",
"userId": "user-28389290",
"maxSuggestions": 5,
"minSuggestions": 1,
"contextFields": ["material", "description"]
}'

Example Response:

[
"What heels would go well with this?",
"What is the material made out of?",
"What do people say about this product?"
]

The response is an array of suggested queries that users might want to ask about the product. Results are cached per document and parameter set, so repeated requests for the same product return the same suggestions.

Error Responses:

  • 403 Agentic chat is not enabled for this index
  • 400 documentId is required
  • 400 minSuggestions must be <= maxSuggestions
  • 400 Document has no context fields or image to generate suggestions from when none of the requested contextFields exist on the document and it has no image
  • 404 Document not found
  • 500 Failed to generate chat suggestions

Get Conversation

Retrieve the history of a previous conversation by its ID.

Endpoint: GET /indexes/{index_name}/agentic-search/conversations/{conversation_id}

Headers:

  • x-marqo-index-id: {index_id} (required)

Path Parameters:

ParameterTypeRequiredDescription
index_namestringYesThe name of your index
conversation_idstringYesThe conversation ID returned from a previous converse response

Example Request:

curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/conversations/3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9' \
--header 'x-marqo-index-id: abc123-my-ecom-store'

Example Response:

{
"conversationId": "3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9",
"title": "Tropical Vacation Outfits",
"conversation": [
{
"role": "user",
"message": "I need outfits for a tropical vacation"
},
{
"role": "agent",
"messageId": "9b4c4b6d-8bfe-4c66-b388-0d97d3ec1e2e",
"message": "Here are some great options for a tropical getaway!",
"categories": [
{
"query": "tropical vacation dresses",
"category": "Summer Dresses",
"confidence": 0.9,
"hits": ["dress_001", "dress_002"]
}
]
}
]
}

Response Fields:

  • conversationId (string): The conversation identifier
  • title (string, optional): A short title summarizing the conversation topic
  • conversation (array): Array of messages in chronological order
    • role (string): Either "user" or "agent"
    • message (string): The message content
    • messageId (string, optional, agent only): Unique identifier for the agent message. Use this with the get message and feedback endpoints.
    • categories (array, optional, agent only): Search categories from the agent's response
      • query (string): The search query used
      • category (string): The category name
      • confidence (number): Confidence score (0–1)
      • hits (array of strings): Product document IDs returned

Error Responses:

StatusMessageWhen
400Conversation not found for conversationId: {conversation_id}The ID is unknown, malformed, or belongs to a conversation that has been deleted or has expired
401UnauthorizedMissing or invalid credential

:::warning Reading a missing conversation returns 400, not 404 This endpoint, Get Conversation Message, and Submit Message Feedback report an unknown conversation ID as 400. Delete Conversation reports the same condition as 404. Do not assume one status covers both: check for the Conversation not found for conversationId message rather than branching on 404 alone. :::


Get Conversation Message

Retrieve a specific agent message with its category hit IDs hydrated into product documents.

Endpoint: GET /indexes/{index_name}/agentic-search/conversations/{conversation_id}/messages/{message_id}

Headers:

  • x-marqo-index-id: {index_id} (required)

Use the messageId returned by the message-id SSE event or from GET /indexes/{index_name}/agentic-search/conversations/{conversation_id}. This endpoint does not accept query parameters.

Path Parameters:

ParameterTypeRequiredDescription
index_namestringYesThe name of your index
conversation_idstringYesThe conversation ID that contains the target message
message_idstringYesThe agent message ID to retrieve

Example Request:

curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/conversations/3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9/messages/9b4c4b6d-8bfe-4c66-b388-0d97d3ec1e2e' \
--header 'x-marqo-index-id: abc123-my-ecom-store'

Example Response:

{
"messageId": "9b4c4b6d-8bfe-4c66-b388-0d97d3ec1e2e",
"user": "I need outfits for a tropical vacation",
"agent": "Here are some great options for a tropical getaway!",
"suggestions": [
"show me beach cover-ups",
"what shoes work with these outfits?",
"find accessories for this look"
],
"categories": [
{
"query": "tropical vacation dresses",
"category": "Summer Dresses",
"confidence": 0.9,
"hits": [
{
"_id": "dress_001",
"productTitle": "Red Floral Sundress",
"variantTitle": "Red / Small",
"price": 89.99,
"variantImageUrl": "https://example.com/images/dress_001.jpg"
},
{
"_id": "dress_002",
"productTitle": "Linen Midi Dress",
"variantTitle": "Natural / Medium",
"price": 129.99,
"variantImageUrl": "https://example.com/images/dress_002.jpg"
}
]
}
]
}

Response Fields:

  • messageId (string): Unique identifier for the returned agent message
  • user (string): The user message immediately before the selected agent response
  • agent (string): The selected agent response text
  • suggestions (array, optional): Suggested follow-up queries extracted from the agent response
  • categories (array, optional): Search categories from the selected agent response
    • query (string): The search query used
    • category (string): The category name
    • confidence (number): Confidence score (0–1)
    • hits (array): Product documents returned for the category. Returned document fields follow the attributesToRetrieve used when the message was created. If a document cannot be retrieved, the hit entry contains _id, status, and error.

Error Responses:

StatusMessageWhen
400Conversation not found for conversationId: {conversation_id}The conversation ID is unknown, malformed, deleted, or expired
400messageId is requiredThe message ID path segment is empty
404Message not found for messageId: {message_id}The conversation exists but holds no agent message with that ID
401UnauthorizedMissing or invalid credential

A missing conversation is a 400 here while a missing message is a 404; see the note under Get Conversation.


Submit Message Feedback

Record feedback for a specific agent message.

Endpoint: POST /indexes/{index_name}/agentic-search/conversations/{conversation_id}/feedback

Headers:

  • Content-Type: application/json
  • x-marqo-index-id: {index_id} (required)

Use the messageId returned by the message-id SSE event or from GET /indexes/{index_name}/agentic-search/conversations/{conversation_id}.

Path Parameters:

ParameterTypeRequiredDescription
index_namestringYesThe name of your index
conversation_idstringYesThe conversation ID that contains the target message

Request Body:

ParameterTypeRequiredDescription
messageIdstringYesThe agent message to attach feedback to
feedbackintegerYesFeedback value. Use 1 for positive feedback and 0 for negative feedback
feedbackTextstringNoOptional feedback note, up to 500 characters

Example Request:

curl -X POST 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/conversations/3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9/feedback' \
--header 'Content-Type: application/json' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data '{
"messageId": "9b4c4b6d-8bfe-4c66-b388-0d97d3ec1e2e",
"feedback": 1,
"feedbackText": "Helpful response"
}'

Example Response:

{
"status": "ok"
}

Error Responses:

StatusMessageWhen
400conversationId is requiredThe conversation ID path segment is empty
400messageId is requiredmessageId is missing from the body
400feedback must be 0 or 1feedback is absent or is any other value
400feedbackText must be 500 characters or lessfeedbackText is longer than 500 characters
400Invalid feedback requestThe body fails validation for any other reason
400Conversation not found for conversationId: {conversation_id}The conversation ID is malformed
404Conversation not found for conversationId: {conversation_id}The conversation ID is well-formed but no such conversation exists, including one that was deleted or has expired
404Message not found for messageId: {message_id}The conversation exists but holds no message with that ID
400Feedback is not supported for this conversationThe conversation predates feedback support
401UnauthorizedMissing or invalid credential

The same Conversation not found message is returned as 400 for a malformed ID and 404 for a well-formed one that does not exist. Match on the message rather than the status if you need to treat both the same way.

List Conversations

List all conversations for a specific user, sorted by most recently updated first.

Endpoint: GET /indexes/{index_name}/agentic-search/conversations

Headers:

  • x-marqo-index-id: {index_id} (required)

Query Parameters:

ParameterTypeRequiredDescription
userIdstringYesThe user identifier to list conversations for

Example Request:

curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/conversations?userId=user-123' \
--header 'x-marqo-index-id: abc123-my-ecom-store'

Example Response:

{
"conversations": [
{
"conversationId": "3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9",
"title": "Tropical Vacation Outfits",
"createdAt": 1717012800000,
"updatedAt": 1717016400000
},
{
"conversationId": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"title": "Running Shoes",
"createdAt": 1716926400000,
"updatedAt": 1716930000000
}
]
}

Response Fields:

  • conversations (array): Array of conversation summaries, sorted by updatedAt descending (most recent first)
    • conversationId (string): Unique identifier for the conversation
    • title (string): A short title summarizing the conversation topic
    • createdAt (number): Timestamp (milliseconds since epoch) when the conversation was created
    • updatedAt (number): Timestamp (milliseconds since epoch) when the conversation was last updated

Error Responses:

StatusMessageWhen
400accountId, indexName, and userId are requireduserId is missing from the query string
401UnauthorizedMissing or invalid credential

A userId with no conversations is not an error: the response is 200 with an empty conversations array.

Delete Conversation

Permanently delete a stored conversation, including its message history, feedback, and its entry in the user's conversation list.

Endpoint: DELETE /indexes/{index_name}/agentic-search/conversations/{conversation_id}

warning

This endpoint requires a Read-Write (or Admin) API key authenticated with the Authorization: Bearer {api_key} header and does not accept the x-marqo-index-id credential used by the other conversation endpoints. Call it from your backend so the key is never exposed in client-side code.

Headers:

  • Authorization: Bearer {api_key} (required)

Path Parameters:

ParameterTypeRequiredDescription
index_namestringYesThe name of your index
conversation_idstringYesThe conversation ID returned from a previous converse response

This endpoint does not accept query parameters or a request body.

Example Request:

curl -X DELETE 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/conversations/3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9' \
--header 'Authorization: Bearer {api_key}'

Example Response:

{
"status": "ok"
}

Error Responses:

  • 401: Missing or invalid API key.
  • 403 Insufficient API key scope: The key is a Read key.
  • 404: No conversation exists for the given conversation_id under this index. This also covers a malformed conversation ID, a conversation belonging to a different index or account, and a conversation that has already been deleted.

Deletion is permanent and cannot be undone. Because a second delete of the same conversation returns 404, treat that status as "already gone" rather than an error when you retry. Once deleted, the conversation_id is also rejected by the other conversation endpoints, and passing it to GET /indexes/{index_name}/agentic-search/converse returns 400.


Help Center Content

When customer support is enabled for your conversational agent, Marqo crawls your public help center and grounds support answers in that content. These endpoints let you see which pages are indexed, read what the agent sees, and request a refresh. Marqo configures which site and locales are crawled; contact Marqo to set this up or change it.

All four endpoints require Authorization: Bearer {api_key}. The three GET endpoints accept any valid key; POST .../reindex requires an Admin key. The channel query parameter does not apply to them.

List Locales

Endpoint: GET /indexes/{index_name}/help-center/locales

Lists every locale configured for the index with the time its content was last indexed.

curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/help-center/locales' \
--header 'Authorization: Bearer {api_key}'

Example Response:

[
{"locale": "en", "indexedAt": "2026-09-08T02:15:41+00:00"},
{"locale": "fr", "indexedAt": null}
]
  • locale (string): A configured locale
  • indexedAt (string or null): ISO 8601 timestamp of the last successful index, or null if the locale has not been indexed yet

The list is empty when no locale is configured.

Get Corpus

Endpoint: GET /indexes/{index_name}/help-center/corpus

Returns the list of indexed pages and freshness for one locale.

ParameterTypeRequiredDescription
localestringYesThe locale to read, as returned by List Locales
includestringNoSet to text to include the full corpus text in the response. Only applies when mode is inline
curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/help-center/corpus?locale=en&include=text' \
--header 'Authorization: Bearer {api_key}'

Example Response:

{
"indexName": "my-ecom-store",
"locale": "en",
"mode": "manifest",
"indexedAt": "2026-09-08T02:15:41+00:00",
"totalTokens": 48213,
"version": "1",
"citations": {
"shipping-times": "https://help.example.com/articles/shipping-times",
"returns-policy": "https://help.example.com/articles/returns-policy"
},
"articles": [
{
"articleId": "shipping-times",
"title": "Shipping times",
"summary": "Delivery estimates by region and carrier.",
"citationUrl": "https://help.example.com/articles/shipping-times"
}
]
}
  • indexName (string): Your index name
  • locale (string): The requested locale
  • mode (string): inline when the corpus is stored as one text, manifest when it is stored as individual articles
  • indexedAt (string): ISO 8601 timestamp of the last successful index
  • totalTokens (number): Approximate size of the corpus in tokens
  • version (string): Corpus format version
  • citations (object): Map of article ID to the public URL the agent cites for that article
  • articles (array, manifest mode only): One entry per indexed article with articleId, title, summary, and citationUrl. Fetch an article's full text with Get Article
  • corpus (string, inline mode with include=text only): The full corpus text

Error Responses:

  • 404 No help-center corpus for index '{index_name}' locale '{locale}'. It may not have been indexed yet.
  • 422: locale is missing or invalid, or include is not text

Get Article

Endpoint: GET /indexes/{index_name}/help-center/corpus/pages/{article_id}

Returns the full text of one article from a manifest mode corpus.

ParameterTypeRequiredDescription
article_idstring (path)YesAn articleId from Get Corpus
localestringYesThe locale the article belongs to
curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/help-center/corpus/pages/shipping-times?locale=en' \
--header 'Authorization: Bearer {api_key}'

Example Response:

{
"articleId": "shipping-times",
"title": "Shipping times",
"body": "Standard shipping takes 3 to 5 business days within the US...",
"sourceUrl": "https://help.example.com/articles/shipping-times",
"citationUrl": "https://help.example.com/articles/shipping-times",
"indexedAt": "2026-09-08T02:15:41+00:00"
}
  • articleId, title, body (string): The article as indexed
  • sourceUrl (string): The URL the article was crawled from
  • citationUrl (string): The public URL the agent cites
  • indexedAt (string): ISO 8601 timestamp the article was indexed

Error Responses:

  • 404 Article '{article_id}' not found in the corpus for index '{index_name}' locale '{locale}'. This is also returned when the locale has no corpus
  • 422: locale is missing or invalid

Trigger Reindex

Endpoint: POST /indexes/{index_name}/help-center/reindex

Queues a fresh crawl of the help center for one locale. The crawl runs in the background; poll List Locales or Get Corpus and watch indexedAt to see when it lands. Requires an Admin key. No request body.

ParameterTypeRequiredDescription
localestringYesThe locale to reindex
curl -X POST 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/help-center/reindex?locale=en' \
--header 'Authorization: Bearer {api_key}'

Example Response:

{
"indexName": "my-ecom-store",
"locale": "en",
"status": "queued",
"indexedAt": "2026-09-08T02:15:41+00:00"
}
  • status (string): Always queued on success
  • indexedAt (string or null): The corpus freshness before this run, or null if the locale has never been indexed

Reindexing is limited to one request per index every 60 seconds, across all locales. A second request inside that window returns 429 Reindex was triggered too recently; retry after {seconds}s. A request that returns 429 or 503 did not queue a crawl.

Error Responses:

  • 403 This operation requires an admin-scoped API key.
  • 422: locale is missing or invalid
  • 429 Reindex was triggered too recently; retry after {seconds}s.
  • 503 Help-center reindexing is temporarily unavailable.

Agentic Conversation Behavior Overview

Context Management

The system maintains conversation context across interactions:

  • Context Continuity: Previous conversation context is used to inform current responses
  • Product Context: When documentIds are provided, the system fetches those products and uses their information to provide more relevant responses. Use contextFields to limit which product fields are included.
  • Extra Context: When extraContext is provided, the system passes it to the agent as additional context for the current request before the user's query.
  • Session Tracking: sessionId and userId help maintain context throughout a user's session

Extra Context

Use extraContext to provide request-specific context that should help the agent respond to the user's query, such as the current page, campaign, or browsing context. The value must be a string. Empty or whitespace-only values are ignored.

extraContext is used internally for the agent prompt and is not returned by GET /indexes/{index_name}/agentic-search/conversations/{conversation_id}. Treat it as public, user-controlled input like q: do not include secrets, sensitive personal information, or privileged assumptions that should not influence the model.

Conversation Retention and Limits

  • Retention. A conversation is kept for 30 days after its last activity (a new turn or a read), then deleted. Reads and feedback for a deleted conversation fail, and passing its ID to /converse returns 400.
  • Stored history. The 100 most recent turns of a conversation are stored and returned by Get Conversation. Older turns are dropped. The agent itself only considers the most recent turns when composing a reply, so very long conversations do not keep growing the context the model sees.
  • Hard limit. A conversation accepts at most 1000 user messages. The turn that reaches the limit is answered normally and is followed by a conversation-end event. Any later /converse request with that conversationId returns 400 This conversation has reached the maximum of 1000 user messages and cannot accept more. Start a new conversation to continue.
  • User and anonymous conversations. A conversation started with a userId in its first turn belongs to that user: it is given a title and appears in List Conversations for that userId. A conversation started without userId is anonymous: it is stored and can be continued and read by ID, but it never appears in a user's list, even if later turns include a userId. Decide on the first turn.
  • Input limits. q and extraContext are each limited to 2048 characters by default; longer values return 413, and the message reports the limit configured for your index. Both are scanned for payment card numbers, email addresses, and US phone numbers before use, and any found are removed.

Question Triggering - Ambiguous Queries

The system automatically asks clarifying questions when user queries are ambiguous or too broad.

Examples:

  • Query: "jacket" → System asks: "What type of jacket are you looking for (winter coat, rain jacket, casual jacket, work blazer)?"
  • Query: "shoes" → System asks clarifying questions about style, occasion, or gender
  • Query: "dress" → System asks about occasion, style, or fit preferences

When Questions Are Triggered:

  • Queries that are too broad (single word product categories)
  • Queries missing important context (style, occasion, gender, features)
  • Queries that could match many different product types

Division Seed

The divisionSeed parameter tells the agent which product division (e.g. Women's, Men's, Kids) the user is currently browsing. The agent uses this as a default filter for searches without the user needing to state it explicitly.

Allowed values: men, mens, women, womens, kids, kid, beauty

Values are matched case-insensitively and surrounding whitespace is ignored. Any other value returns 400 Invalid divisionSeed: "{value}". Allowed values: men, mens, women, womens, kids, kid, beauty.

The division parameter on Conversation Starters accepts a different set: it has no beauty value.

Example Request:

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--data-urlencode "payload=$(echo -n '{
"q": "show me summer dresses",
"divisionSeed": "womens",
"sessionId": "session-001",
"userId": "user-456"
}' | base64 | tr -d '\n')"

Behavior:

  • The agent defaults searches to the specified division (e.g. applying a division filter for Women's products)
  • If the user explicitly requests a different division (e.g. "show me men's jackets"), the agent switches to the appropriate division
  • Once switched, the agent stays on the new division for subsequent messages until the conversation context indicates otherwise
  • The division is not mentioned to the user unless they ask about it

Interaction with filter:

If you also pass a filter that includes a division constraint (e.g. productDivision:(WOMENS)), the server-side filter takes priority. The agent will not add a conflicting division filter from the seed. In general, prefer using divisionSeed over hardcoded division filters — it allows the agent to adapt when the user's intent changes, rather than being locked to a fixed filter.

Order Lookup

When a logged-in shopper asks about their orders (e.g. "where is my last order?", "what's the status of order #1234?"), the agent can answer directly from the shopper's order history instead of handing them off to a help page. This is enabled by forwarding the shopper's customer access token on the x-marqo-shopify-customer-token header.

Forwarding the token:

  • Your trusted, server-side backend (e.g. Shopify Hydrogen, Next.js, Remix) owns the shopper's authenticated storefront session and obtains a per-session customer access token from your commerce platform.
  • Forward that token on the x-marqo-shopify-customer-token header with each /converse request you make on the shopper's behalf. Send the token value exactly as issued by the platform.
  • Forward the token from your backend over your server-to-server channel. Because the order token must be sent as a header, browser clients using EventSource (which cannot set custom headers) are not suitable for authenticated order lookups — use the fetch + ReadableStream approach instead.

What the agent can answer:

  • Recent orders — "where is my last order?", "what did I order recently?". The agent returns the shopper's most recent order(s).
  • A specific order by number — "where is order #1234?", including branded or custom order numbers (e.g. ORD-2024-001). Lookups by order number are not limited to recent orders — they can reach orders of any age.
  • Disambiguation — when the shopper has multiple recent orders and the request is ambiguous, the agent asks which one they mean (e.g. "Which order — #1234 (delivered), #1230 (in transit), or #1228 (processing)?") rather than guessing.

Answers can include order status, fulfillment and tracking details, line items, and totals.

Scope and security:

  • The token is scoped to a single shopper. The agent can only read that shopper's own orders — it cannot read another customer's orders, and there is no parameter (such as a customer ID) that the model can set to widen the scope.
  • Order lookups are strictly read-only. The agent never creates, cancels, or modifies orders.
  • Retrieved order data is used only to compose the answer for the current request.

Missing or expired token:

  • No token passed. If a shopper asks an order question without the x-marqo-shopify-customer-token header (e.g. a logged-out visitor), the agent does not attempt a lookup and instead invites the shopper to log in.
  • Expired or invalid token. Customer access tokens are short-lived. If the forwarded token has expired or is rejected mid-conversation, the agent stops attempting the lookup and asks the shopper to log in again. There is no server-side retry — the token is per-shopper and short-lived by design.
  • The /converse request still succeeds in both cases. A missing or expired token does not produce an HTTP error to your backend — the response is a normal SSE stream, and the prompt to log in is delivered in-band as part of the agent's reply.
  • Non-order questions are unaffected. Product discovery and other non-order questions continue to work normally, with or without a token and without re-authentication.
  • Recovering. Once the shopper (re-)authenticates, forward a fresh token on the next /converse request and order lookups resume.

Supported platforms:

  • Shopify — forward the shopper's Shopify customer access token.

Support for additional commerce platforms is coming. Each platform will use its own header (e.g. x-marqo-{platform}-customer-token).

Example Request:

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
--header 'x-marqo-index-id: abc123-my-ecom-store' \
--header 'x-marqo-shopify-customer-token: {shopper_customer_access_token}' \
--data-urlencode "payload=$(echo -n '{
"q": "where is my last order?",
"sessionId": "session-001",
"userId": "user-456"
}' | base64 | tr -d '\n')"

Implementation Notes

Streaming Response Handling

When using the converse endpoint, you must handle Server-Sent Events (SSE). The response will stream multiple events, each containing different parts of the response.

Example: Using EventSource

EventSource does not support custom headers natively. If your setup allows the x-marqo-index-id header to be set via other means (e.g., cookies or a proxy), you can use EventSource with named event listeners:

const requestData = {
q: "red dress",
sessionId: "session-001",
userId: "user-456",
};

const payload = btoa(JSON.stringify(requestData));
const url = `https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse?payload=${encodeURIComponent(payload)}`;

const eventSource = new EventSource(url);

let agentMessage = "";
let latestMessageId = null;
let conversationId = null;

eventSource.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
agentMessage += data.message;
});

eventSource.addEventListener("category-hits", (event) => {
const data = JSON.parse(event.data);
console.log("Categories:", data.categoryHits);
});

eventSource.addEventListener("suggestions", (event) => {
const data = JSON.parse(event.data);
console.log("Suggestions:", data.suggestions);
});

eventSource.addEventListener("message-id", (event) => {
const data = JSON.parse(event.data);
latestMessageId = data.messageId;
});

eventSource.addEventListener("conversation-id", (event) => {
const data = JSON.parse(event.data);
conversationId = data.conversationId;
console.log("Conversation ID:", conversationId);
});

eventSource.addEventListener("auth-required", (event) => {
const data = JSON.parse(event.data);
console.log("Login needed:", data.reason, data.loginUrl);
});

eventSource.addEventListener("conversation-end", (event) => {
const data = JSON.parse(event.data);
console.log("Conversation full, start a new one:", data.reason);
});

eventSource.addEventListener("error", (event) => {
if (!event.data) return; // EventSource also fires "error" on connection failures
const data = JSON.parse(event.data);
console.error("Server error:", data.error, data.status);
});

eventSource.addEventListener("stream-end", () => {
console.log("Full message:", agentMessage);
console.log("Latest agent message ID:", latestMessageId);
eventSource.close();
});

Example: Using fetch with ReadableStream (supports custom headers)

const requestData = {
q: "red dress",
sessionId: "session-001",
userId: "user-456",
};

const payload = btoa(JSON.stringify(requestData));
const url = `https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse?payload=${encodeURIComponent(payload)}`;

const response = await fetch(url, {
method: "GET",
headers: {
"x-marqo-index-id": "abc123-my-ecom-store",
},
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";

while (true) {
const { done, value } = await reader.read();
if (done) break;

buffer += decoder.decode(value, { stream: true });
const parts = buffer.split("\n\n");
buffer = parts.pop();

for (const part of parts) {
const eventMatch = part.match(/^event: (.+)$/m);
const dataMatch = part.match(/^data: (.+)$/m);
if (!eventMatch || !dataMatch) continue;

const eventType = eventMatch[1];
const data = JSON.parse(dataMatch[1]);

switch (eventType) {
case "message":
console.log("Text delta:", data.message);
break;
case "category-hits":
console.log("Categories:", data.categoryHits);
break;
case "suggestions":
console.log("Suggestions:", data.suggestions);
break;
case "message-id":
console.log("Latest agent message ID:", data.messageId);
break;
case "conversation-id":
console.log("Conversation ID:", data.conversationId);
break;
case "auth-required":
console.log("Login needed:", data.reason, data.loginUrl);
break;
case "conversation-end":
console.log("Conversation full, start a new one:", data.reason);
break;
case "error":
console.error("Error:", data.error, data.status);
break;
case "stream-end":
console.log("Stream complete");
break;
}
}
}