Reference

REST API

The routes of the Zaproo Search REST API, grouped by area, with who may call it.

Basics

The API lives at https://api.search.zaproo.cloud. Every request body and response is JSON, every route except the health checks sits under /v1, and every request authenticates with one header:

-H "Authorization: Bearer zs_sk_..."

The bearer is a secret key (zs_sk_…) for a server, a public key (zs_pk_…) for the storefront routes, or the cabinet's session token for a signed-in user. You create keys in the cabinet, on the project's API keys page; see API keys. The project id in each path is in the cabinet URL, /app/p/<project id>/..., and on the project's Settings page.

Who may call a route is printed under each one:

LabelMeans
AnyoneNo credentials.
No credentialsSign-in and account recovery: the route takes its own proof (a password, an emailed token, a refresh cookie).
Signed-in userA cabinet session of any user.
Organization member, admin, ownerA cabinet session whose role in the organization is at least this one. Roles rank owner, admin, member.
Project member or admin (signed in)A cabinet session with at least that role in the project's organization. API keys cannot call these routes.
Project member or any secret keyA cabinet session of a member, or a secret key of the project with read or full access.
Project admin or a full-access secret keyA cabinet session of an admin, or a secret key of the project with full access.
Public key from an allowed origin, or a secret keyA public key whose request comes from one of its allowed origins, or a secret key of the same project.

An id that belongs to another organization or project answers 404, never 403, so ids cannot be probed. A key with an index scope gets 404 for every other index.

Errors share one shape:

{"error": {"code": "PROFILE_INVALID", "message": "...", "details": [{"path": "queryFields.title", "message": "..."}]}}
Writes to documents, a reindex and a suggestion rebuild answer 202 with {"taskId": "..."}. Poll the task under Tasks until it is done.

Storefront

The three routes a storefront calls. They take a public handle in the path instead of a project id. POST /v1/events/:profileKey takes a bare JSON array of 1 to 100 click, add-to-cart, purchase or suggestion-click events and answers 202; see Event tracking.

POST/v1/search/:profileKeyPublic key from an allowed origin, or a secret keyPOST/v1/suggest/:suggestKeyPublic key from an allowed origin, or a secret keyPOST/v1/events/:profileKeyPublic key from an allowed origin, or a secret key

These routes answer the CORS preflight for every origin, without cookies, so a shop's pages can call them from the browser with a public key. The key's allowed origins are checked on the real request. A server sends no Origin header, so call them from a server with a secret key.

Indices

See Indices and languages, Mapping and fields and Reindex. A mapping change, reindex or replace session that would break a profile, rule, facet, autocomplete field or data source answers 409 MAPPING_BREAKS_CONFIG; details lists each use to change first.

A shop platform plugin, such as the Magento 2 module, reports itself with PUT .../integration (body platform, name, optional url and version, settings.manageMapping) each time its settings change, and GET .../:indexId returns it as integration. Only a full-access secret key may connect one; a signed-in user gets 403 INTEGRATION_KEY_ONLY. While settings.manageMapping is on, PUT .../mapping from the plugin's own key only adds the fields the saved mapping lacks and keeps every saved field and the language, and a PUT or PATCH .../mapping from anyone else answers 409 MAPPING_MANAGED_BY_INTEGRATION if it removes a field. While any integration is connected, PUT .../feed and POST .../feed/sync answer 409 INDEX_HAS_INTEGRATION. DELETE .../integration disconnects it, answers 204 and is safe to repeat. See Integrations.

PUT .../:indexId takes { "name" }, { "folderId" } or both. name renames the index; a name the project already uses answers 409 INDEX_NAME_TAKEN. folderId files the index in a folder of the project, and null moves it out; an unknown folder answers 404 INDEX_FOLDER_NOT_FOUND. DELETE .../:indexId takes { "name" } too: the index name exactly as saved, or it answers 400 INDEX_NAME_MISMATCH and deletes nothing. See Delete an index.

GET .../indices lists the indices in the order the cabinet shows. PUT .../indices/order saves a new one: { "ids" } with every index id of the project once, or it answers 400 INDEX_ORDER_MISMATCH. A new index goes last.

