curl --request GET \
--url https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id} \
--header 'Authorization: Bearer <token>' \
--header 'X-Namespace: <api-key>'import requests
url = "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}"
headers = {
"Authorization": "Bearer <token>",
"X-Namespace": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {Authorization: 'Bearer <token>', 'X-Namespace': '<api-key>'}
};
fetch('https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}', 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/{sync_config_id}/jobs/{sync_job_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"X-Namespace: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("X-Namespace", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}")
.header("Authorization", "Bearer <token>")
.header("X-Namespace", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
request["X-Namespace"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"sync_config_id": "<string>",
"internal_id": "<string>",
"namespace_id": "<string>",
"sync_job_id": "<string>",
"status": "running",
"trigger": "scheduled",
"phase": "<string>",
"total_files": 1,
"files_synced": 0,
"files_failed": 0,
"files_verified": 1,
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"error": "<string>",
"resumed_via": "<string>",
"metadata": {},
"progress_percent": 50,
"throughput_files_per_min": 1,
"lag_seconds": 1,
"current_cursor": "<string>",
"progress": {}
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}Get Sync Job
Get details for a specific sync job.
Returns the full job record including status, file counts, start/completion times, and any error messages.
curl --request GET \
--url https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id} \
--header 'Authorization: Bearer <token>' \
--header 'X-Namespace: <api-key>'import requests
url = "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}"
headers = {
"Authorization": "Bearer <token>",
"X-Namespace": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {Authorization: 'Bearer <token>', 'X-Namespace': '<api-key>'}
};
fetch('https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}', 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/{sync_config_id}/jobs/{sync_job_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"X-Namespace: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("X-Namespace", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}")
.header("Authorization", "Bearer <token>")
.header("X-Namespace", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/jobs/{sync_job_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
request["X-Namespace"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"sync_config_id": "<string>",
"internal_id": "<string>",
"namespace_id": "<string>",
"sync_job_id": "<string>",
"status": "running",
"trigger": "scheduled",
"phase": "<string>",
"total_files": 1,
"files_synced": 0,
"files_failed": 0,
"files_verified": 1,
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"error": "<string>",
"resumed_via": "<string>",
"metadata": {},
"progress_percent": 50,
"throughput_files_per_min": 1,
"lag_seconds": 1,
"current_cursor": "<string>",
"progress": {}
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}{
"error": {
"details": {
"id": "ns_123",
"resource": "namespace"
},
"message": "Namespace not found",
"type": "NotFoundError"
},
"status": 404,
"success": false
}Authorizations
Mixpeek API key, sent as Authorization: Bearer mxp_sk_.... Create one in Studio under Settings → API Keys, or with an admin key via POST /v1/organizations/users/{user_email}/api-keys. A missing header returns 403; an invalid or revoked key returns 401.
Namespace id (ns_...), not the namespace name. This scopes the request rather than authenticating it, and it is required on every operation marked x-mixpeek-namespace-scoped.
Response
Successful Response
Execution record for a single storage sync run.
Created when a sync is triggered (manually or by scheduler). Tracks progress, metrics, and errors for the sync execution.
Job Lifecycle: records are BORN status=RUNNING (pre-dispatch, before the lock attempt) → COMPLETED/FAILED/INTERRUPTED. started_at=None marks the born-but-not-yet-executing window; there is no PENDING status.
Tracked Metrics:
- files_synced: Successfully created objects
- files_failed: Objects sent to Dead Letter Queue
- started_at/completed_at: Timing for duration calculation.
started_at is the CURRENT ATTEMPT's execution start, stamped at the
RUNNING transition (mark_sync_job_running) — None while queued. The
document's provider-level created_at is record creation, so
created_at→started_at is record-creation-to-execution-start (dispatch
- admission + pre-RUNNING setup), NOT queue time alone. Rows written before this stamping existed (no metadata.started_at_source) carry a construction time here; their execution duration is unknown, not measured.
Identifier of the sync configuration that spawned this job.
Organization scope identifier.
Namespace scope identifier.
Unique identifier for the sync job.
Current status of the sync job.
running, completed, failed, interrupted, skipped What started this job: scheduled (the polling loop), manual (a person, through the trigger endpoint), or resume (continuation of a sliced run). None on records written before this field shipped, which means 'not recorded' and NOT 'unknown trigger' — those jobs carry the free-form metadata.triggered_by string instead.
scheduled, manual, resume Human-readable phase within a RUNNING job for observability (e.g. '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 expected for this sync run.
x >= 0Number of files synced successfully in this job.
x >= 0Number of files that failed to sync in this job.
x >= 0OPTIONAL. 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.
x >= 0Execution 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.
Timestamp when the job completed.
Last progress update timestamp for this job.
Last error encountered during the job.
1000Set 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.
Optional metadata captured during execution (provider stats, cursors, etc.).
Derived percent complete when total_files is known.
0 <= x <= 100Derived successful-file throughput for the job.
x >= 0Seconds since the latest progress update for running jobs.
x >= 0Latest provider cursor/page token captured for this job.
Derived progress summary for API observability.
Was this page helpful?

