Syncing a batch

View as MarkdownOpen in Claude

When you append datapoints to a dataset, the datapoints land on the dataset — but a batch built from that dataset already has its tasks materialised from setup. A sync reconciles the two: it creates tasks for the datapoints added to the batch’s dataset since setup or the last sync, so participants can start annotating them.

This guide covers what a sync does, how to trigger one manually, how to poll its progress, and how to have syncs run automatically.

What a sync does

At setup, a batch turns every datapoint in its dataset into a task and organises those tasks into task groups. Appending adds datapoints to the dataset but leaves the batch’s tasks untouched. A sync closes that gap:

  • It finds datapoints that don’t yet have a task in the batch (the delta since the last sync).
  • It creates one task per new datapoint and slots them into task groups, following the batch’s existing grouping:
    • Fixed-size grouping (tasks_per_group): the open, partial group is topped up first, then any remaining datapoints are chunked into new groups.
    • Predetermined grouping (task_group_id in the schema): datapoints join the existing group that carries their group key, or start a new keyed group.
  • It updates the batch’s task and task-group counts.

Syncs are V4-only (the dataset must be a V4/schema dataset), and the batch must be READY — a batch that hasn’t been set up yet has no tasks to extend and must go through setup instead.

A sync only ever adds tasks for new datapoints. It never removes tasks, and no participant is assigned the same task group twice — including groups that grew during a sync.

Syncing manually

Trigger a sync with an empty POST. The batch’s attached dataset is synced.

$POST /api/v1/data-collection/batches/{batch_id}/sync

The request returns 202 Accepted immediately with a sync job — the actual task creation happens asynchronously.

1{
2 "batch_id": "0192a3b4-d6e7-7f8a-0b1c-2d3e4f5a6b7c",
3 "dataset_id": "0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d",
4 "sync_id": "01935c2d-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
5 "status": "queued",
6 "created_at": "2026-07-15T10:30:00.000Z",
7 "updated_at": "2026-07-15T10:30:00.000Z"
8}

Keep the sync_id — you’ll use it to poll for completion.

The request is rejected with a 400 if the batch has no dataset attached, or if the batch isn’t in READY status.

Polling a sync

Poll the sync job with the batch_id and the sync_id from the trigger response.

$GET /api/v1/data-collection/batches/{batch_id}/syncs/{sync_id}

Sync status

StatusDescription
queuedJob created and enqueued; task creation not started yet
processingTasks are being created
completeSync finished — result counts are populated
failedSync could not complete — see reason

A complete job includes counts describing what the sync did:

1{
2 "batch_id": "0192a3b4-d6e7-7f8a-0b1c-2d3e4f5a6b7c",
3 "dataset_id": "0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d",
4 "sync_id": "01935c2d-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
5 "status": "complete",
6 "created_at": "2026-07-15T10:30:00.000Z",
7 "updated_at": "2026-07-15T10:30:04.000Z",
8 "tasks_created": 3,
9 "datapoints_processed": 3,
10 "groups_created": 1,
11 "groups_expanded": 0
12}
FieldDescription
tasks_createdNumber of new tasks materialised this sync
datapoints_processedNumber of appended datapoints handled
groups_createdNew task groups created
groups_expandedExisting task groups grown — only non-zero for predetermined grouping, where appended datapoints join a group that carries their key. Always 0 for fixed-size (tasks_per_group) batches.

If nothing has changed since the last sync, the job still completes — with all counts at 0.

A failed job carries a reason, for example when an import is in progress on the dataset while the sync runs:

1{
2 "status": "failed",
3 "reason": "Dataset 0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d has an import in progress. Retry the sync once it completes."
4}

Auto-sync

Rather than triggering a sync after every append, you can have a batch sync itself whenever datapoints are added to its dataset. Enable it by patching the batch:

$PATCH /api/v1/data-collection/batches/{batch_id}
1{
2 "auto_sync_enabled": true
3}

With auto-sync on, every successful append to the dataset automatically enqueues a sync for the batch — no separate POST .../sync call needed. The append response returns as soon as the datapoints are written; the sync then runs asynchronously, exactly as a manual one does, and you can poll it the same way.

Enabling auto-sync on a batch that is already READY triggers an immediate catch-up sync, so any datapoints appended while it was off are materialised right away rather than waiting for the next append.

To turn it off, patch auto_sync_enabled back to false.

Recipe: append with auto-sync

1

Enable auto-sync on the batch: PATCH /batches/{batch_id} with { "auto_sync_enabled": true }.

2

Append datapoints: POST /datasets/{dataset_id}/datapoints. Check the accepted / rejected counts in the response.

3

A sync is enqueued automatically. Read the batch (GET /batches/{batch_id}) — while a sync is running, the active_sync field carries its sync_id and start time.

4

Poll GET /batches/{batch_id}/syncs/{sync_id} until it reaches complete, then confirm the new total_task_count on the batch.

Concurrency

Syncs for a single batch run one at a time — they’re serialised, so you never need to space out your requests. If a sync is already in flight when another is triggered (including an auto-sync fired by a fresh append), the in-flight active_sync on the batch record tells you so, and the redundant trigger is coalesced away. Because task creation is deterministic, retries and redeliveries converge on the same result rather than double-creating tasks.


By using AI Task Builder, you agree to our AI Task Builder Terms.