GET/v1/projects/:projectId/indicesProject member or any secret keyPOST/v1/projects/:projectId/indicesProject admin or a full-access secret keyPUT/v1/projects/:projectId/indices/orderProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexIdProject member or any secret keyPUT/v1/projects/:projectId/indices/:indexIdProject admin or a full-access secret keyDELETE/v1/projects/:projectId/indices/:indexIdProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexId/mappingProject member or any secret keyGET/v1/projects/:projectId/indices/:indexId/mapping/usageProject member or any secret keyPUT/v1/projects/:projectId/indices/:indexId/mappingProject admin or a full-access secret keyPATCH/v1/projects/:projectId/indices/:indexId/mappingProject admin or a full-access secret keyPUT/v1/projects/:projectId/indices/:indexId/integrationA full-access secret keyDELETE/v1/projects/:projectId/indices/:indexId/integrationProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexId/facetsProject member or any secret keyPUT/v1/projects/:projectId/indices/:indexId/facetsProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/reindexProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/reindex/cancelProject admin or a full-access secret key

Every index carries folderId (its cabinet folder, or null) and dataUpdatedAt (when its documents last changed, or null). See Last data update.

Index folders

Folders only organize the cabinet list, one level deep. Search, API keys and plugins ignore them. POST and PUT take { "name" }, unique in the project, 1 to 100 characters; a taken name answers 409 INDEX_FOLDER_NAME_TAKEN. GET lists them in the cabinet order. PUT .../index-folders/order saves a new one: { "ids" } with every folder id of the project once, or it answers 400 INDEX_FOLDER_ORDER_MISMATCH. A new folder goes last. DELETE answers 204 and moves the folder's indices to the top level. See Organize indices in folders.

GET/v1/projects/:projectId/index-foldersProject member or any secret keyPOST/v1/projects/:projectId/index-foldersProject admin or a full-access secret keyPUT/v1/projects/:projectId/index-folders/orderProject admin or a full-access secret keyPUT/v1/projects/:projectId/index-folders/:folderIdProject admin or a full-access secret keyDELETE/v1/projects/:projectId/index-folders/:folderIdProject admin or a full-access secret key

Documents and full sync

POST .../documents takes a bare JSON array of up to 1000 documents; POST .../documents/delete a bare array of ids. Both accept an Idempotency-Key header. POST .../documents/flush takes no body, deletes every document and answers 202 with taskId and previousDocCount; see Delete all documents. Replace sessions upload a whole catalog and swap it in at commit. See Documents and tasks and Full catalog sync.

POST/v1/projects/:projectId/indices/:indexId/documentsProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/documents/deleteProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/documents/flushProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexId/documentsProject member or any secret keyGET/v1/projects/:projectId/indices/:indexId/documents/:docIdProject member or any secret keyPOST/v1/projects/:projectId/indices/:indexId/replace-sessionsProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionIdProject member or any secret keyPOST/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionId/documentsProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionId/commitProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionId/abortProject admin or a full-access secret key

Tasks

GET/v1/projects/:projectId/tasksProject member or any secret keyGET/v1/projects/:projectId/tasks/:taskIdProject member or any secret key

Search and profiles

POST .../indices/:indexId/search is the secret search by index id: a saved profile by profileKey, or an inline profile to try settings before saving them. See Search API and Search profiles.

GET/v1/projects/:projectId/indices/:indexId/profilesProject member or any secret keyPOST/v1/projects/:projectId/indices/:indexId/profilesProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexId/profiles/:profileIdProject member or any secret keyPUT/v1/projects/:projectId/indices/:indexId/profiles/:profileIdProject admin or a full-access secret keyDELETE/v1/projects/:projectId/indices/:indexId/profiles/:profileIdProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/searchProject member or any secret key

Synonyms

See Synonyms.

GET/v1/projects/:projectId/indices/:indexId/synonymsProject member or any secret keyPOST/v1/projects/:projectId/indices/:indexId/synonymsProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/synonyms/importProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexId/synonyms/exportProject member or any secret keyPUT/v1/projects/:projectId/indices/:indexId/synonyms/:synonymIdProject admin or a full-access secret keyDELETE/v1/projects/:projectId/indices/:indexId/synonyms/:synonymIdProject admin or a full-access secret key

Language groups

Groups are managed from a cabinet session only; API keys see an index's group in languageGroup but cannot change groups. See Language groups.

GET/v1/projects/:projectId/language-groupsProject member (signed in)POST/v1/projects/:projectId/language-groupsProject admin (signed in)GET/v1/projects/:projectId/language-groups/:groupIdProject member (signed in)PUT/v1/projects/:projectId/language-groups/:groupIdProject admin (signed in)DELETE/v1/projects/:projectId/language-groups/:groupIdProject admin (signed in)

Ranking rules

See Ranking rules.

