Skip to main content
POST
/
v1
/
buckets
/
{bucket_id}
/
syncs
Create Sync Configuration
curl --request POST \
  --url https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "connection_id": "<string>",
  "source_path": "my-bucket/videos",
  "sync_mode": "continuous",
  "file_filters": {
    "extensions": [
      ".mp4",
      ".mov"
    ]
  },
  "schema_mapping": {
    "mappings": {
      "category": {
        "source": {
          "key": "category",
          "type": "tag"
        },
        "target_type": "field"
      },
      "content": {
        "blob_type": "auto",
        "source": {
          "type": "file"
        },
        "target_type": "blob"
      }
    }
  },
  "polling_interval_seconds": 300,
  "batch_size": 50,
  "skip_batch_submission": false,
  "skip_duplicates": true,
  "reconcile": {
    "on_delete": true,
    "on_filter_drift": true,
    "on_update": true
  },
  "sync_from": "2026-07-07T00:00:00Z",
  "provider_filters": {
    "collection_ids": [
      "col_abc",
      "col_def"
    ]
  },
  "metadata": {
    "environment": "production",
    "project": "video-pipeline"
  }
}
'
import requests

url = "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs"

payload = {
"connection_id": "<string>",
"source_path": "my-bucket/videos",
"sync_mode": "continuous",
"file_filters": { "extensions": [".mp4", ".mov"] },
"schema_mapping": { "mappings": {
"category": {
"source": {
"key": "category",
"type": "tag"
},
"target_type": "field"
},
"content": {
"blob_type": "auto",
"source": { "type": "file" },
"target_type": "blob"
}
} },
"polling_interval_seconds": 300,
"batch_size": 50,
"skip_batch_submission": False,
"skip_duplicates": True,
"reconcile": {
"on_delete": True,
"on_filter_drift": True,
"on_update": True
},
"sync_from": "2026-07-07T00:00:00Z",
"provider_filters": { "collection_ids": ["col_abc", "col_def"] },
"metadata": {
"environment": "production",
"project": "video-pipeline"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
connection_id: '<string>',
source_path: 'my-bucket/videos',
sync_mode: 'continuous',
file_filters: {extensions: ['.mp4', '.mov']},
schema_mapping: {
mappings: {
category: {source: {key: 'category', type: 'tag'}, target_type: 'field'},
content: {blob_type: 'auto', source: {type: 'file'}, target_type: 'blob'}
}
},
polling_interval_seconds: 300,
batch_size: 50,
skip_batch_submission: false,
skip_duplicates: true,
reconcile: {on_delete: true, on_filter_drift: true, on_update: true},
sync_from: '2026-07-07T00:00:00Z',
provider_filters: {collection_ids: ['col_abc', 'col_def']},
metadata: {environment: 'production', project: 'video-pipeline'}
})
};

