---
title: "List Sync Jobs"
method: POST
path: "/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs"
tags: ["Bucket Syncs"]
---

# List Sync Jobs

`POST /v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs`

## Request

- Base URL: `https://api.mixpeek.com`
- URL: `https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs`
- Auth: HTTP bearer and API key in header `X-Namespace`

List sync job history for a sync configuration.

Returns paginated job records ordered by most recent first.
Each job includes status, file counts, timing, and error details.
Use the optional status filter to find failed or running jobs.

## Path parameters

- `bucket_id` string, required
- `sync_config_id` string, required

## Query parameters

- `limit` integer, nullable
- `page_size` integer, nullable
- `offset` integer, nullable
- `page` integer, nullable
- `cursor` string, nullable
- `next_cursor` string, nullable
- `after` string, nullable
- `include_total` boolean

## Request body

- ListSyncJobsRequest: Request to list sync job history for a sync configuration.
  - `status` 'running' | 'completed' | 'failed' | 'interrupted' | 'skipped': Lifecycle states for individual storage sync jobs.

## Response `200`

Successful Response

- SyncJobListResponse: Paginated list of sync jobs.
  - `results` SyncJobModel[], required
    - `sync_job_id` string: Unique identifier for the sync job.
    - `sync_config_id` string, required: Identifier of the sync configuration that spawned this job.
    - `internal_id` string, required: Organization scope identifier.
    - `namespace_id` string, required: Namespace scope identifier.
    - `status` 'running' | 'completed' | 'failed' | 'interrupted' | 'skipped': Lifecycle states for individual storage sync jobs.
    - `trigger` 'scheduled' | 'manual' | 'resume': What started a sync job. The job record already carried this as a free-form ``metadata.triggered_by`` string, which is fine for a log line and unusable as a query: a caller asking "has this sync completed a SCHEDULED run since the user connected it" had to match on prose. Those strings STAY, because ``reap_stale_running_jobs`` matches on ``triggered_by == "queued_full_sync"`` to restore ``pending_full_sync``; this enum is additive beside them. THERE IS DELIBERATELY NO ``api`` MEMBER. The trigger endpoint reads ``request.state.auth.user.user_id`` unconditionally, so a key-only caller is not distinguishable from a person there, and a member nothing can emit is a dead field that reads as a real one. Add it when the endpoint can tell the two apart.
    - `phase` string, nullable: Human-readable phase within a RUNNING job for observability (e.g. 'queued' until a worker starts the job, then 'discovering', 'downloading', 'verifying', 're-verifying', 'idle'). Optional and descriptive — distinct from `status`, which is the coarse lifecycle state. Lets a sync that is re-verifying already-synced files (low net-new throughput, low percent) read as healthy rather than stuck. Back-compatible: older jobs have None.
    - `total_files` integer, nullable: Total files expected for this sync run.
    - `files_synced` integer: Number of files synced successfully in this job.
    - `files_failed` integer: Number of files that failed to sync in this job.
    - `files_verified` integer, nullable: OPTIONAL. Files the run re-checked and found already present, as opposed to newly transferred. A re-scan of a settled source is mostly this, so a run with files_synced=0 and files_verified>0 did work and found nothing new, which is a different state from a run that did nothing.
    - `started_at` string, date-time, nullable: Execution start of the CURRENT attempt, stamped at the RUNNING transition. None = not yet started (queued/pre-dispatch). Legacy rows (no metadata.started_at_source) hold a record-construction time instead — not execution evidence.
    - `completed_at` string, date-time, nullable: Timestamp when the job completed.
    - `updated_at` string, date-time, nullable: Last progress update timestamp for this job.
    - `error` string, nullable: Last error encountered during the job.
    - `resumed_via` string, nullable: Set when this job record was reopened and re-run after its worker died without finalizing (value 'acks_late_redelivery': the broker redelivered the original message against the reaped record). On rows that predate per-attempt history (metadata.prior_attempts), this is the only retry signal; its absence proves nothing about whether a job retried.
    - `metadata` object: Optional metadata captured during execution (provider stats, cursors, etc.).
    - `progress_percent` number, nullable: Percent complete: files with an outcome (synced, failed, re-verified, unchanged or quarantined) / total_files when the total is known (total_files, or metadata.total_files_discovered on rows written before total_files was stored); otherwise 100 for a completed or skipped run and 0 for a run that has counted no file yet. Null only for a row with files counted and no total, which no current writer produces: every count write carries the total.
    - `throughput_files_per_min` number, nullable: Derived successful-file throughput for the job.
    - `lag_seconds` integer, nullable: Seconds since the latest progress update for running jobs.
    - `current_cursor` string, nullable: Latest provider cursor/page token captured for this job.
    - `progress` object: Derived progress summary for API observability.
  - `pagination` PaginationResponse, required: PaginationResponse. Cursor-based pagination response: - Use next_cursor for navigation - Total count fields only populated when include_total=true
    - `total` integer, nullable: Number of items matching the request across all pages, filters included. null unless the request set include_total=true (in the body or as ?include_total=true). A counted request that matches nothing returns 0.
    - `page` integer, nullable
    - `page_size` integer, nullable
    - `total_pages` integer, nullable: Number of pages at page_size. null unless include_total=true.
    - `next_page` string, nullable
    - `previous_page` string, nullable
    - `next_cursor` string, nullable
  - `total` integer, required

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `422`: Unprocessable Entity
- `429`: Too Many Requests
- `500`: Internal Server Error
- `503`: Service Unavailable

## Changes

- **2026-10-09** `61a175e8eb9a`: 1 warning, 5 info
  - removed the optional property `detail` from the response with the `422` status
  - added the non-success response with the status `429`
  - added the non-success response with the status `503`
  - added the optional property `success` to the response with the `422` status
  - …2 more
- **2026-09-19** `4bbfcce2371b`: 1 info
  - added the optional property `results/items/trigger` to the response with the `200` status
- **2026-09-15** `d6818abb12f9`: 1 breaking, 1 info
  - response property `results/items/started_at` list-of-types was widened by adding types `null` to media type `application/json` of response `200`
  - added the optional property `results/items/resumed_via` to the response with the `200` status
- **2026-08-31** `daf60765b81d`: 1 warning, 1 info
  - added the new `skipped` enum value to the `results/items/status` response property for the response status `200`
  - added the new `skipped` enum value to the request property `status/anyOf[subschema #1: SyncJobStatus]/`
- **2026-08-25** `7d35e524d98b`: 1 info
  - added the optional property `results/items/files_verified` to the response with the `200` status

[Operation history](https://skmtc.dev/mixpeek/apis/mixpeek-api/changes/v1/buckets/:bucket_id/syncs/:sync_config_id/jobs/post.md)

---

[API](https://skmtc.dev/mixpeek/apis/mixpeek-api.md) - [All operations](https://skmtc.dev/mixpeek/apis/mixpeek-api/llms.txt) - [OpenAPI document](https://skmtc.dev/mixpeek/apis/mixpeek-api/revisions/790bc16455f6?raw)
