> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zebratruth.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Poll video job status + retrieve report

> Returns the current state of a video compliance job. When the job is
terminal (`status: completed | failed`), the full `report` payload is
inlined in the response — no extra fetch needed.

**Polling cadence:** every 2 seconds is recommended; the engine has a
3-minute upper bound on a single job's worker time.

**`reportFetchFailed`.** Blob storage is eventually-consistent — a
read immediately after the worker completes can occasionally miss.
Rather than 500, the response surfaces `reportFetchFailed: true` so
the client can retry the same endpoint shortly.

**Tenant scoping.** A `requestId` belonging to a different tenant
returns 404 (no info leak about another tenant's jobs).




## OpenAPI

````yaml /openapi/zebratruth-v1.yaml get /compliance/check-video/{requestId}
openapi: 3.1.0
info:
  title: ZebraTruth Compliance API
  version: 1.0.0
  description: >
    AI-powered compliance checking for advertising content. Check text and
    images against

    jurisdiction laws, platform policies, and rights clearance requirements.
    Results include

    embeddable annotations mapped to content locations (text spans, video
    timestamps, image regions).
  contact:
    name: ZebraTruth Support
    email: support@zebratruth.ai
    url: https://developers.zebratruth.ai
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
servers:
  - url: https://api.zebratruth.ai/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Video Compliance
    description: >
      **Primary endpoint.** Async compliance analysis for video ads. 3-step
      flow:

      get an upload URL, upload the video bytes, submit for analysis. Poll or

      receive an HMAC-signed webhook with the report. Returns timestamped

      findings citing stable evidence IDs (`audio_NNN`, `frame_NNN`, `ocr_NNN`,

      `signal_NNN`). 3-180 second videos. mp4 / webm /

      quicktime. Built for ad agencies and creators.
  - name: Authentication
    description: Validate API keys and check account status
  - name: Compliance
    description: >-
      Run compliance checks on text + image content (sync). For video, use the
      Video Compliance endpoints above.
  - name: Agents
    description: Discover and invoke individual compliance agents
  - name: Jobs
    description: Poll async job status and view execution traces
  - name: Reports
    description: Retrieve and replay compliance reports
  - name: Observability
    description: Request logs and webhook delivery status
  - name: Billing
    description: Subscriptions, plan changes, and credit balance
  - name: Documents
    description: Extract text from PDF and Word documents before or as part of a check
  - name: Check History
    description: List and retrieve past compliance checks for the workspace
  - name: Provenance
    description: Inspect and sign Content Credentials (C2PA) on images and video
  - name: Corpus
    description: >-
      Review queue for proposed changes to the governed legal corpus (dashboard
      session)
  - name: Webhooks
    description: Saved webhook endpoints (dashboard session) and delivery logs
paths:
  /compliance/check-video/{requestId}:
    get:
      tags:
        - Video Compliance
      summary: Poll video job status + retrieve report
      description: |
        Returns the current state of a video compliance job. When the job is
        terminal (`status: completed | failed`), the full `report` payload is
        inlined in the response — no extra fetch needed.

        **Polling cadence:** every 2 seconds is recommended; the engine has a
        3-minute upper bound on a single job's worker time.

        **`reportFetchFailed`.** Blob storage is eventually-consistent — a
        read immediately after the worker completes can occasionally miss.
        Rather than 500, the response surfaces `reportFetchFailed: true` so
        the client can retry the same endpoint shortly.

        **Tenant scoping.** A `requestId` belonging to a different tenant
        returns 404 (no info leak about another tenant's jobs).
      operationId: getVideoCheckStatus
      parameters:
        - name: requestId
          in: path
          required: true
          schema:
            type: string
          description: The requestId returned by `POST /compliance/check-video`
          example: 82b68316-ed85-489c-991e-2ff0f2b95f29
      responses:
        '200':
          description: Current status + report (when terminal)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoCheckStatusResponse'
        '400':
          description: Missing or malformed requestId
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: No video compliance job for this tenant + requestId
components:
  schemas:
    VideoCheckStatusResponse:
      type: object
      required:
        - requestId
        - tenantId
        - status
      properties:
        requestId:
          type: string
        tenantId:
          type: string
        status:
          type: string
          description: |
            Public 4-state contract. `queued` + `processing` mean the worker is
            in-flight (continue polling). `completed` + `failed` are terminal.
          enum:
            - queued
            - processing
            - completed
            - failed
            - unknown
        phase:
          type: string
          description: >
            Internal worker phase name (e.g. `transcribeAudio`, `analyzeFrames`,
            `done`).

            Useful for showing live progress UI. Not part of the stability
            contract —

            new phases may be added without notice.
        reportStatus:
          type: string
          description: Terminal status of the analysis. Absent until terminal.
          enum:
            - complete
            - insufficient_evidence
            - analysis_failed
        billingStatus:
          type: string
          description: Reservation lifecycle. Absent until the worker resolves billing.
          enum:
            - reserved
            - committed
            - released
        workerCompletedAt:
          type: string
          format: date-time
        completedAt:
          type: string
          format: date-time
        durationMs:
          type: integer
          description: Total worker pipeline duration in milliseconds.
        error:
          type: string
          description: Failure reason. Present when status is `failed`.
        reportBlobPath:
          type: string
          description: >-
            Path to the persisted report.json in blob storage. Informational —
            content is inlined in `report`.
        report:
          $ref: '#/components/schemas/VideoReport'
        reportFetchFailed:
          type: boolean
          description: |
            Present + `true` when the row is terminal but the report blob could
            not be fetched (eventually-consistent storage edge). Retry the same
            endpoint in 1-2 seconds.
    VideoReport:
      type: object
      description: >-
        The contents of the persisted report.json blob, inlined into status
        responses.
      required:
        - schemaVersion
        - preprocessorVersion
        - evidenceVersion
        - tenantId
        - requestId
        - generatedAt
        - status
        - checks
        - preprocessing
      properties:
        schemaVersion:
          type: string
          enum:
            - video-report.v1
        preprocessorVersion:
          type: string
          enum:
            - video-preprocessor.v1
        evidenceVersion:
          type: string
          enum:
            - evidence-timeline.v1
        tenantId:
          type: string
        requestId:
          type: string
        generatedAt:
          type: string
          format: date-time
        status:
          type: string
          enum:
            - complete
            - insufficient_evidence
            - analysis_failed
        reason:
          type: string
          description: Failure / no-evidence reason. Present when status is not `complete`.
        checks:
          type: array
          items:
            $ref: '#/components/schemas/VideoComplianceCheck'
        analysisDiagnostics:
          type: array
          description: >-
            Pipeline diagnostics (boundary-validation drops, evidence
            truncation, etc.). Empty for clean runs.
          items:
            $ref: '#/components/schemas/AnalysisDiagnostic'
        detections:
          description: >-
            Raw vision-detection signals (logos, OCR, labels, safe-search).
            Forensic only.
        preprocessing:
          type: object
          required:
            - transcriptionStatus
            - frameAnalysisStatus
            - degraded
            - evidenceTruncated
          properties:
            transcriptionStatus:
              type: string
              enum:
                - complete
                - skipped
                - failed
            frameAnalysisStatus:
              type: string
              enum:
                - ok
                - partial
                - failed
            degraded:
              type: boolean
              description: True when any diagnostic was emitted.
            evidenceTruncated:
              type: boolean
              description: True when the evidence renderer hit a size ceiling.
    VideoComplianceCheck:
      description: |
        Same shape as `ComplianceCheck` (text/image) with two optional
        video-mode fields. Frame-level deterministic findings (logos,
        on-screen text, restricted-category labels) carry `evidenceIds` +
        `timelineLocation`; broader LLM-derived findings may omit them.
      allOf:
        - $ref: '#/components/schemas/ComplianceCheck'
        - type: object
          properties:
            evidenceIds:
              type: array
              description: >-
                Stable evidence IDs this check cites. Pattern `<track>_NNN`
                where track is `audio`, `frame`, `ocr`, or `signal`.
              items:
                type: string
                pattern: ^(audio|frame|ocr|signal)_\d+$
              example:
                - frame_007
                - ocr_012
            timelineLocation:
              $ref: '#/components/schemas/VideoTimelineLocation'
    AnalysisDiagnostic:
      type: object
      description: |
        First-class pipeline diagnostic. Surfaces non-compliance signals like
        renderer overflow or boundary-validation drops without polluting
        the compliance findings array.
      required:
        - code
        - message
        - severity
      properties:
        code:
          type: string
          description: >-
            Stable machine-readable code (e.g. `evidence_truncated`,
            `video_check_missing_evidence_ids`).
          example: evidence_truncated
        message:
          type: string
          description: Human-readable explanation.
        severity:
          type: string
          enum:
            - info
            - warning
            - error
        evidenceIds:
          type: array
          items:
            type: string
    ComplianceCheck:
      type: object
      description: >
        A single compliance finding. Includes both the raw finding fields

        (checkName, severity, message, recommendation, citation) and structured

        classification metadata added by the engine (id, jurisdictions,
        platforms,

        scope, primaryCategory, categories).
      properties:
        id:
          $ref: '#/components/schemas/CheckId'
        agentId:
          $ref: '#/components/schemas/ComplianceAgentId'
        checkName:
          type: string
          description: Human-readable check name
          example: Unsubstantiated Health Claim - 'Cure Cancer'
        status:
          $ref: '#/components/schemas/ComplianceStatus'
        severity:
          $ref: '#/components/schemas/ComplianceSeverity'
        message:
          type: string
          description: Human-readable description of the issue
          example: >-
            'Guaranteed to cure cancer' is an unsubstantiated health claim under
            FTC and EU UCPD.
        recommendation:
          type: string
          description: Specific action to fix the issue
          example: >-
            Remove the guarantee or substantiate with peer-reviewed clinical
            evidence.
        citation:
          type: string
          description: Legal or policy reference
          example: FTC Endorsement Guides, 16 CFR Part 255
        metadata:
          type: string
          description: Optional JSON string with agent-specific data
        jurisdictions:
          type: array
          items:
            type: string
          description: >
            Canonical jurisdiction codes (us, eu, uk, india, china) this check

            applies to. May be empty when `scope` is `global` or
            `platform-specific`.

            Always a subset of the request's jurisdiction list.
          example:
            - us
            - eu
        platforms:
          type: array
          items:
            type: string
          description: >
            Canonical platform codes (youtube, instagram, facebook, tiktok,
            linkedin)

            this check applies to. May be empty when `scope` is `global` or

            `jurisdiction-specific`. Always a subset of the request's platform
            list.
          example:
            - youtube
            - instagram
        scope:
          $ref: '#/components/schemas/CheckScope'
        primaryCategory:
          $ref: '#/components/schemas/CheckCategory'
        categories:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/CheckCategory'
          description: >
            All matched categories, with `primaryCategory` first. A finding may

            apply to multiple categories (e.g. a deepfake celebrity check
            matches

            both `deepfake-impersonation` and `right-of-publicity`).
          example:
            - unsubstantiated-health-claim
            - performance-claim
    VideoTimelineLocation:
      type: object
      required:
        - startMs
        - endMs
        - track
      properties:
        startMs:
          type: integer
          minimum: 0
          description: Start of the evidence range in milliseconds from video start.
        endMs:
          type: integer
          minimum: 0
          description: >-
            End of the evidence range (>= startMs). Equal to startMs for instant
            signals.
        track:
          type: string
          description: |
            Which video track the evidence lives on. Sub-source granularity
            (frame vs ocr vs signal) lives in `evidenceIds`.
          enum:
            - audio
            - video
            - mixed
    CheckId:
      type: string
      pattern: ^chk_[0-9a-f]{8}$
      description: |
        Stable check identifier. Format: `chk_<8 lowercase hex>`. Generated as a
        SHA-256 hash of (agentId, checkName, citation, sorted jurisdictions,
        sorted platforms, primaryCategory) — stable across reruns of identical
        content + scope + engine version. NOT stable across taxonomy
        reclassifications (primaryCategory change) or content/scope changes.
      example: chk_a1b2c3d4
    ComplianceAgentId:
      type: string
      enum:
        - ai-laws
        - jurisdiction-detection
        - advertising-law
        - platform-policy
        - metadata-labeling
        - rights-clearance
        - rights-clearance-text
        - rights-clearance-image
        - compliance-score
        - fs-compliance-financial-promotion
        - fs-compliance-advisory-suitability
        - fs-compliance-credit-servicing
        - fs-compliance-markets-trading
        - fs-compliance-financial-crime
        - fs-compliance-ai-governance
        - financial-services-compliance
        - pharma-healthcare-compliance
      description: >
        Agent identifier. Use `GET /agents` to discover all available agents
        dynamically.

        The list is filtered to the industries your workspace has selected.


        **Financial services.** The six `fs-compliance-*` agents correspond
        one-to-one to the

        review scopes (`financial_promotion` →
        `fs-compliance-financial-promotion`, and so on).

        In a full check they are selected with `reviewScopes`. Via `POST
        /agents/{agentId}`

        only `fs-compliance-financial-promotion` can be invoked directly today;
        the other five

        return 400 `review_scope_not_enabled` on direct invocation and must run
        through

        `POST /compliance/check`. `financial-services-compliance` is a read-only
        alias of

        `fs-compliance-financial-promotion` accepted for older clients.


        **Pharma and healthcare.** `pharma-healthcare-compliance` runs for
        workspaces on the

        `pharma_healthcare` industry and honours `regulatedActor`.


        `ai-laws` is the canonical id; `jurisdiction-detection` is accepted as
        an

        input alias for backward compatibility with historical clients. New

        integrations should use `ai-laws`.


        **Note on rights-clearance variants.** `GET /agents` exposes two
        registered agents

        for rights clearance: `rights-clearance-text` and
        `rights-clearance-image` — invoke

        them via `POST /agents/{agentId}` using those qualified IDs. On **check
        response

        objects**, however, text rights-clearance findings carry the bare
        `agentId:

        "rights-clearance"`. Treat bare `rights-clearance` and
        `rights-clearance-text` as

        the same logical pipeline — the bare form is the value that appears on
        `checks[]`

        entries from that agent.
    ComplianceStatus:
      type: string
      enum:
        - pass
        - flag
        - block
        - escalate
      description: |
        - `pass` — No issue found
        - `flag` — Issue found, review recommended
        - `block` — Critical issue, must fix
        - `escalate` — Needs human review
    ComplianceSeverity:
      type: string
      enum:
        - critical
        - high
        - medium
        - low
        - info
      description: |
        - `critical` — Legal liability risk (-25 points)
        - `high` — Likely violation (-15 points)
        - `medium` — Potential issue (-8 points)
        - `low` — Minor concern (-3 points)
        - `info` — Informational only (0 points)
    CheckScope:
      type: string
      enum:
        - global
        - jurisdiction-specific
        - platform-specific
        - cross-cutting
      description: |
        Disambiguates the empty-array case for `jurisdictions` and `platforms`:
        - `global` — universal; both arrays empty
        - `jurisdiction-specific` — jurisdictions populated, platforms empty
        - `platform-specific` — platforms populated, jurisdictions empty
        - `cross-cutting` — both populated; check applies at the intersection
    CheckCategory:
      type: string
      enum:
        - celebrity-endorsement
        - expert-authority
        - fabricated-testimonial
        - material-connection-disclosure
        - unsubstantiated-health-claim
        - medical-efficacy-claim
        - safety-claim
        - performance-claim
        - comparative-advertising
        - right-of-publicity
        - trademark-infringement
        - copyright-infringement
        - music-licensing
        - ai-disclosure-missing
        - watermark-missing
        - c2pa-missing
        - deepfake-impersonation
        - disguised-advertising
        - sponsored-content-labeling
        - consumer-information-disclosure
        - scarcity-urgency
        - aggressive-practice
        - algorithmic-amplification
        - minor-targeting
        - vulnerable-audience
        - platform-policy-violation
        - data-privacy
        - jurisdiction-coverage-gap
        - other
      description: |
        Top-level breach taxonomy. New categories may be added in minor versions
        (additive only); renaming and removal are forbidden. Clients MUST accept
        unknown enum values gracefully (forward-compat). `other` is the fallback
        bucket for findings that don't fit any specific category.
  responses:
    Unauthorized:
      description: |
        Invalid, missing, or expired API key. Standard error envelope —
        read `message` for the human-readable reason.
      content:
        application/json:
          schema:
            type: object
            description: Standard error envelope.
            required:
              - statusCode
              - message
            properties:
              error:
                type: boolean
                example: true
              url:
                type: string
                format: uri
                example: https://api.zebratruth.ai/v1/whoami
              statusCode:
                type: integer
                example: 401
              statusMessage:
                type: string
                example: Invalid API key
              message:
                type: string
                description: Canonical human-readable reason — pattern-match on this field.
                example: Invalid API key
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        API key starting with `zt_live_` (production) or `zt_test_` (sandbox).
        Get your key at https://developers.zebratruth.ai

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.