Skip to main content
SaliencyLab Docs
Reference

API reference

Integrate the SaliencyLab creative analysis API: upload media, submit asynchronous jobs, handle limits, and verify signed webhooks.

The SaliencyLab API supports workspace-scoped, asynchronous creative analysis. Manage keys from Settings → API inside the authenticated workspace.

Private preview: REST analysis writes and webhook delivery are currently in private preview. Test keys return deterministic fixtures for integration development. Live-key write requests can return 503 when live processing is not enabled, without consuming quota.

Authentication

Send a key with either header:

Authorization: Bearer sl_live_xxx
x-api-key: sl_live_xxx

Keys beginning with sl_test_ return deterministic fixtures and do not invoke the live analysis pipeline.

If both supported headers are present, the Bearer token takes precedence. Do not use the generic apikey header from a Supabase client; SaliencyLab keys use the sl_live_ or sl_test_ format.

Integration flow

Large media should not pass through your application server or a Vercel request body. The API uses a direct-upload sequence:

  1. Call POST /v1/uploads with file metadata to obtain a signed storage upload URL.
  2. Upload the bytes directly to that signed URL.
  3. Call POST /v1/analyses with the returned storage_path and creative context.
  4. Store the returned job ID.
  5. Poll GET /v1/analyses/{job_id} until complete or failed, or provide a webhook URL.

Video upload requests must include a positive duration_seconds value no greater than the documented limit. The processing worker measures duration again before analysis.

Submit an analysis

const headers = {
  Authorization: `Bearer ${process.env.SALIENCYLAB_API_KEY}`,
  'Content-Type': 'application/json',
};

const uploadResponse = await fetch('https://api.saliencylab.com/v1/uploads', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    filename: 'creative.mp4',
    content_type: 'video/mp4',
    size_bytes: file.size,
    duration_seconds: 15,
  }),
});

const upload = await uploadResponse.json();

await fetch(upload.data.upload_url, {
  method: 'PUT',
  headers: { 'Content-Type': 'video/mp4' },
  body: file,
});

const response = await fetch('https://api.saliencylab.com/v1/analyses', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    storage_path: upload.data.storage_path,
    platform: 'youtube',
    market: 'US',
  }),
});

const analysis = await response.json();
const jobId = analysis.data.job_id;

Check every HTTP status and the response envelope before reading data. JSON responses use { success, data, error, meta }.

Main endpoints

MethodPathPurpose
POST/v1/uploadsMint a signed direct-upload URL
POST/v1/analysesSubmit one creative for analysis
GET/v1/analysesList analyses in the workspace
GET/v1/analyses/{job_id}Read status or the completed result
DELETE/v1/analyses/{job_id}Delete an analysis and its assets
POST/v1/analyses/batchSubmit a batch of creatives
GET/v1/analyses/batch/{batch_id}Read batch status
GET/v1/benchmarksRead supported benchmark context
GET/v1/creative-driversRead creative attribute drivers

Job states and polling

Analysis jobs move through queued, running, complete, or failed. Batch responses can also be partial. Poll with bounded backoff, honor rate-limit headers, and stop on a terminal state. Do not resubmit a creative merely because a job remains queued or running.

Errors and rate limits

Failure envelopes include a stable error code and message. Handle at least:

  • 400 for invalid metadata, unsupported media, or unsafe webhook URLs
  • 401 for a missing or invalid API key
  • 403 for plan or workspace restrictions
  • 404 when a resource is absent from the authenticated workspace
  • 429 when a minute or monthly limit is reached
  • 503 when private-preview live processing is unavailable

Use the X-RateLimit-* response headers for live counters and retry timing. Do not infer quota consumption from the number of client attempts.

Webhooks

When you supply a webhook URL, verify X-SaliencyLab-Signature against the raw request body using the one-time signing secret returned at submission. Reject the delivery if verification fails.

Compute a hex HMAC-SHA256 digest over the untouched request bytes and compare signatures in constant time. Store the signing secret when the job is created; it is returned once. Make webhook handling idempotent because deliveries can be retried.

Webhook URLs must use HTTPS and pass SaliencyLab's public-network safety checks. Redirects to local, private, or link-local addresses are rejected.

Security checklist

  • Keep live keys in a server-side secret manager.
  • Never expose a key in browser code, logs, screenshots, or source control.
  • Scope every stored job ID to the workspace associated with the key.
  • Verify webhooks before parsing or acting on their contents.
  • Rotate and revoke keys from workspace settings when exposure is suspected.
  • Use a test key for CI and integration demos.

Download the machine-readable OpenAPI specification.

On this page