fetch('https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'connection_id' => '<string>',
'source_path' => 'my-bucket/videos',
'sync_mode' => 'continuous',
'file_filters' => [
'extensions' => [
'.mp4',
'.mov'
]
],
'schema_mapping' => [
'mappings' => [
'category' => [
'source' => [
'key' => 'category',
'type' => 'tag'
],
'target_type' => 'field'
],
'content' => [
'blob_type' => 'auto',
'source' => [
'type' => 'file'
],
'target_type' => 'blob'
]
]
],
'polling_interval_seconds' => 300,
'batch_size' => 50,
'skip_batch_submission' => false,
'skip_duplicates' => true,
'reconcile' => [
'on_delete' => true,
'on_filter_drift' => true,
'on_update' => true
],
'sync_from' => '2026-07-07T00:00:00Z',
'provider_filters' => [
'collection_ids' => [
'col_abc',
'col_def'
]
],
'metadata' => [
'environment' => 'production',
'project' => 'video-pipeline'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs"

payload := strings.NewReader("{\n \"connection_id\": \"<string>\",\n \"source_path\": \"my-bucket/videos\",\n \"sync_mode\": \"continuous\",\n \"file_filters\": {\n \"extensions\": [\n \".mp4\",\n \".mov\"\n ]\n },\n \"schema_mapping\": {\n \"mappings\": {\n \"category\": {\n \"source\": {\n \"key\": \"category\",\n \"type\": \"tag\"\n },\n \"target_type\": \"field\"\n },\n \"content\": {\n \"blob_type\": \"auto\",\n \"source\": {\n \"type\": \"file\"\n },\n \"target_type\": \"blob\"\n }\n }\n },\n \"polling_interval_seconds\": 300,\n \"batch_size\": 50,\n \"skip_batch_submission\": false,\n \"skip_duplicates\": true,\n \"reconcile\": {\n \"on_delete\": true,\n \"on_filter_drift\": true,\n \"on_update\": true\n },\n \"sync_from\": \"2026-07-07T00:00:00Z\",\n \"provider_filters\": {\n \"collection_ids\": [\n \"col_abc\",\n \"col_def\"\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"project\": \"video-pipeline\"\n }\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"connection_id\": \"<string>\",\n \"source_path\": \"my-bucket/videos\",\n \"sync_mode\": \"continuous\",\n \"file_filters\": {\n \"extensions\": [\n \".mp4\",\n \".mov\"\n ]\n },\n \"schema_mapping\": {\n \"mappings\": {\n \"category\": {\n \"source\": {\n \"key\": \"category\",\n \"type\": \"tag\"\n },\n \"target_type\": \"field\"\n },\n \"content\": {\n \"blob_type\": \"auto\",\n \"source\": {\n \"type\": \"file\"\n },\n \"target_type\": \"blob\"\n }\n }\n },\n \"polling_interval_seconds\": 300,\n \"batch_size\": 50,\n \"skip_batch_submission\": false,\n \"skip_duplicates\": true,\n \"reconcile\": {\n \"on_delete\": true,\n \"on_filter_drift\": true,\n \"on_update\": true\n },\n \"sync_from\": \"2026-07-07T00:00:00Z\",\n \"provider_filters\": {\n \"collection_ids\": [\n \"col_abc\",\n \"col_def\"\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"project\": \"video-pipeline\"\n }\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"connection_id\": \"<string>\",\n \"source_path\": \"my-bucket/videos\",\n \"sync_mode\": \"continuous\",\n \"file_filters\": {\n \"extensions\": [\n \".mp4\",\n \".mov\"\n ]\n },\n \"schema_mapping\": {\n \"mappings\": {\n \"category\": {\n \"source\": {\n \"key\": \"category\",\n \"type\": \"tag\"\n },\n \"target_type\": \"field\"\n },\n \"content\": {\n \"blob_type\": \"auto\",\n \"source\": {\n \"type\": \"file\"\n },\n \"target_type\": \"blob\"\n }\n }\n },\n \"polling_interval_seconds\": 300,\n \"batch_size\": 50,\n \"skip_batch_submission\": false,\n \"skip_duplicates\": true,\n \"reconcile\": {\n \"on_delete\": true,\n \"on_filter_drift\": true,\n \"on_update\": true\n },\n \"sync_from\": \"2026-07-07T00:00:00Z\",\n \"provider_filters\": {\n \"collection_ids\": [\n \"col_abc\",\n \"col_def\"\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"project\": \"video-pipeline\"\n }\n}"

response = http.request(request)
puts response.read_body
{
  "bucket_id": "<string>",
  "connection_id": "<string>",
  "internal_id": "<string>",
  "namespace_id": "<string>",
  "source_path": "<string>",
  "created_by_user_id": "<string>",
  "locked": true,
  "sync_config_id": "<string>",
  "file_filters": {
    "include_patterns": [
      "<string>"
    ],
    "exclude_patterns": [
      "<string>"
    ],
    "min_size_bytes": 1,
    "max_size_bytes": 1,
    "modified_after": "2023-11-07T05:31:56Z",
    "modified_before": "2023-11-07T05:31:56Z",
    "mime_types": [
      "<string>"
    ],
    "metadata_filters": [
      {
        "field": "<string>",
        "operator": "contains",
        "value": "<string>"
      }
    ]
  },
  "schema_mapping": {
    "mappings": {}
  },
  "sync_mode": "continuous",
  "polling_interval_seconds": 300,
  "batch_size": 50,
  "create_object_on_confirm": true,
  "skip_duplicates": true,
  "skip_batch_submission": false,
  "reconcile": {
    "on_delete": true,
    "on_update": true,
    "on_filter_drift": true,
    "re_extract_on_update": true,
    "re_extract_fields": [
      "<string>"
    ]
  },
  "status": "PENDING",
  "is_active": true,
  "total_files_discovered": 0,
  "total_files_synced": 0,
  "total_files_failed": 0,
  "total_bytes_synced": 0,
  "created_at": "2023-11-07T05:31:56Z",
  "updated_at": "2023-11-07T05:31:56Z",
  "last_sync_at": "2023-11-07T05:31:56Z",
  "per_shard_last_sync_at": {},
  "next_sync_at": "2023-11-07T05:31:56Z",
  "last_error": "<string>",
  "consecutive_failures": 0,
  "provider_filters": {},
  "source_type": "<string>",
  "metadata": {},
  "locked_by_worker_id": "<string>",
  "locked_at": "2023-11-07T05:31:56Z",
  "lock_expires_at": "2023-11-07T05:31:56Z",
  "pending_full_sync": false,
  "paused": false,
  "pause_reason": "<string>",
  "paused_at": "2023-11-07T05:31:56Z",
  "paused_by_user_id": "<string>",
  "max_objects_per_run": 100000,
  "max_batch_chunk_size": 1000,
  "batch_chunk_size": 100,
  "current_sync_run_id": "<string>",
  "sync_run_counter": 0,
  "batch_ids": [
    "<string>"
  ],
  "task_ids": [
    "<string>"
  ],
  "batches_created": 0,
  "resume_enabled": true,
  "resume_cursor": "<string>",
  "resume_last_primary_key": "<string>",
  "resume_objects_processed": 0,
  "resume_checkpoint_frequency": 1000,
  "current_cursor": "<string>",
  "sync_checkpoints": {},
  "schedule": {},
  "sync_progress": {}
}
{
"status": 123,
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>",
"details": {}
},
"success": false
}
{
"status": 123,
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>",
"details": {}
},
"success": false
}
{
"status": 123,
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>",
"details": {}
},
"success": false
}
{
"status": 123,
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>",
"details": {}
},
"success": false
}
{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}
{
"status": 123,
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>",
"details": {}
},
"success": false
}

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