GET/v1/projects/:projectId/indices/:indexId/rulesProject member or any secret keyPOST/v1/projects/:projectId/indices/:indexId/rulesProject admin or a full-access secret keyPUT/v1/projects/:projectId/indices/:indexId/rules/orderProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/rules/testProject member or any secret keyGET/v1/projects/:projectId/indices/:indexId/rules/:ruleIdProject member or any secret keyPUT/v1/projects/:projectId/indices/:indexId/rules/:ruleIdProject admin or a full-access secret keyDELETE/v1/projects/:projectId/indices/:indexId/rules/:ruleIdProject admin or a full-access secret key

Autocomplete

See Autocomplete.

GET/v1/projects/:projectId/indices/:indexId/suggestions/configProject member or any secret keyPUT/v1/projects/:projectId/indices/:indexId/suggestions/configProject admin or a full-access secret keyGET/v1/projects/:projectId/indices/:indexId/suggestions/customProject member or any secret keyPOST/v1/projects/:projectId/indices/:indexId/suggestions/customProject admin or a full-access secret keyDELETE/v1/projects/:projectId/indices/:indexId/suggestions/custom/:suggestionIdProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/suggestions/rebuildProject admin or a full-access secret keyPOST/v1/projects/:projectId/indices/:indexId/suggestProject member or any secret key

Analytics

All three take from, to, compare, device, country and includeInternal. :report is one of queries, no-click, products, positions, filters, autocomplete, rules, refinements, opportunities; the query route takes q. See Search analytics and Reports.

GET/v1/projects/:projectId/indices/:indexId/analyticsProject member or any secret keyGET/v1/projects/:projectId/indices/:indexId/analytics/queryProject member or any secret keyGET/v1/projects/:projectId/indices/:indexId/analytics/:reportProject member or any secret key

API keys

Keys are managed from a cabinet session only; no key can create or revoke another key. Creating a key needs a confirmed email. See API keys.

GET/v1/projects/:projectId/api-keysProject member (signed in)POST/v1/projects/:projectId/api-keysProject admin (signed in)DELETE/v1/projects/:projectId/api-keys/:keyIdProject admin (signed in)

A secret key belongs to one project. An integration given only the key finds that project, { items: [Project] }, with:

GET/v1/api-key/projectsSecret key

Account and sign-in

The cabinet's own routes. refresh and logout read the refresh cookie the cabinet holds. impersonate and impersonation/exit serve Zaproo support: they trade a one-time code from an administrator for a session as the account owner, and end it. See Account and sign-in.

POST/v1/auth/registerNo credentialsGET/v1/auth/verify-emailNo credentialsPOST/v1/auth/resend-verificationSigned-in userPOST/v1/auth/loginNo credentialsPOST/v1/auth/refreshNo credentialsPOST/v1/auth/logoutNo credentialsPOST/v1/auth/forgot-passwordNo credentialsPOST/v1/auth/reset-passwordNo credentialsPOST/v1/auth/impersonateNo credentialsPOST/v1/auth/impersonation/exitSigned-in userGET/v1/auth/meSigned-in userPOST/v1/auth/change-passwordSigned-in userGET/v1/auth/sessionsSigned-in userDELETE/v1/auth/sessions/:familyIdSigned-in user

Organizations, members and projects

See Organizations, members and roles and Projects.

GET/v1/orgsSigned-in userGET/v1/orgs/:orgIdOrganization memberGET/v1/orgs/:orgId/projectsOrganization memberPOST/v1/orgs/:orgId/projectsOrganization adminGET/v1/projects/:projectIdProject member or any secret keyPUT/v1/projects/:projectIdOrganization admin

PUT /v1/projects/:projectId takes any of name, analyticsExcludedIps (up to 50 addresses or CIDR ranges) and analyticsDigest, at least one.

DELETE/v1/projects/:projectIdOrganization adminGET/v1/orgs/:orgId/membersOrganization memberPOST/v1/orgs/:orgId/membersOrganization ownerPUT/v1/orgs/:orgId/members/:userIdOrganization ownerDELETE/v1/orgs/:orgId/members/:userIdOrganization owner

MCP

The MCP server, for AI agents. See MCP setup.

POST/mcpSecret key

Status

GET/v1/statusAnyone

See Status for what it answers. GET /health and GET /ready are probes for the infrastructure that runs the API.

Not allowed while impersonating

When Zaproo support acts as an account owner, these routes answer 403 IMPERSONATION_FORBIDDEN: creating an API key, changing the password, ending a session, changing the plan, and adding, changing or removing a member.