What is a submission?
A submission is a container for one or more media assets that you want to process. When you create a submission, the API queues the assets for processing and begins analysis. Each submission has:- A unique
submissionIdfor tracking and polling - A workspace context (derived from your API key)
- One or more assets to process
- A lifecycle status (
uploading,submitted,queued,processing,complete,partial,failed)
Submission lifecycle
A live submission is created asqueued and moves to processing as its assets are admitted to review. Sandbox submissions are created as submitted instead and skip the queue entirely.
States explained
Terminal states for polling are
complete, partial, and failed. A newly created submission returns queued; it is non-terminal, so keep polling.
Assets are admitted to review a few at a time, so a submission reports
processing as soon as any asset starts — even while its remaining assets are still waiting. It stays non-terminal until every asset has settled, so a submission can sit in processing with only part of its work actually running. Use assets[].processingStatus on the status response to see exactly where each asset is.Creating a submission
POST/api/submissions
Each asset object needs a blobPath. The optional previousSubmissionId links an asset to a prior submission for versioning. The submission-level sidekickIds (a list of UUIDs) is required — at least one sidekick must run, or there is nothing to check; an empty or omitted list is rejected with 422. Each asset may also carry its own sidekickIds (a subset of the submission-level set) to run only those sidekicks on that asset; an empty per-asset list inherits the full set. You may also pass a free-form metadata object, or an externalReference — a structured {system, ref} reference to the external work item the submission originates from, which (unlike metadata) is returned on the status endpoint and echoed on the asset.processing.* webhook so an integration can correlate the completion back (system is capped at 64 characters and ref must serialize to under 4 KB). To label assets or give the review extra material to work with, attach tags and contextItems — see Tags and supporting context.
201 Created:
submissionId, not id.
Tags and supporting context
Beyond the assets themselves, a submission can carry two optional, top-level kinds of extra input:- Tags — key/value labels applied to assets (e.g.
Campaign: Summer). Tags are referenced bykey/value, not by id: the matching workspace tag is found-or-created automatically, so you never need to pre-create tags or look up their UUIDs. - Context items — supporting files or links that give the compliance review more to work with (substantiation documents, brand guidelines, transcripts, legal copy, and so on). A context file is uploaded exactly like an asset (see the File upload guide) and referenced by its
blobPath; a context link carries an externalurlinstead.
applyTo
Every tag and context item has anapplyTo field that selects which assets it attaches to:
"all"(the default) — every asset in the submission.- a list of asset blobPaths — only the listed assets.
Example
contextType must be one of: substantiation, product_info, brand_guidelines_evidence, legal, transcript_script, talent_licensing, brand_guidelines_publishing, platform_metadata, other.
Tags are echoed back on each asset in the status response; both tags and context items are returned on the asset result.
Checking submission status
GET/api/submissions/{submission_id}
Returns the current state of the submission and all of its assets. There is no /status suffix.
workflowId is an internal processing reference and is frequently null — track submissions by submissionId and read per-asset progress from assets[].processingStatus.
progressPercent to track progress. A 404 is returned if the submission does not exist in the authenticated workspace. startedAt and completedAt bracket the work that actually ran: they are null while an asset is still queued, and the submission’s startedAt is the earliest asset start (its completedAt is when the submission settled). Each asset object also carries a tags array ([{ "key": "...", "value": "..." }]) reflecting any tags applied at submit time, and a workflowId — the processing workflow identifier for that specific asset, useful as a support reference when reporting a stuck or failed asset.
Polling recommendations
For large-scale operations, prefer webhooks over tight polling — they are more efficient and deliver near real-time updates. For live, in-app progress, subscribe to the submission’s channel instead — see the Realtime updates guide.Multiple assets per submission
You can submit multiple assets in a single submission. Batching assets into one submission is also the recommended way to stay within rate limits.Error handling
If an asset fails, its failure details appear as flat fields on the asset object in the status response — there is no nestederror object.
completedAt is when it stopped — the failure time, not a success time. Retrying re-stamps startedAt and clears completedAt, so the pair always describes the most recent attempt.
When isRetryable is true, you can retry the asset:
POST /api/submissions/{submission_id}/assets/{asset_id}/retry
This returns 202 Accepted with the same shape as creating a submission. A 409 is returned if the asset is not in a failed state, the error is not retryable, the maximum attempts have been reached, or a retry is already in flight.
See Error codes for the full list of status codes and error envelopes.
Versioning and resubmission
To create a new version of an asset, create a new submission whose asset references the original viapreviousSubmissionId. Each version is tracked by versionGroupId and versionNumber. List all versions with:
GET /api/submissions/{submission_id}/versions
See Assets for details.