bucket_id
string
required

Body

application/json

Request to create a bucket sync configuration.

Establishes automated synchronization between a storage connection and a bucket. The sync monitors the source path for changes and ingests files according to the specified mode and filters.

Supported Storage Providers: - google_drive: Google Drive and Workspace shared drives - s3: Amazon S3 and S3-compatible (MinIO, DigitalOcean Spaces, Wasabi) - snowflake: Snowflake data warehouse tables (rows become objects) - sharepoint: Microsoft SharePoint and OneDrive for Business - tigris: Tigris globally distributed object storage

Robustness Features (built-in): - Dead Letter Queue (DLQ): Failed objects tracked with 3 retries before quarantine - Idempotent ingestion: Deduplication via (bucket_id, source_provider, source_object_id) - Distributed locking: Prevents concurrent execution of same sync config - Rate limit handling: Automatic backoff on provider 429 responses - Metrics: Duration, files synced/failed, batches created, rate limit hits

Sync Modes: - continuous: Real-time monitoring with polling interval - one_time: Single bulk import then stops - scheduled: Polling-based batch imports

Requirements: - connection_id: REQUIRED, must be an existing connection - source_path: REQUIRED, path must exist in the storage provider - sync_mode: OPTIONAL, defaults to 'continuous' - All other fields are OPTIONAL with sensible defaults

connection_id
string
required

REQUIRED. Storage connection identifier to sync from. Must reference an existing connection created via POST /organizations/connections. The connection defines the storage provider and credentials. Supported providers: google_drive, s3, snowflake, sharepoint, tigris.

Examples:

"conn_abc123"

"conn_s3_prod"

source_path
string | null

