Video intelligence API
Define reusable questions as saved scanners, run them against authorized recordings, and query typed observations with evidence. One-off analysis and optional rendering remain available underneath.
Core concepts
A Scanner is a saved, versioned question and typed output contract. A Run applies one scanner version to one recording. An Observation is a typed result with explicit semantics, relevance, source metadata, and timestamped evidence.
A lower-level Analysis processes one video without saving a reusable definition. A Moment is its ranked time range. A Render optionally turns selected Moments into MP4 files.
Authentication
Create a revocable API key in the console and send it from your server in the Bearer header. Never ship a secret key in browser or mobile client code.
Authorization: Bearer cct_your_secret_keyResources are account-scoped. Requests for an unknown resource and a resource owned by a different account both return 404.
API reference
/v1/scannersCreate a reusable, versioned scanner definition.
/v1/scannersList account-owned scanner definitions.
/v1/scanners/{scanner_id}Create the next immutable scanner version.
/v1/scanners/{scanner_id}/versionsList definition snapshots used by prior runs.
/v1/scanners/{scanner_id}/runsRun the current scanner version against one recording.
/v1/runs/{run_id}Read run state, source metadata, and provenance.
/v1/runs/{run_id}/observationsRead typed findings from one completed run.
/v1/observationsQuery observations across account-owned runs.
/v1/uploadsIssue a private, time-limited direct upload target.
/v1/webhook-endpointsCreate a signed event-delivery endpoint when enabled.
/v1/analysesSubmit an authorized video for asynchronous analysis.
/v1/analyses/{analysis_id}Read analysis status and terminal errors.
/v1/analyses/{analysis_id}/momentsRetrieve ranked Moments after completion.
/v1/render-presetsRead supported output and caption controls.
/v1/rendersOptionally render selected Moment IDs.
/v1/renders/{render_id}Read render status and completed assets.
Create a saved scanner
Choose a type based on the value you need: monitor, summarizer, classifier, scorer, find_moments, or extractor. Instructions must describe observable evidence and may contain up to 600 characters.
curl -X POST https://api.chatclipthat.com/v1/scanners \
-H "Authorization: Bearer $CCT_API_KEY" \
-H "Idempotency-Key: scanner-001" \
-H "Content-Type: application/json" \
-d '{
"name": "Onboarding friction",
"instructions": "Find where the user repeats a setup action, receives an error, or says they cannot continue.",
"type": "find_moments",
"profile": "conversation",
"max_observations": 20,
"min_seconds": 10,
"max_seconds": 60,
"output": {"fields": ["title", "summary", "start_ms", "end_ms", "relevance_score", "transcript_excerpt"]},
"metadata": {"owner": "product-research"}
}'Updating a scanner creates a new version. Runs retain the version and definition they used; old observation provenance is not rewritten.
Run a scanner
Submit one direct HTTPS source URL from a trusted hostname. Run metadata accepts up to 20 bounded scalar values and is copied onto resulting observations.
curl -X POST https://api.chatclipthat.com/v1/scanners/scn_YOUR_ID/runs \
-H "Authorization: Bearer $CCT_API_KEY" \
-H "Idempotency-Key: recording-1842-scanner-v3" \
-H "Content-Type: application/json" \
-d '{
"source_url": "https://media.example.com/session-1842.mp4",
"metadata": {"recording_id": "1842", "cohort": "new-user"}
}'Poll GET /v1/runs/{run_id} every 5–10 seconds. A completed run can contain zero observations when the recording does not support the scanner instructions.
Read typed observations
An observation separates its typed value and value_type from explicit semantics. relevance_score ranks support for the scanner instructions and must not be presented as calibrated confidence.
{
"observation_id": "obs_...",
"scanner_id": "scn_...",
"scanner_version": 3,
"run_id": "run_...",
"type": "find_moments",
"value_type": "object",
"semantics": "timestamped_moment",
"value": {"event_type": "setup_blocked"},
"title": "Repeated connection failure",
"summary": "The user retries the same connection flow after an error.",
"relevance_score": 0.91,
"evidence": {"start_ms": 84210, "end_ms": 109440, "duration_ms": 25230, "transcript_excerpt": "Why won't this connect?", "signals": []},
"source_metadata": {"recording_id": "1842", "cohort": "new-user"}
}Create a one-off analysis
Use the lower-level analysis endpoint when you do not need a saved definition or cross-run observation model. Submit a direct HTTPS media URL from a hostname configured under Trusted Sources and use what_to_find as an evidence-based brief.
curl -X POST https://api.chatclipthat.com/v1/analyses \
-H "Authorization: Bearer $CCT_API_KEY" \
-H "Idempotency-Key: request-001" \
-H "Content-Type: application/json" \
-d '{
"source_url": "https://media.example.com/session.mp4",
"what_to_find": "Find where the user repeatedly fails to connect an integration",
"profile": "conversation",
"max_moments": 10,
"min_seconds": 10,
"max_seconds": 60
}'Request fields
stringDirect HTTPS media URL on a trusted hostname.stringPlain-language search brief, up to 600 characters.enumconversation or gameplay.integerMaximum results from 1–50.integerTarget Moment length, each from 5–600 seconds.Poll analysis status
Poll /v1/analyses/{analysis_id} every 5–10 seconds. Stop at completed or failed.
{
"analysis_id": "ana_0123456789abcdef0123456789abcdef",
"status": "completed",
"profile": "conversation",
"created_at": "2026-08-14T18:00:00Z",
"updated_at": "2026-08-14T18:03:24Z",
"error": null
}Retrieve Moments
A completed analysis returns ranked timestamps, summaries, transcript evidence, selection signals, and edit instructions. Zero Moments is a valid answer when the recording does not support the brief.
{
"analysis_id": "ana_...",
"count": 1,
"moments": [{
"id": "mom_0123456789abcdef0123456789abcdef",
"start_ms": 84210,
"end_ms": 109440,
"duration_ms": 25230,
"score": 0.91,
"title": "Repeated setup failure",
"event_type": "highlight",
"transcript_excerpt": "Why won't this connect?",
"edit": {"mode": "continuous", "subclips": []}
}]
}Read render capabilities
GET /v1/render-presets returns the supported aspect ratios, output format, caption presets, bundled fonts, effects, and bounded editor controls. Read this response instead of hard-coding capability values.
Create an optional render
Choose 1–20 Moment IDs from one completed analysis. ChatClipThat reuses the privately acquired source and creates one MP4 per Moment.
curl -X POST https://api.chatclipthat.com/v1/renders \
-H "Authorization: Bearer $CCT_API_KEY" \
-H "Idempotency-Key: render-001" \
-H "Content-Type: application/json" \
-d '{
"analysis_id": "ana_...",
"moment_ids": ["mom_..."],
"render": {
"output": {"format": "mp4", "aspect_ratio": "9:16"},
"captions": {"enabled": true, "preset_id": "cct_clean_v1"}
}
}'Private uploads
When upload storage is enabled, POST /v1/uploads accepts the plain filename, one supported video content type, and declared byte size. It returns a time-limited PUT URL and required headers. Upload the bytes directly, call POST /v1/uploads/{upload_id}/complete, then pass the ready upload_id instead of source_url when creating a scanner run.
503 uploads_unavailable response means this deployment has no private-upload storage. Trusted direct HTTPS URLs remain supported.Signed completion webhooks
When event delivery is enabled, create a target with POST /v1/webhook-endpoints and subscribe to scanner-run, analysis, render, or upload terminal events. The signing secret is returned once. Verify the HMAC against the raw request body, reject stale timestamps, and deduplicate by event ID.
List delivery state at GET /v1/webhook-deliveries. If webhook service is unavailable for the account, poll run status every 5–10 seconds instead.
Errors
401The bearer key is missing, invalid, or revoked.403The media hostname is not trusted for this account.404The scanner is unknown or belongs to another account.404The run is unknown or belongs to another account.409Observations were requested before the run completed.409Moments or rendering were requested before completion.402The shared account wallet cannot cover the operation.503The operation could not be queued.Idempotency and retries
Send a unique Idempotency-Key with every POST. Retrying the same operation with the same key returns its original resource rather than creating and charging for duplicate work.
Limits, source safety, and retention
Only direct HTTPS media from account-approved public DNS hostnames is accepted. Private and loopback destinations are blocked. Scanner and run metadata is limited to 20 bounded scalar fields. Account concurrency and monthly allowances are shown under Console → Usage.
Request and response fields are allowlisted; raw source URLs, signed query strings, secrets, and renderer-internal identifiers are excluded from public control responses.