curl --request POST \
--url https://api.zebratruth.ai/v1/compliance/check-video \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"requestId": "82b68316-ed85-489c-991e-2ff0f2b95f29",
"blobPath": "videos/kp_abc123.../82b68316-.../source.mp4",
"jurisdictions": [
"us",
"eu"
],
"platforms": [
"youtube",
"instagram"
],
"mode": "fast",
"webhookUrl": "https://your-app.example.com/webhooks/zebratruth",
"callbackId": "<string>",
"reviewScopes": []
}
'import requests
url = "https://api.zebratruth.ai/v1/compliance/check-video"
payload = {
"requestId": "82b68316-ed85-489c-991e-2ff0f2b95f29",
"blobPath": "videos/kp_abc123.../82b68316-.../source.mp4",
"jurisdictions": ["us", "eu"],
"platforms": ["youtube", "instagram"],
"mode": "fast",
"webhookUrl": "https://your-app.example.com/webhooks/zebratruth",
"callbackId": "<string>",
"reviewScopes": []
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
requestId: '82b68316-ed85-489c-991e-2ff0f2b95f29',
blobPath: 'videos/kp_abc123.../82b68316-.../source.mp4',
jurisdictions: ['us', 'eu'],
platforms: ['youtube', 'instagram'],
mode: 'fast',
webhookUrl: 'https://your-app.example.com/webhooks/zebratruth',
callbackId: '<string>',
reviewScopes: []
})
};
fetch('https://api.zebratruth.ai/v1/compliance/check-video', 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.zebratruth.ai/v1/compliance/check-video",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'requestId' => '82b68316-ed85-489c-991e-2ff0f2b95f29',
'blobPath' => 'videos/kp_abc123.../82b68316-.../source.mp4',
'jurisdictions' => [
'us',
'eu'
],
'platforms' => [
'youtube',
'instagram'
],
'mode' => 'fast',
'webhookUrl' => 'https://your-app.example.com/webhooks/zebratruth',
'callbackId' => '<string>',
'reviewScopes' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.zebratruth.ai/v1/compliance/check-video"
payload := strings.NewReader("{\n \"requestId\": \"82b68316-ed85-489c-991e-2ff0f2b95f29\",\n \"blobPath\": \"videos/kp_abc123.../82b68316-.../source.mp4\",\n \"jurisdictions\": [\n \"us\",\n \"eu\"\n ],\n \"platforms\": [\n \"youtube\",\n \"instagram\"\n ],\n \"mode\": \"fast\",\n \"webhookUrl\": \"https://your-app.example.com/webhooks/zebratruth\",\n \"callbackId\": \"<string>\",\n \"reviewScopes\": []\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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.zebratruth.ai/v1/compliance/check-video")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"requestId\": \"82b68316-ed85-489c-991e-2ff0f2b95f29\",\n \"blobPath\": \"videos/kp_abc123.../82b68316-.../source.mp4\",\n \"jurisdictions\": [\n \"us\",\n \"eu\"\n ],\n \"platforms\": [\n \"youtube\",\n \"instagram\"\n ],\n \"mode\": \"fast\",\n \"webhookUrl\": \"https://your-app.example.com/webhooks/zebratruth\",\n \"callbackId\": \"<string>\",\n \"reviewScopes\": []\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zebratruth.ai/v1/compliance/check-video")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"requestId\": \"82b68316-ed85-489c-991e-2ff0f2b95f29\",\n \"blobPath\": \"videos/kp_abc123.../82b68316-.../source.mp4\",\n \"jurisdictions\": [\n \"us\",\n \"eu\"\n ],\n \"platforms\": [\n \"youtube\",\n \"instagram\"\n ],\n \"mode\": \"fast\",\n \"webhookUrl\": \"https://your-app.example.com/webhooks/zebratruth\",\n \"callbackId\": \"<string>\",\n \"reviewScopes\": []\n}"
response = http.request(request)
puts response.read_body{
"jobId": "82b68316-ed85-489c-991e-2ff0f2b95f29",
"status": "queued",
"estimatedCredits": 123,
"callbackId": "<string>",
"idempotent": true
}{
"statusCode": 401,
"message": "Invalid API key",
"error": true,
"url": "https://api.zebratruth.ai/v1/whoami",
"statusMessage": "Invalid API key"
}{
"statusCode": 402,
"message": "Insufficient credits",
"error": true,
"url": "<string>",
"statusMessage": "Insufficient credits",
"data": {
"creditsRemaining": 3,
"creditsNeeded": 123,
"upgradeUrl": "https://developers.zebratruth.ai/dashboard/billing"
}
}{
"statusCode": 403,
"message": "Requested jurisdictions [india, china] are not in your subscription. Allowed: [us, eu].",
"error": true,
"url": "https://api.zebratruth.ai/v1/compliance/check",
"statusMessage": "Requested jurisdictions [india, china] are not in your subscription. Allowed: [us, eu]."
}{
"error": true,
"code": "idempotency_conflict",
"reason": "blobPath",
"existing": "<string>",
"incoming": "<string>"
}{
"statusCode": 429,
"message": "Rate limit exceeded",
"error": true,
"url": "<string>",
"statusMessage": "Rate limit exceeded",
"data": {
"retryAfter": 5,
"limit": 60,
"remaining": 0
}
}Submit a video for compliance analysis
Submits an uploaded video (referenced by requestId + blobPath from
a prior POST /compliance/media/upload-url) for compliance analysis.
Asynchronous — returns 202 immediately with a jobId. Poll
GET /compliance/check-video/{requestId} for status + the inlined
report when terminal, OR set webhookUrl to receive a signed callback.
Required: jurisdictions + platforms (mirror text/image checks —
same canonical codes, e.g. ["us", "eu"], ["youtube", "instagram"]).
Inputs are canonicalized (trim + lowercase + sort) before storage and
hashed — case-only differences are treated as the same request.
Idempotency. The request is keyed on
(blobPath, feature, inputHash). Re-posting with the same requestId
AND the same inputs returns 202 with idempotent: true. Different
inputs on the same requestId returns 409 idempotency_conflict
with reason set to the field that differs.
Billing. Credits are reserved at submit time
(estimatedCredits returned). They are committed when the job
completes with a real report, OR released for insufficient_evidence
/ analysis_failed / poison-queue failures — tenants only pay for
valid reports.
Latency. Typical: 8–30 seconds for a 5–30s video. Longer videos and dense-content frames take proportionally longer.
curl --request POST \
--url https://api.zebratruth.ai/v1/compliance/check-video \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"requestId": "82b68316-ed85-489c-991e-2ff0f2b95f29",
"blobPath": "videos/kp_abc123.../82b68316-.../source.mp4",
"jurisdictions": [
"us",
"eu"
],
"platforms": [
"youtube",
"instagram"
],
"mode": "fast",
"webhookUrl": "https://your-app.example.com/webhooks/zebratruth",
"callbackId": "<string>",
"reviewScopes": []
}
'import requests
url = "https://api.zebratruth.ai/v1/compliance/check-video"
payload = {
"requestId": "82b68316-ed85-489c-991e-2ff0f2b95f29",
"blobPath": "videos/kp_abc123.../82b68316-.../source.mp4",
"jurisdictions": ["us", "eu"],
"platforms": ["youtube", "instagram"],
"mode": "fast",
"webhookUrl": "https://your-app.example.com/webhooks/zebratruth",
"callbackId": "<string>",
"reviewScopes": []
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
requestId: '82b68316-ed85-489c-991e-2ff0f2b95f29',
blobPath: 'videos/kp_abc123.../82b68316-.../source.mp4',
jurisdictions: ['us', 'eu'],
platforms: ['youtube', 'instagram'],
mode: 'fast',
webhookUrl: 'https://your-app.example.com/webhooks/zebratruth',
callbackId: '<string>',
reviewScopes: []
})
};
fetch('https://api.zebratruth.ai/v1/compliance/check-video', 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.zebratruth.ai/v1/compliance/check-video",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'requestId' => '82b68316-ed85-489c-991e-2ff0f2b95f29',
'blobPath' => 'videos/kp_abc123.../82b68316-.../source.mp4',
'jurisdictions' => [
'us',
'eu'
],
'platforms' => [
'youtube',
'instagram'
],
'mode' => 'fast',
'webhookUrl' => 'https://your-app.example.com/webhooks/zebratruth',
'callbackId' => '<string>',
'reviewScopes' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.zebratruth.ai/v1/compliance/check-video"
payload := strings.NewReader("{\n \"requestId\": \"82b68316-ed85-489c-991e-2ff0f2b95f29\",\n \"blobPath\": \"videos/kp_abc123.../82b68316-.../source.mp4\",\n \"jurisdictions\": [\n \"us\",\n \"eu\"\n ],\n \"platforms\": [\n \"youtube\",\n \"instagram\"\n ],\n \"mode\": \"fast\",\n \"webhookUrl\": \"https://your-app.example.com/webhooks/zebratruth\",\n \"callbackId\": \"<string>\",\n \"reviewScopes\": []\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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.zebratruth.ai/v1/compliance/check-video")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"requestId\": \"82b68316-ed85-489c-991e-2ff0f2b95f29\",\n \"blobPath\": \"videos/kp_abc123.../82b68316-.../source.mp4\",\n \"jurisdictions\": [\n \"us\",\n \"eu\"\n ],\n \"platforms\": [\n \"youtube\",\n \"instagram\"\n ],\n \"mode\": \"fast\",\n \"webhookUrl\": \"https://your-app.example.com/webhooks/zebratruth\",\n \"callbackId\": \"<string>\",\n \"reviewScopes\": []\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zebratruth.ai/v1/compliance/check-video")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"requestId\": \"82b68316-ed85-489c-991e-2ff0f2b95f29\",\n \"blobPath\": \"videos/kp_abc123.../82b68316-.../source.mp4\",\n \"jurisdictions\": [\n \"us\",\n \"eu\"\n ],\n \"platforms\": [\n \"youtube\",\n \"instagram\"\n ],\n \"mode\": \"fast\",\n \"webhookUrl\": \"https://your-app.example.com/webhooks/zebratruth\",\n \"callbackId\": \"<string>\",\n \"reviewScopes\": []\n}"
response = http.request(request)
puts response.read_body{
"jobId": "82b68316-ed85-489c-991e-2ff0f2b95f29",
"status": "queued",
"estimatedCredits": 123,
"callbackId": "<string>",
"idempotent": true
}{
"statusCode": 401,
"message": "Invalid API key",
"error": true,
"url": "https://api.zebratruth.ai/v1/whoami",
"statusMessage": "Invalid API key"
}{
"statusCode": 402,
"message": "Insufficient credits",
"error": true,
"url": "<string>",
"statusMessage": "Insufficient credits",
"data": {
"creditsRemaining": 3,
"creditsNeeded": 123,
"upgradeUrl": "https://developers.zebratruth.ai/dashboard/billing"
}
}{
"statusCode": 403,
"message": "Requested jurisdictions [india, china] are not in your subscription. Allowed: [us, eu].",
"error": true,
"url": "https://api.zebratruth.ai/v1/compliance/check",
"statusMessage": "Requested jurisdictions [india, china] are not in your subscription. Allowed: [us, eu]."
}{
"error": true,
"code": "idempotency_conflict",
"reason": "blobPath",
"existing": "<string>",
"incoming": "<string>"
}{
"statusCode": 429,
"message": "Rate limit exceeded",
"error": true,
"url": "<string>",
"statusMessage": "Rate limit exceeded",
"data": {
"retryAfter": 5,
"limit": 60,
"remaining": 0
}
}Authorizations
API key starting with zt_live_ (production) or zt_test_ (sandbox).
Get your key at https://developers.zebratruth.ai
Headers
Unique request identifier to prevent duplicate execution and double-charging. Generate a new UUID for each distinct request. Reuse the same key to safely retry.
Body
The requestId returned from POST /compliance/media/upload-url.
"82b68316-ed85-489c-991e-2ff0f2b95f29"
The blobPath returned from POST /compliance/media/upload-url.
"videos/kp_abc123.../82b68316-.../source.mp4"
Canonical jurisdiction codes scoped to your account's subscription. Inputs are canonicalized (trim + lowercase + sort) before hashing — case-only differences are treated as the same request.
1["us", "eu"]
Canonical platform codes scoped to your account's subscription.
1youtube, instagram, facebook, tiktok, linkedin ["youtube", "instagram"]
Execution mode. V1 supports fast only.
fast Optional callback URL. When set, a signed POST is delivered when the
job reaches a terminal status. Requires you to have configured a
webhook signing secret via GET /compliance/webhooks/video/secret.
"https://your-app.example.com/webhooks/zebratruth"
Opaque tag echoed back in the 202 response and the webhook payload. Use it to correlate jobs with your internal records.
256Financial-services review scopes to run on the transcript and on-screen text. Same admission rules as the text check. JSON body only.
6A financial-services review scope. Each maps to one specialist agent:
financial promotions, disclosures and conduct; investment advice and suitability;
credit origination, servicing and collections; order execution, transaction reporting
and market abuse; KYC, AML/CFT, fraud and sanctions; AI governance, model risk and
automated decisions. Coverage is US, EU and UK for every scope, plus China and India
for financial_promotion.
financial_promotion, advisory_suitability, credit_servicing, markets_trading, financial_crime, ai_governance What kind of artifact the video is. JSON body only.
marketing, suitability_report, advice_letter, precontract_disclosure, adverse_action_notice, collections_communication, arrears_notice, fund_factsheet, research_note, trader_communication, best_execution_disclosure, kyc_onboarding, scam_warning, aml_policy, ai_policy, model_documentation, other Response
Job accepted + queued
Same value as the request's requestId. Use it to poll status.
"82b68316-ed85-489c-991e-2ff0f2b95f29"
queued Credits reserved for this job. Committed on success or released on insufficient_evidence / analysis_failed.
Echoed verbatim from the request when provided.
Present + true when this request matched an existing job with the
same (requestId, blobPath, feature, inputHash). No additional
credits reserved.