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'import requests
url = "https://api.mixpeek.com/v1/manifest/apply"
files = { "manifest_file": ("example-file", open("example-file", "rb")) }
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('manifest_file', '<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--",
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--")
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--")
.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--"
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
}{
"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
}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. Performs automatic rollback if any resource creation fails.
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
- Dry run mode validates the manifest 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'import requests
url = "https://api.mixpeek.com/v1/manifest/apply"
files = { "manifest_file": ("example-file", open("example-file", "rb")) }
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('manifest_file', '<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--",
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--")
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--")
.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--"
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
}{
"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.
Query Parameters
Validate only, don't create resources
create_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.
create_only, create_missing Body
YAML manifest file
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
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)
Was this page helpful?

