Full catalog sync
When to use a replace session
Upserts and deletes change the documents you name. They cannot remove a product you forgot to delete. A replace session makes the index hold exactly what you send: you open it, send the whole catalog in batches and commit. Search switches to the new catalog in one step, and every document you did not send is gone.
Use a replace session when:
- your shop exports the full catalog on a schedule, for example every night, and you have no reliable list of deleted products;
- the index has drifted from the shop and you want a clean copy;
- you changed the mapping and want to rebuild from your source data instead of from the stored documents.
Use upserts and deletes for changes during the day. They are cheaper, and they keep working while a session is open.
How a session works
Opening a session builds a new, empty version of the index next to the live one, with the saved mapping. Search keeps using the live version the whole time.
- Batches sent to the session go to the new version only.
- Normal upserts and deletes sent while the session is open go to both versions, so they survive the commit.
- Commit waits until every batch is written, then swaps search to the new version in one step.
The index's status is REINDEXING while the session is open, and its buildingVersion is the session's version.
Run a sync
Open a session
POST/v1/projects/:projectId/indices/:indexId/replace-sessionsProject admin or a full-access secret keycurl -X POST https://api.zaproo-search.com/v1/projects/$PROJECT_ID/indices/$INDEX_ID/replace-sessions \
-H "Authorization: Bearer $ZS_KEY"
{
"id": "5d2c9a40-8a51-4c3e-b8f1-2f6d0e7c9b13",
"version": 4,
"status": "OPEN",
"expiresAt": "2026-10-16T15:30:00.000Z",
"commitTaskId": null
}
Only one version can be built at a time. If a reindex or another session is running, the API answers 409 VERSION_BUILDING.
Send the catalog in batches
POST/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionId/documentsProject admin or a full-access secret keyThe body is the same bare array as an upsert, with the same limits: up to 1000 documents and 10 MB per request. Each batch answers 202 with a SESSION_BATCH task. Send an Idempotency-Key with each batch so a retry does not send it twice.
curl -X POST https://api.zaproo-search.com/v1/projects/$PROJECT_ID/indices/$INDEX_ID/replace-sessions/$SESSION_ID/documents \
-H "Authorization: Bearer $ZS_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: nightly-2026-10-16-batch-1" \
-d '[{"id": "tv-1", "title": "55 inch OLED TV", "price": 899}]'
Check every batch
Poll each batch task until it finishes. A document that failed in a batch is not in the new version, so it disappears from search when you commit. Fix and resend failed documents before you commit.
Commit
POST/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionId/commitProject admin or a full-access secret keyThe answer is 202 with a SESSION_COMMIT task. The session moves to COMMITTING and takes no more batches. When the task succeeds, the session is COMMITTED, the index's activeVersion is the session's version and search returns the new catalog.
Watch a session
GET/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionIdProject member or any secret keyThe session's status is one of:
| Status | Meaning |
|---|---|
OPEN | Takes batches. |
COMMITTING | Commit is running. No more batches. |
COMMITTED | The new catalog is live. |
ABORTED | You aborted it. The live index is as it was. |
EXPIRED | It stayed open past expiresAt. The live index is as it was. |
FAILED | The commit failed. The live index is as it was, and the index status is FAILED until the next build. |
The index itself names its open session in openReplaceSessionId. In the cabinet, the Reindex panel on the index overview and on Fields & mapping shows an open session with its status, version and expiry. Sessions are opened, filled and committed through the API only.
Abort a session
POST/v1/projects/:projectId/indices/:indexId/replace-sessions/:sessionId/abortProject admin or a full-access secret keyAborting drops the new version and cancels batches that have not finished. Search never sees any of it. In the cabinet, click Abort session in the Reindex panel. Cancel reindex does not apply to a session.
Session lifetime
A session expires 6 hours after it was opened, counted from the open, not from the last batch. Within a minute of expiresAt, an open session becomes EXPIRED and its new version is dropped. Commit before then. A session that is already committing does not expire.
Errors
| Code | When |
|---|---|
409 VERSION_BUILDING | Opening a session while a reindex or another session builds a version. |
409 SESSION_NOT_OPEN | Sending a batch, committing or aborting a session that is no longer OPEN. |
404 SESSION_NOT_FOUND | The session does not exist or belongs to another index. |
400 INVALID_DOCUMENTS | A batch has documents that do not match the mapping. Nothing from that batch is written. |
Common mistakes
- Committing before every batch task has finished without errors. Commit waits for the batches, but it does not check their results. Failed documents are missing from the new catalog.
- Opening a session and never committing it. The index stays
REINDEXING, and no reindex or breaking mapping change can start until the session expires 6 hours later. Abort it instead. - Running a full sync for a handful of changes. Upserts are enough, and they do not block other builds.
Related
Documents and tasks
Upload and delete documents in batches, follow each write as a task, retry safely with Idempotency-Key, and browse what the index holds.
Reindex and versions
Rebuild an index with its saved mapping and swap it in without downtime, follow or cancel the rebuild, and read activeVersion and buildingVersion.