curl --request POST \
--url https://api.mixpeek.com/v1/manifest/apply \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form manifest_file=@example-file \
--form 'parameters=<string>'import requests
url = "https://api.mixpeek.com/v1/manifest/apply"
files = { "manifest_file": ("example-file", open("example-file", "rb")) }
payload = { "parameters": "<string>" }
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('manifest_file', '<string>');
form.append('parameters', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.mixpeek.com/v1/manifest/apply', 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/manifest/apply",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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/manifest/apply"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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/manifest/apply")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixpeek.com/v1/manifest/apply")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created_count": 2,
"dry_run": false,
"errors": [],
"failed_count": 0,
"resources": [
{
"name": "video_search",
"resource_id": "ns_abc123",
"resource_type": "namespace",
"status": "created"
},
{
"name": "raw_videos",
"resource_id": "bkt_xyz789",
"resource_type": "bucket",
"status": "created"
}
],
"rollback_performed": false,
"skipped_count": 0,
"success": true
}{
"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
}Apply Manifest
Apply a YAML manifest to create resources.
Creates all resources defined in the manifest file in dependency order.
Modes:
create_only(default) — fails if any resource already exists.create_missing— creates what is missing, leaves what exists alone, and resolves manifest references against the resources ALREADY in the namespace. This is what makes “here is a namespace with buckets, add these collections over them” work. Undercreate_onlya reference to an undeclared-but-existing bucket is a validation error, because the manifest is treated as a closed world.
Plan first: before creating anything, apply runs the same checks as
POST /v1/manifest/validate. Any error refuses the whole manifest with
success: false, every resource skipped, and each error naming the
resource, the field and the fix. Nothing is created. A namespace budget above
the organization’s bound is set to the bound and reported as a warning.
Features:
- Topological sorting ensures resources are created in correct dependency order
- Secret references (
${{ secrets.NAME }}) are resolved from organization secrets - Atomic operation: rolls back all created resources if any creation fails, and an apply whose process is stopped part way is rolled back when the API starts again
- Dry run returns the plan without making changes
Example:
curl -X POST /v1/manifest/apply \
-H "Authorization: Bearer $API_KEY" \
-H "X-Namespace: ns_xxx" \
-F "manifest_file=@mixpeek.yaml"
Example manifest:
version: "1.0"
metadata:
name: "my-environment"
namespaces:
- name: video_search
feature_extractors:
- name: multimodal_extractor
version: v1
buckets:
- name: raw_videos
namespace: video_search
schema:
properties:
video: { type: video }
curl --request POST \
--url https://api.mixpeek.com/v1/manifest/apply \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form manifest_file=@example-file \
--form 'parameters=<string>'import requests
url = "https://api.mixpeek.com/v1/manifest/apply"
files = { "manifest_file": ("example-file", open("example-file", "rb")) }
payload = { "parameters": "<string>" }
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('manifest_file', '<string>');
form.append('parameters', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.mixpeek.com/v1/manifest/apply', 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/manifest/apply",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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/manifest/apply"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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/manifest/apply")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixpeek.com/v1/manifest/apply")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"manifest_file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"parameters\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created_count": 2,
"dry_run": false,
"errors": [],
"failed_count": 0,
"resources": [
{
"name": "video_search",
"resource_id": "ns_abc123",
"resource_type": "namespace",
"status": "created"
},
{
"name": "raw_videos",
"resource_id": "bkt_xyz789",
"resource_type": "bucket",
"status": "created"
}
],
"rollback_performed": false,
"skipped_count": 0,
"success": true
}{
"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.
Query Parameters
Run the plan only: the same checks as POST /v1/manifest/validate, returned as errors and warnings, with nothing created
Wait up to this many seconds after the resources are created for every Ray Serve app a declared collection needs to be RUNNING (the apps listed in readiness). Past the deadline the result has success false and an error naming the deadline and each app not RUNNING; the resources stay in place. Omit to return as soon as the resources exist.
1 <= x <= 1800create_only (default): fail if any resource already exists. create_missing: create what is missing and leave what exists alone, which is what lets a manifest be applied to an EXISTING namespace. create_missing does not UPDATE anything — a resource that exists but differs from the manifest is reported as exists and left untouched. upsert: create what is missing AND patch what exists but differs, so re-applying a manifest brings the running resources back to what it declares. Each resource is patched only through its own update surface, so a field that surface does not accept, or refuses the value of, is reported in refused with the resource and the field named, and the rest of the manifest still applies. Explicit on purpose: this is the only mode that CHANGES resources that already exist.
create_only, create_missing, upsert Body
Response
Successful Response
Result of applying a manifest.
Whether all resources were created successfully
Results for each resource
Show child attributes
Show child attributes
Number of resources created
Number of resources that failed
Number of resources skipped
Resources that existed, differed, and were PATCHED to match. Only ever non-zero under upsert. Counted separately because without it an upsert that changed five running resources reports created 0, failed 0, skipped 0, a summary that reads as nothing having happened.
Error messages
Non-fatal issues found while PARSING the manifest, chiefly keys the parser had to drop. the parser already detects these and /validate and /lint already surface them, but /apply computed them and threw them away — so anyone applying without validating first got a 201 and no hint that part of their manifest was ignored. A collection-level field_passthrough: is the case that cost a customer POC: detected, described, discarded.
Whether a rollback was ATTEMPTED after a failure. this used to read as 'the namespace was returned to its prior state', which it does not mean — rollback deletes only namespaces and buckets today, so any other resource created before the failure SURVIVES. Read rollback_orphans to find out what is still there.
Resources created before the failure that rollback did NOT delete, as '/'. Non-empty means the namespace is in a PARTIAL state and a straight retry will hit AlreadyExists on these. previously these were silently skipped while rollback_performed=true claimed otherwise, which is the state that had to be unpicked by hand on the Radio-Canada POC.
Whether this was a dry run (no changes made)
The apply's task: GET /v1/tasks/{task_id} returns every resource of the plan with its states in order (planned, creating, created, exists, updated or failed with the finding; for a collection, warming or ready), each with the time it was reached. Absent on a dry run
For each collection the manifest declares whose extractor needs Ray Serve applications for real-time inference: whether each one is served, read once from the live Serve list after apply. realtime_available true means every app is RUNNING. An app scaled to zero replicas is still RUNNING; its first call answers 503 with Retry-After (code model_warming) while it warms, so retry after that many seconds. Empty for collections whose extractor needs no Serve app.
Show child attributes
Show child attributes
Was this page helpful?

