Media Scoring API Guide

A step-by-step guide on usage of Scoring API to score media.

The Creative Scoring API lets you evaluate media assets against your organization's configured guidelines and receive structured pass/fail results per advertising channel. This guide walks through the full integration end to end.

📘

Prerequisites

You'll need an API key with scoring:read_write scope, and at least one Workspace configured in your Vidmob organization. Call GET /v1/organization to retrieve your workspaceId values before you start.

How Scoring Works

Scoring is asynchronous. You submit a media asset, Vidmob queues it through a multi-stage AI pipeline, and results become available when processing completes — typically within 30–60 minutes depending on asset complexity and queue depth.

The workflow is always three steps:

  1. Submit — Register the asset and receive a uniqueId
  2. Poll — Check status every 10–15 minutes until COMPLETE
  3. Fetch — Retrieve the score results

Step 1 — Submit Media

Register your asset with POST /v1/media. At minimum you need a client-side id and a publicly accessible url.

curl -X POST https://public-api.vidmob.com/v1/media \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "spring-campaign-15s-v1",
    "version": "1.0",
    "url": "https://your-cdn.com/creative.mp4",
    "workspaceId": 45914,
    "channels": ["META", "TIKTOK"]
  }'

The response returns a uniqueId — a UUID that permanently identifies this asset in Vidmob. Store it.

{
  "status": "OK",
  "result": {
    "uniqueId": "8576725c-dc61-42c6-bf56-3898ea2523cf"
  }
}

Key parameters:

ParameterRequiredNotes
idYesYour client-side identifier
urlYesDirect download URL — must be publicly accessible. Presigned S3 URLs and CDN links work reliably. Auth-gated or redirect URLs can cause silent failures.
versionNoPart of the deduplication key with id. Use if you track multiple versions of the same asset.
workspaceIdNoMakes the asset visible in the Vidmob platform UI and applies workspace-specific guidelines. Strongly recommended.
channelsNoChannels to score against (e.g. META, TIKTOK, DV360). Defaults to channels configured on the workspace scorecard.

Deduplication: Submitting the same id + version + source combination twice does not re-ingest the asset — Vidmob returns the existing uniqueId with a 409 response. You can use that uniqueId directly.

Step 2 — Poll for Completion

Check processing status with GET /v1/media/{uniqueId}/status. Poll every 10–15 minutes — more frequent polling does not speed up processing.

curl -H "Authorization: Bearer $API_KEY" \
  https://public-api.vidmob.com/v1/media/8576725c-dc61-42c6-bf56-3898ea2523cf/status
{
  "status": "OK",
  "result": {
    "uniqueId": "8576725c-dc61-42c6-bf56-3898ea2523cf",
    "status": "PROCESSING"
  }
}

Status values:

StatusMeaningAction
PROCESSINGIn progressContinue polling
COMPLETEDoneFetch scores
ERRORNon-terminal errorRetry after a delay
UNSUPPORTEDFormat not supportedTerminal — do not retry
FAILEDProcessing failedTerminal — do not retry

You can also look up by your client-side id instead of uniqueId by appending ?source=<source>&version=<version> query params.

Step 3 — Fetch Scores

Once status is COMPLETE, retrieve results with GET /v1/scoring/media/{uniqueId}/scores.

# Summary only (default)
curl -H "Authorization: Bearer $API_KEY" \
  "https://public-api.vidmob.com/v1/scoring/media/8576725c-.../scores"

# Per-guideline detail
curl -H "Authorization: Bearer $API_KEY" \
  "https://public-api.vidmob.com/v1/scoring/media/8576725c-.../scores?format=detail&channel=META"

The format parameter controls response depth:

ValueReturns
summary (default)Per-channel rollup: score, adherencePercent, pass/fail counts
detailSummary + per-guideline breakdown (name, rule, result, weight)
summary,detailBoth

Understanding Score Results

score vs adherencePercent — these are two different ways of measuring the same underlying data:

  • score is a weighted aggregate: SUM(passed guideline points) / SUM(total guideline points). Guidelines with higher weight contribute more.
  • adherencePercent is a simple pass rate: passCount / applicableCount. Every guideline counts equally. This is usually the easier number to communicate to stakeholders.

Both range from 0.0 to 1.0.

Per-guideline result values:

ValueMeaning
PASSGuideline met
FAILGuideline not met
NOT_APPLICABLEGuideline does not apply to this asset type
NO_DATACould not evaluate — data missing
NO_DATA_*Specific data gap, e.g. NO_DATA_MEDIA_NOT_TAGGED

Only PASS and FAIL results are counted in the score and adherencePercent calculations. NOT_APPLICABLE and NO_DATA results are excluded.

Staying in Sync — Updated Scores

Scores can change after initial processing if a workspace admin overrides a result in the Vidmob platform, or if an asset is rescored against updated guidelines. Use GET /v1/media/updated-scores to poll for assets whose scores have changed since a given timestamp:

curl -H "Authorization: Bearer $API_KEY" \
  "https://public-api.vidmob.com/v1/media/updated-scores?workspaceId=45914&updatedSince=2026-04-01T00:00:00Z"

The response returns a paginated list of uniqueId values. Re-fetch scores for each using the scores endpoint.

Scorecards and Guidelines

Your workspace's scoring rules are organized into Scorecards — named collections of guidelines associated with specific channels and campaigns. Call GET /v1/scoring/workspace/{workspaceId}/scorecards to see what's configured.

To inspect the full catalog of guidelines (criteria) available to your organization, use POST /v1/scoring/criteria/metadata. This endpoint supports filtering by channel, scorecard, and other dimensions.

Common Integration Patterns

Simple polling loop

import time, requests

headers = {'Authorization': f'Bearer {API_KEY}'}
base = 'https://public-api.vidmob.com/v1'

# 1. Submit
res = requests.post(f'{base}/media', headers=headers, json={
    'id': 'my-asset-001', 'url': 'https://cdn.example.com/ad.mp4', 'workspaceId': 45914
})
unique_id = res.json()['result']['uniqueId']

# 2. Poll
while True:
    status = requests.get(f'{base}/media/{unique_id}/status', headers=headers).json()['result']['status']
    if status == 'COMPLETE':
        break
    if status in ('FAILED', 'UNSUPPORTED'):
        raise Exception(f'Terminal status: {status}')
    time.sleep(600)  # 10 minutes

# 3. Fetch
scores = requests.get(f'{base}/scoring/media/{unique_id}/scores', headers=headers, params={'format': 'detail'}).json()

Tips:

  • Store uniqueId values persistently — they are stable identifiers and you will need them for re-fetching scores.
  • Use workspaceId on every submission unless you intentionally want org-global guidelines only.
  • If you receive a 409 Conflict, extract the existing uniqueId from the error context and use it directly.
  • For large-scale integrations, use GET /v1/media/updated-scores rather than polling every individual asset.