curl --request GET \
--url https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/metrics \
--header 'Authorization: Bearer <token>' \
--header 'X-Namespace: <api-key>'import requests
url = "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/metrics"
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}/metrics', 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}/metrics",
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}/metrics"
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}/metrics")
.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}/metrics")
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>",
"status": "<string>",
"is_active": true,
"paused": false,
"total_files_discovered": 0,
"total_files_synced": 0,
"total_files_failed": 0,
"batches_created": 0,
"sync_run_counter": 0,
"consecutive_failures": 0,
"last_error": "<string>",
"last_sync_at": "2023-11-07T05:31:56Z",
"next_sync_at": "2023-11-07T05:31:56Z",
"seconds_since_last_sync": 123,
"is_stale": false,
"intervals_since_last_sync": 0.4,
"stale_after_seconds": 600,
"failure_rate": 0,
"healthy": true,
"dlq_total": 0,
"dlq_by_error": {},
"running_job": false,
"stalled": false,
"stalled_reason": "<string>",
"last_job": {}
}{
"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
}{
"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
}Get Sync Metrics
Operational metrics for a sync in one call.
Folds config totals + health/staleness + the DLQ failure breakdown (grouped by normalized error reason) + the most-recent job’s throughput into a single response — so callers can see “is this sync healthy / is anything backlogged” without stitching /jobs and /dlq or reading logs.
curl --request GET \
--url https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/metrics \
--header 'Authorization: Bearer <token>' \
--header 'X-Namespace: <api-key>'import requests
url = "https://api.mixpeek.com/v1/buckets/{bucket_id}/syncs/{sync_config_id}/metrics"
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}/metrics', 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}/metrics",
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}/metrics"
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}/metrics")
.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}/metrics")
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>",
"status": "<string>",
"is_active": true,
"paused": false,
"total_files_discovered": 0,
"total_files_synced": 0,
"total_files_failed": 0,
"batches_created": 0,
"sync_run_counter": 0,
"consecutive_failures": 0,
"last_error": "<string>",
"last_sync_at": "2023-11-07T05:31:56Z",
"next_sync_at": "2023-11-07T05:31:56Z",
"seconds_since_last_sync": 123,
"is_stale": false,
"intervals_since_last_sync": 0.4,
"stale_after_seconds": 600,
"failure_rate": 0,
"healthy": true,
"dlq_total": 0,
"dlq_by_error": {},
"running_job": false,
"stalled": false,
"stalled_reason": "<string>",
"last_job": {}
}{
"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
}{
"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
}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, malformed, unknown, revoked, inactive or expired key returns 401; a key without the permission, scope or plan an operation needs returns 403.
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
Operational metrics for a sync configuration, in one call.
Folds together what previously required stitching the config + /jobs + /dlq: lifetime totals, health/staleness, the DLQ failure breakdown (grouped by normalized error reason), and the most-recent job's throughput. Lets callers answer "is this sync healthy and is anything backlogged?" without circumventing the API with kubectl/log spelunking.
Sync config status (e.g. ACTIVE).
Age of last successful sync; None if never synced.
True when a continuous sync has not progressed for more than TWO of its own polling intervals. Previously the bar was three intervals OR 600 seconds, whichever was larger, so a one-minute sync could miss ten consecutive runs and still read healthy while an hourly one got three. Read it beside intervals_since_last_sync and stale_after_seconds rather than on its own.
How overdue the sync is, measured in its OWN polling intervals: seconds_since_last_sync / polling_interval_seconds. 1.0 means one interval has elapsed, which is normal for a sync about to run. None when the sync has never run. Present so a caller can judge lateness without knowing where the threshold happens to sit.
0.4
The threshold is_stale was evaluated against, in seconds, so the verdict can be checked rather than trusted. max(2 * polling_interval_seconds, 120).
600
total_files_failed / total_files_discovered (0..1).
Composite: active, not paused, no consecutive failures, not stale, running job not stalled. Because it folds in is_stale, a sync more than two intervals overdue reports healthy=false rather than true.
Objects stuck after all retries.
DLQ counts grouped by normalized error reason (IDs stripped).
Show child attributes
Show child attributes
The running job has made no progress: no heartbeat, or nothing discovered or synced, for longer than max(stale_after_seconds, 300). A first run that has not finished yet has no last sync to be stale against, so this is how it reports a stall. Folds into healthy.
Why the running job counts as stalled, when it does.
Summary of the most recent job: status, files_synced/failed, throughput_files_per_min, duration_seconds.
Was this page helpful?

