Skip to main content

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 submissionId for tracking and polling
  • A workspace context (derived from your API key)
  • One or more assets to process
  • A lifecycle status (uploading, submitted, processing, complete, failed)

Submission lifecycle

States explained

StatusMeaningNext step
uploadingAssets are being uploaded to blob storageFinish uploads, then create the submission
submittedSubmission registered, queued for processingWait for processing to begin
processingWorkflows are actively analyzing assetsPoll for completion
completeAll assets successfully analyzedRetrieve results
failedOne or more assets failed to processCheck error details and retry if retryable
Terminal states for polling are complete and failed.

Creating a submission

POST /api/integrations/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. To label assets or give the review extra material to work with, attach tags and contextItems — see Tags and supporting context.
{
  "assets": [
    { "blobPath": "<workspace-id>/campaign-video.mp4" }
  ],
  "sidekickIds": ["<sidekick-id>"],
  "metadata": { "campaign": "spring-2026" }
}
Response 201 Created:
{
  "submissionId": "550e8400-e29b-41d4-a716-446655440000",
  "workflowId": "asset-processing-...",
  "ablyChannel": "submission:550e8400-...",
  "status": "submitted",
  "assets": [
    { "assetId": "a1b2...", "versionGroupId": "g1...", "versionNumber": 1 }
  ]
}
The submission identifier is 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 by key/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 external url instead.

applyTo

Every tag and context item has an applyTo 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

{
  "assets": [
    { "blobPath": "<workspace-id>/campaign-video.mp4" }
  ],
  "tags": [
    { "key": "Campaign", "value": "Summer", "applyTo": "all" }
  ],
  "contextItems": [
    {
      "kind": "file",
      "contextType": "substantiation",
      "blobPath": "<workspace-id>/evidence.pdf",
      "name": "evidence.pdf",
      "mimeType": "application/pdf",
      "applyTo": "all"
    },
    {
      "kind": "link",
      "contextType": "legal",
      "url": "https://example.com/brand-guidelines",
      "linkName": "Brand guidelines",
      "applyTo": "all"
    }
  ]
}
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/integrations/submissions/{submission_id} Returns the current state of the submission and all of its assets. There is no /status suffix.
{
  "submissionId": "550e8400-...",
  "workflowId": "asset-processing-...",
  "workspaceId": "660e8400-...",
  "status": "processing",
  "progressPercent": 40,
  "createdAt": "2026-06-03T12:00:00Z",
  "completedAt": null,
  "errorMessage": null,
  "assets": [
    {
      "assetId": "a1b2...",
      "versionGroupId": "g1...",
      "versionNumber": 1,
      "issueCount": null,
      "errorMessage": null,
      "errorType": null,
      "isRetryable": false,
      "retryCount": 0
    }
  ],
  "isRetryable": false
}
Use progressPercent to track progress. A 404 is returned if the submission does not exist in the authenticated workspace. Each asset object also carries a tags array ([{ "key": "...", "value": "..." }]) reflecting any tags applied at submit time.

Polling recommendations

Poll GET /api/integrations/submissions/{submission_id} every few seconds and back off over time. Stop polling once the top-level status is complete or failed.
For large-scale operations, prefer webhooks over tight polling — they are more efficient and deliver near real-time updates.

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.
{
  "assets": [
    { "blobPath": "<workspace-id>/video1.mp4" },
    { "blobPath": "<workspace-id>/video2.mp4" },
    { "blobPath": "<workspace-id>/doc.pdf" }
  ],
  "sidekickIds": ["<sidekick-id>"],
  "metadata": {}
}
Each asset is processed independently and has its own per-asset status fields.

Error handling

If an asset fails, its failure details appear as flat fields on the asset object in the status response — there is no nested error object.
{
  "submissionId": "550e8400-...",
  "status": "failed",
  "assets": [
    {
      "assetId": "a1b2...",
      "versionGroupId": "g1...",
      "versionNumber": 1,
      "issueCount": null,
      "errorMessage": "Source media could not be decoded.",
      "errorType": "unsupported_codec",
      "isRetryable": true,
      "retryCount": 0
    }
  ],
  "isRetryable": true
}
When isRetryable is true, you can retry the asset: POST /api/integrations/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 via previousSubmissionId. Each version is tracked by versionGroupId and versionNumber. List all versions with: GET /api/integrations/submissions/{submission_id}/versions See Assets for details.