REQUIRED unless provider_filters.use_search_api is true (search-API syncs don't traverse a path; defaults to '/'). Source path within the storage provider to monitor and sync. Path format varies by provider: - s3/tigris: 'bucket-name/prefix' or 'bucket-name'. - google_drive: folder ID or path like '/Marketing/Assets'. - sharepoint: '/sites/SiteName/Shared Documents/folder'. - snowflake: 'DATABASE.SCHEMA.TABLE' or just 'TABLE' if defaults set.

Example:

"my-bucket/videos"

sync_mode
enum<string>
default:continuous

Synchronization mode determining how files are monitored and ingested. OPTIONAL. Defaults to 'continuous'. 'continuous': Actively monitors for new files and syncs immediately. 'one_time': Performs a single sync of existing files then stops. 'scheduled': Syncs on polling intervals only.

Available options:
initial_only,
continuous
Examples:

"continuous"

"one_time"

"scheduled"

file_filters
File Filters · object | null

OPTIONAL. Filters to control which files are synced. When omitted, all files in source_path are synced. Supported filters: - include_patterns: Glob patterns to include (e.g., ['.mp4', '.mov']). - exclude_patterns: Glob patterns to exclude (e.g., ['.tmp', '.DS_Store']). - extensions: File extensions to include (e.g., ['.mp4', '.jpg']). - min_size_bytes: Minimum file size in bytes. - max_size_bytes: Maximum file size in bytes. - modified_after: ISO datetime, only sync files modified after this time. - mime_types: List of MIME types to include (e.g., ['video/', 'image/jpeg']).

Example:
{ "extensions": [".mp4", ".mov"] }
schema_mapping
SchemaMapping · object | null

OPTIONAL. Defines how source data maps to bucket schema fields and blobs. When provided, enables structured extraction of metadata from the sync source. Keys are target bucket schema field names, values define the source extraction method.

Blob Mappings (target_type='blob'): Map files or URLs to blob fields. Use source.type='file' for the synced file itself, or source.type='column'/'metadata' for URLs.

Field Mappings (target_type='field'): Map metadata to schema fields. Source options by provider: - S3/Tigris: 'tag' (object tags), 'metadata' (x-amz-meta-*) - Snowflake: 'column' (table columns) - Google Drive: 'drive_property' (file properties) - All: 'filename_regex', 'folder_path', 'constant'

If omitted, default behavior depends on provider - typically maps file to 'content' blob.

Example:
{
"mappings": {
"category": {
"source": { "key": "category", "type": "tag" },
"target_type": "field"
},
"content": {
"blob_type": "auto",
"source": { "type": "file" },
"target_type": "blob"
}
}
}
polling_interval_seconds
integer
default:300

Interval in seconds between polling checks for new files. OPTIONAL. Defaults to 300 seconds (5 minutes). Must be between 30 and 900 seconds (0.5 to 15 minutes). Only applies to 'continuous' and 'scheduled' sync modes. Lower values mean faster detection but higher API usage.

Required range: 30 <= x <= 900
Examples:

60

300

600

batch_size
integer
default:50

Number of files to process in each batch during sync. OPTIONAL. Defaults to 50 files per batch. Must be between 1 and 100. Larger batches improve throughput but require more memory. Smaller batches provide more granular progress tracking.

Required range: 1 <= x <= 100
Examples:

10

50

100

skip_batch_submission
boolean
default:false

If True, sync objects to the bucket without creating or submitting batches for collection processing. Objects are created in the bucket but no tier processing is triggered. Useful for bulk data migration or when you want to manually control when processing occurs. OPTIONAL. Defaults to False (batches are created and submitted).

Examples:

false

true

skip_duplicates
boolean
default:true

If True, skip files whose source ID already exists in the bucket. If False, replace existing objects when re-syncing. OPTIONAL. Defaults to True.

Examples:

true

false

reconcile
ReconcileSettings · object | null

Controls how Mixpeek reconciles objects when the source changes. on_delete: cascade-delete when source asset is removed (default True). on_update: propagate metadata changes and re-process (default True). on_filter_drift: remove objects that no longer match filters (default True). OPTIONAL. Defaults to all enabled for full consistency.

Example:
{
"on_delete": true,
"on_filter_drift": true,
"on_update": true
}
sync_from
string<date-time> | null

OPTIONAL. Seed the incremental watermark: only assets modified after this timestamp are ingested — the historical backlog is skipped. Use for a 'freshness lane': a second config on an already-backfilling source (with a distinct source_path label) that keeps NEW uploads landing within minutes while the backfill config churns. Omit for a full sync from the beginning.

Example:

"2026-07-07T00:00:00Z"

provider_filters
Provider Filters · object | null

OPTIONAL. Provider-specific pre-filters pushed down to the storage API call. Applied BEFORE file_filters (which are client-side). Each provider defines its own filter schema. Examples: - Iconik: {'collection_ids': ['col_abc']} - Google Drive: {'shared_drive_id': '0AH-Xabc123'} - S3: {'prefix': 'videos/'}

Example:
{ "collection_ids": ["col_abc", "col_def"] }
metadata
Metadata · object | null

Optional custom metadata to attach to the sync configuration. NOT REQUIRED. Arbitrary key-value pairs for tagging and organization. Common uses: project tags, environment labels, cost centers. Maximum 50 keys, values must be JSON-serializable.

Example:
{
"environment": "production",
"project": "video-pipeline"
}

Response

Successful Response

Bucket-scoped configuration for automated storage synchronization.

Defines how files are synced from external storage providers to a Mixpeek bucket. Includes configuration, status, metrics, and robustness control fields.

Supported Providers: google_drive, s3, snowflake, sharepoint, tigris

Built-in Robustness:

  • Distributed locking (locked_by_worker_id, lock_expires_at)
  • Pause/resume control (paused, pause_reason, paused_at)
  • Safety limits (max_objects_per_run, batch_chunk_size)
  • Resume checkpointing (resume_cursor, resume_objects_processed)
  • Batch tracking (batch_ids, task_ids, batches_created)

Metrics Fields:

  • total_files_discovered: Files found in source
  • total_files_synced: Successfully synced files
  • total_files_failed: Files that failed (check DLQ)
  • total_bytes_synced: Total data transferred
  • consecutive_failures: Failure count for auto-suspend
bucket_id
string
required

Target bucket identifier (e.g. 'bkt_marketing_assets').

connection_id
string
required

Storage connection identifier (e.g. 'conn_abc123').

internal_id
string
required

Organization internal identifier (multi-tenancy scope).

namespace_id
string
required

Namespace identifier owning the bucket.

source_path
string
required

Source path in the external storage provider. Format varies by provider: s3/tigris='bucket/prefix', google_drive='folder_id', sharepoint='/sites/Name/Documents', snowflake='DB.SCHEMA.TABLE'.

created_by_user_id
string
required

User identifier that created the sync configuration.

locked
boolean
required
read-only

Whether a worker currently holds this sync's run lock.

sync_config_id
string

Unique identifier for the sync configuration.

file_filters
FileFilters · object | null

Optional filter rules limiting which files are synced.

schema_mapping
SchemaMapping · object | null

Schema mapping defining how source data maps to bucket schema fields. Maps external storage attributes (tags, metadata, columns, filenames) to bucket schema fields and blob properties. When provided, enables structured extraction of metadata from the sync source. See SchemaMapping for detailed configuration options.

sync_mode
enum<string>
default:continuous

Sync mode controlling lifecycle (initial_only or continuous).

Available options:
initial_only,
continuous
polling_interval_seconds
integer
default:300

Polling interval in seconds (continuous mode).

Required range: 30 <= x <= 900
batch_size
integer
default:50

Number of files processed per sync batch.

Required range: 1 <= x <= 100
create_object_on_confirm
boolean
default:true

Whether objects should be created immediately after confirmation.

skip_duplicates
boolean
default:true

Skip files whose hashes already exist in the bucket.

skip_batch_submission
boolean
default:false

Sync-only mode: download and store files in the bucket without running them through the collection processing pipeline. Set to True during initial bulk ingestion, then flip to False to trigger processing once all files are synced.

reconcile
ReconcileSettings · object

Controls how Mixpeek reconciles objects when the source changes. on_delete: cascade-delete when source asset is removed. on_update: propagate metadata changes and re-process. on_filter_drift: remove objects that no longer match filters. All default to True for full consistency.

status
enum<string>
default:PENDING

Current lifecycle status for the sync configuration. PENDING: Not yet started. ACTIVE: Currently running/polling. SUSPENDED: Temporarily paused. COMPLETED: Initial sync completed (for initial_only mode). FAILED: Sync encountered errors.

Available options:
PENDING,
QUEUED,
IN_PROGRESS,
PROCESSING,
COMPLETED,
COMPLETED_WITH_ERRORS,
FAILED,
CANCELED,
INTERRUPTED,
UNKNOWN,
SKIPPED,
DRAFT,
ACTIVE,
ARCHIVED,
SUSPENDED
is_active
boolean
default:true

Convenience flag used for filtering active syncs.

total_files_discovered
integer
default:0

Cumulative count of files found in source across all runs.

Required range: x >= 0
total_files_synced
integer
default:0

Cumulative count of successfully synced files.

Required range: x >= 0
total_files_failed
integer
default:0

Cumulative count of failed files (sent to DLQ after 3 retries).

Required range: x >= 0
total_bytes_synced
integer
default:0

Cumulative bytes transferred across all runs.

Required range: x >= 0
created_at
string<date-time>

When sync configuration was created.

updated_at
string<date-time>

Last modification timestamp.

last_sync_at
string<date-time> | null

When last successful sync completed. Used for incremental syncs.

per_shard_last_sync_at
Per Shard Last Sync At · object

Per-shard last-sync timestamps keyed by shard value (e.g. collection_id). When a new shard is added, its absence here forces a full scan even if the global last_sync_at is set.

next_sync_at
string<date-time> | null

Scheduled time for next sync (continuous/scheduled modes).

last_error
string | null

Most recent error message if sync attempts failed.

Maximum string length: 1000
consecutive_failures
integer
default:0
Required range: x >= 0
provider_filters
Provider Filters · object

Provider-specific pre-filters pushed down to the API call. The sync engine passes these to iter_objects() without interpretation. Each provider defines its own schema. Applied BEFORE file_filters. Examples: Iconik {'collection_ids': [...]}, Google Drive {'shared_drive_id': '...'}

source_type
string | null

Storage provider type for API progress views (for example: s3, google_drive, iconik).

metadata
Metadata · object

Arbitrary metadata supplied by the user.

locked_by_worker_id
string | null

Worker ID that currently holds the lock for this sync

locked_at
string<date-time> | null

Timestamp when lock was acquired

lock_expires_at
string<date-time> | null

Timestamp when lock expires (for stale lock recovery)

pending_full_sync
boolean
default:false

A full sweep was requested (trigger?full_sync=true) while a run held the lock. The finishing run dispatches it automatically on lock release.

paused
boolean
default:false

Whether sync is currently paused (user-controlled)

pause_reason
string | null

Reason for pause

paused_at
string<date-time> | null

Timestamp when paused

paused_by_user_id
string | null

User who paused the sync

max_objects_per_run
integer
default:100000

Hard cap on objects per sync run (prevents runaway syncs)

Required range: x >= 1
max_batch_chunk_size
integer
default:1000

Maximum objects per batch chunk

Required range: 1 <= x <= 1000
batch_chunk_size
integer
default:100

Number of objects per batch chunk (for concurrent processing)

Required range: 1 <= x <= 1000
current_sync_run_id
string | null

UUID for current/last sync run

sync_run_counter
integer
default:0

Increments on each sync execution

Required range: x >= 0
batch_ids
string[]

List of batch IDs created by this sync

task_ids
string[]

List of task IDs for batches

batches_created
integer
default:0

Total number of batches created

Required range: x >= 0
resume_enabled
boolean
default:true

Whether resuming partial runs is enabled

resume_cursor
string | null

Last page/cursor processed (for paginated APIs like Google Drive)

resume_last_primary_key
string | null

Last primary key processed (for database syncs with stable ordering)

resume_objects_processed
integer
default:0

Count of objects processed in current/last run

Required range: x >= 0
resume_checkpoint_frequency
integer
default:1000

How often to checkpoint (in objects). Default: every 1000 objects

Required range: 100 <= x <= 10000
current_cursor
string | null

Convenience mirror of the current resume cursor for API progress views.

sync_checkpoints
Sync Checkpoints · object

Per-(config, shard) high-water checkpoints keyed by shard key (e.g. collection_id for parallel fan-outs, 'pages_N_M' for page-range shards, 'default' for unsharded runs). Each entry holds: pass_id (lexicographically-ordered pass marker), cursor (provider cursor, e.g. JSON-encoded Iconik search_after), objects_processed (forward-only progress guard), modified_since (incremental filter frozen at pass start), completed_at (set when the shard drained its source — the next cycle wraps around to a fresh full pass only after the polling cadence elapses), and updated_at. A NEW job resumes each shard from its checkpoint instead of re-walking from page 1 (2026-06-11 re-scan treadmill).

schedule
Schedule · object | null

Derived scheduling summary: mode, interval, next run, and last successful run.

sync_progress
Sync Progress · object

Derived progress summary for API observability.