Sync a schema

Create and update lists and indexes to match a schema document, and optionally delete the ones its scope manages that it no longer declares. See schema sync for how documents, scopes, rebuilds and pruning work.

POST https://api.jsonpad.io/sync-schema

Example

cURL
123456789101112131415curl https://api.jsonpad.io/sync-schema?dryRun=true \ -H "Content-Type: application/json" \ -H "x-api-token: <YOUR TOKEN>" \ -d '{ "scope": "recipe-app", "lists": { "recipes": { "name": "Recipes", "indexable": true, "indexes": { "slug": { "pointer": "/slug", "alias": true } } } } }'

Parameters

  • optional
    dryRunbooleanhttps://api.jsonpad.io/sync-schema?dryRun=trueReturn the plan without changing anything. The response says whether a real sync would be refused, in blockedBy.
  • optional
    allowRebuildbooleanhttps://api.jsonpad.io/sync-schema?allowRebuild=trueAllow changes to the pointer of an index in a list that has items. The index is rebuilt in the background, and filtering, ordering and alias lookups that use it are refused until the rebuild finishes. Without this, a sync that includes such a change is refused.
  • optional
    prunebooleanhttps://api.jsonpad.io/sync-schema?prune=trueAlso delete the lists and indexes the document's scope manages that the document no longer declares. The document must have a scope. See pruning for which lists and indexes are deleted.
  • optional
    allowDestructivebooleanhttps://api.jsonpad.io/sync-schema?prune=true&allowDestructive=trueAllow a prune to delete lists that have items (the items are deleted too) and guard indexes. Without this, a prune that includes such a delete is refused.

Request headers

  • required
    x-api-tokenstringYour API token. The token needs the sync-schema permission, and the permission for each change the sync makes, including permission to delete what a prune deletes.

Request body

A schema document. See the document.

  • optional
    scopestringThe scope this document manages. 1-50 letters, numbers, hyphens and underscores. See scopes.
  • required
    listsobjectLists, keyed by path name. Each list can set name, description, tags, schema, readonly, realtime, protected, indexable and indexes (indexes keyed by path name, each of which can set name, description, tags, pointer, valueType, alias, sorting, filtering, searching, guard and defaultOrderDirection). Fields that are left out are left as they are.

Response body

200 OK
{
syncId: "6f0e3e1c-9a53-4b53-9d0b-3e0c7bbd8a41"
dryRun: false
applied: true
prune: false
scope: "recipe-app"
summary: {
create: 2
update: 0
adopt: 0
delete: 0
noChange: 0
error: 0
builds: 1
destructive: 0
}
changes: [
0: {
resourceType: "list"
list: "recipes"
listId: "1bbd0b1e-4b3a-4c52-8f2a-0b8b0a2b5d0e"
action: "create"
fields: {
name: {
from: null
to: "Recipes"
}
indexable: {
from: null
to: true
}
tags: {
from: null
to: [
0: "recipe-app"
]
}
}
}
1: {
resourceType: "index"
list: "recipes"
index: "slug"
listId: "1bbd0b1e-4b3a-4c52-8f2a-0b8b0a2b5d0e"
indexId: "0c7b5c55-7d0f-4f5c-a8d7-5bb2f6d3a0e1"
action: "create"
fields: {
pointer: {
from: null
to: "/slug"
}
alias: {
from: null
to: true
}
}
build: {
reason: "created"
items: 0
requiresConfirmation: false
buildStatus: "building"
}
}
]
blockedBy: null
}
  • syncIdstringIdentifies this sync in the attachments of the events it logs.
  • appliedbooleanWhether the changes were made. Always false in a dry run.
  • summaryobjectHow many changes have each action, how many index builds the sync starts, and how many deletes are destructive.
  • changesobject[]

    One entry for every list and index in the document, in document order, followed (when pruning) by the lists and indexes the scope manages that the document doesn't declare. action is create, update, adopt, delete, no-change or error. fields has the current and new value of each field that changes.

    build is included when the change builds an index: reason is created or pointerChanged, items is how many items the build has to visit, requiresConfirmation says whether it needs allowRebuild, and buildStatus is the index's status once the sync has been applied.

    delete is included when a prune deletes the list or index: destructive says whether it needs allowDestructive, and for a list, items and indexes say how many items and indexes are deleted with it.

    warnings and errors are included when there are any. Each error has the same name, code and message as the equivalent API request's error.

  • blockedByobject | nullWhy the sync wasn't applied (or, in a dry run, wouldn't be): SCHEMA_SYNC_PLAN_HAS_ERRORS, SCHEMA_SYNC_PRUNE_WOULD_EMPTY_SCOPE, SCHEMA_SYNC_REBUILD_NOT_ALLOWED or SCHEMA_SYNC_DESTRUCTIVE_NOT_ALLOWED.
422 Unprocessable Entity

When a sync is refused, nothing is changed. The response has the usual error name, code and message, as well as the whole plan described above, so you can see which changes need fixing. The JS SDK's syncSchema returns the plan rather than throwing, so check applied.

Response headers

No response headers

2026-09-15