curl --request GET \
--url https://api.mixpeek.com/v1/events \
--header 'Authorization: Bearer <token>' \
--header 'X-Namespace: <api-key>'import requests
url = "https://api.mixpeek.com/v1/events"
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/events', 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/events",
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/events"
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/events")
.header("Authorization", "Bearer <token>")
.header("X-Namespace", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixpeek.com/v1/events")
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{
"results": [
{
"seq": 123,
"cursor": "<string>",
"event_type": "<string>",
"resource_type": "<string>",
"operation": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"namespace_id": "<string>",
"payload": {}
}
],
"has_more": true,
"next_cursor": "<string>"
}{
"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
}List change feed events
List this organization’s change feed, ordered and resumable by cursor.
Scope: org-global by default — one ordered sequence across every
namespace and resource type. An X-Namespace header (or namespace_id
query param) narrows it to one namespace’s events. Events recorded
before namespace stamping shipped (2026-08) carry no namespace and are
excluded by ANY namespace filter — a namespace-filtered read is not a
replay of history older than that.
A consumer can be killed mid-stream and resume from its last stored
next_cursor without re-reading or missing anything, as long as it
resumes within the 90-day retention window — events older than that
are permanently expired, not archived. A consumer that has been down
longer than 90 days must resync current state instead of resuming.
A cursor is only meaningful for a FIXED filter set: it encodes a
position in this organization’s overall sequence, not a position
within any particular namespace_id/event_type filter. Changing
either filter mid-stream while reusing an old cursor silently skips
whatever the previous filter combination would have matched in
between — start a fresh cursor (or none) whenever the filters change.
High-churn event types (object.* under active storage syncs) can bury
sparse ones thousands of pages deep in the unfiltered walk — a consumer
looking for one type should pass event_type rather than walking
everything.
curl --request GET \
--url https://api.mixpeek.com/v1/events \
--header 'Authorization: Bearer <token>' \
--header 'X-Namespace: <api-key>'import requests
url = "https://api.mixpeek.com/v1/events"
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/events', 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/events",
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/events"
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/events")
.header("Authorization", "Bearer <token>")
.header("X-Namespace", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixpeek.com/v1/events")
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{
"results": [
{
"seq": 123,
"cursor": "<string>",
"event_type": "<string>",
"resource_type": "<string>",
"operation": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"namespace_id": "<string>",
"payload": {}
}
],
"has_more": true,
"next_cursor": "<string>"
}{
"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.
Query Parameters
Opaque cursor from a prior response's next_cursor. Omit to start from the beginning of the 90-day retention window.
Alias for cursor — the response surfaces this name, so feeding it back must work. If both are given, cursor wins.
Alias for cursor. If both are given, cursor wins.
Filter to events scoped to one namespace (ns_ id or name). The X-Namespace header does the same; if both are present they must agree.
Filter to one event type. Webhook event types for real-time notifications.
These events are emitted when significant state changes occur in the system. Webhooks subscribe to specific event types and receive notifications via configured channels (email, Slack, HTTP webhooks).
Event Naming Convention: {resource}.{action}[.{sub-resource}[.{sub-action}]]
Examples: - object.created: New object ingested - collection.documents.written: Documents indexed - cluster.execution.completed: Cluster job finished
Cache Invalidation Annotations: Each event type includes a comment indicating recommended cache invalidation scope: - [KEY] = Invalidate specific document/object keys - [COLLECTION] = Invalidate collection-level cache - [NAMESPACE] = Invalidate namespace-level cache
Event Categories: - Object Lifecycle: Events for individual objects (create, update, delete) - Collection Lifecycle: Events for collections (create, update, delete, documents written) - Cluster Lifecycle: Events for clusters (create, update, delete, execution status) - Trigger Lifecycle: Events for cluster triggers (create, update, fire, execution status) - Taxonomy Lifecycle: Events for taxonomies (create, update, delete)
Use Cases: - Real-time sync with external systems - Audit trail and compliance logging - Automated workflows triggered by state changes - Cache invalidation for distributed systems - Notifications to team members via Slack/email
object.created, objects.created.batch, object.updated, object.deleted, document.created, document.updated, document.deleted, documents.updated.batch, documents.deleted.batch, collection.created, collection.updated, collection.deleted, collection.documents.written, collection.documents.batch_completed, cluster.created, cluster.updated, cluster.deleted, cluster.execution.started, cluster.execution.completed, cluster.execution.failed, trigger.created, trigger.updated, trigger.deleted, trigger.paused, trigger.resumed, trigger.fired, trigger.execution.completed, trigger.execution.failed, taxonomy.created, taxonomy.updated, taxonomy.deleted, alert.created, alert.updated, alert.deleted, alert.triggered, alert.execution.completed, alert.execution.failed, annotation.created, annotation.updated, annotation.deleted Page size (default 100).
1 <= x <= 1000Alias for limit. If both are given, limit wins.
1 <= x <= 1000Response
Successful Response
Was this page helpful?

