> ## 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.

# Register a signer

> Registers your organisation's signing certificate and endpoint. The chain is validated
against the trust anchors, the endpoint is challenged, and proof of possession of the
leaf key is verified before the signer becomes `active`. Rejections are persisted as a
`failed` signer so they appear in the list with `rejectionCode`.

This is an owner-only, dashboard-session action: it requires a recent-authentication
proof (`X-Recent-Auth-Proof`) and an `Idempotency-Key`, and cannot be performed with an
API key. Fetch `GET /media/provenance/signing-keys` first so your endpoint can verify
the challenge. Not billed.




## OpenAPI

````yaml /openapi/zebratruth-v1.yaml post /media/provenance/signers
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:
  /media/provenance/signers:
    post:
      tags:
        - Provenance
      summary: Register a signer
      description: >
        Registers your organisation's signing certificate and endpoint. The
        chain is validated

        against the trust anchors, the endpoint is challenged, and proof of
        possession of the

        leaf key is verified before the signer becomes `active`. Rejections are
        persisted as a

        `failed` signer so they appear in the list with `rejectionCode`.


        This is an owner-only, dashboard-session action: it requires a
        recent-authentication

        proof (`X-Recent-Auth-Proof`) and an `Idempotency-Key`, and cannot be
        performed with an

        API key. Fetch `GET /media/provenance/signing-keys` first so your
        endpoint can verify

        the challenge. Not billed.
      operationId: registerProvenanceSigner
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - name: X-Recent-Auth-Proof
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProvenanceSignerRegisterRequest'
      responses:
        '201':
          description: Signer registered and active
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProvenanceSignerRegisterResponse'
        '400':
          description: >-
            `data.code`: `invalid_request` (carries `issues`),
            `idempotency_key_required`, `recent_auth_action_mismatch`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CodedError'
        '401':
          description: >-
            `data.code`: `proof_invalid`, `access_principal_required`,
            `recent_auth_required`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CodedError'
        '403':
          $ref: '#/components/responses/ForbiddenCoded'
        '422':
          description: >-
            `data.code`: `certificate_unparseable`, `chain_incomplete`,
            `chain_untrusted`, `certificate_expired`,
            `certificate_not_yet_valid`, `algorithm_mismatch`,
            `certificate_not_signing_capable`, `endpoint_unreachable`,
            `endpoint_invalid_response`, `proof_of_possession_failed`. All but
            the first carry `signerId` of the persisted failed signer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CodedError'
        '503':
          description: >-
            `data.code`: `trust_anchors_unavailable`, `platform_misconfigured`
            (signer left `pending`, carries `signerId`, `retryable: true`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CodedError'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        format: uuid
      description: >
        Unique request identifier to prevent duplicate execution and
        double-charging.

        Generate a new UUID for each distinct request. Reuse the same key to
        safely retry.
  schemas:
    ProvenanceSignerRegisterRequest:
      type: object
      required:
        - displayName
        - legalEntity
        - algorithm
        - endpointUrl
        - certificateChainPem
      properties:
        displayName:
          type: string
          minLength: 1
          maxLength: 120
        legalEntity:
          type: string
          minLength: 1
          maxLength: 200
        algorithm:
          type: string
          enum:
            - es256
            - es384
            - es512
            - ps256
            - ps384
            - ps512
            - ed25519
        endpointUrl:
          type: string
          format: uri
          description: >-
            Your signing endpoint. It is challenged during registration and
            called for every signature; requests to it are signed with the keys
            from `GET /media/provenance/signing-keys`.
        certificateChainPem:
          type: string
          description: >-
            Public certificate chain, leaf first, PEM. Up to 512 KB. Must
            terminate at an accepted trust anchor.
        certificateId:
          type: string
          maxLength: 200
    ProvenanceSignerRegisterResponse:
      type: object
      properties:
        signer:
          $ref: '#/components/schemas/ProvenanceSigner'
        trustAnchor:
          type: object
          properties:
            subject:
              type: string
              nullable: true
            source:
              type: string
              enum:
                - refreshed
                - pinned
                - unavailable
            version:
              type: string
            testAnchor:
              type: boolean
            warning:
              type: string
              description: >-
                Present only when the chain reached a non-production test
                anchor.
    CodedError:
      type: object
      description: >
        Standard error envelope. `data.code` is the stable discriminator to
        branch on;

        `statusMessage` is the human-readable reason. Unless a response
        documents extra

        named fields, `data` is reduced to `{ code }` before it is sent.
      required:
        - statusCode
        - message
      properties:
        error:
          type: boolean
          example: true
        url:
          type: string
          format: uri
        statusCode:
          type: integer
        statusMessage:
          type: string
        message:
          type: string
        data:
          type: object
          required:
            - code
          properties:
            code:
              type: string
              example: review_scope_not_enabled
          additionalProperties: true
    ProvenanceSigner:
      type: object
      description: A registered signer. The certificate chain itself is never returned.
      properties:
        tenantId:
          type: string
        signerId:
          type: string
        displayName:
          type: string
        legalEntity:
          type: string
        algorithm:
          type: string
          enum:
            - es256
            - es384
            - es512
            - ps256
            - ps384
            - ps512
            - ed25519
        endpointUrl:
          type: string
          format: uri
        certificateId:
          type: string
          nullable: true
        status:
          type: string
          enum:
            - pending
            - active
            - failed
            - expired
            - revoked
        rejectionCode:
          type: string
          nullable: true
        rejectionDetail:
          type: string
          nullable: true
        subject:
          type: string
        issuer:
          type: string
        validFrom:
          type: string
          format: date-time
        validTo:
          type: string
          format: date-time
        fingerprintSha256:
          type: string
        createdAt:
          type: string
          format: date-time
        verifiedAt:
          type: string
          format: date-time
          nullable: true
  responses:
    ForbiddenCoded:
      description: >
        The credential is valid but may not perform this action. `data.code` is
        one of

        `permission_not_granted`, `principal_forbidden_control_plane` (an API
        key called a

        dashboard-only action), `membership_not_active`, `entitlement_required`,

        `workspace_provisioning`, `workspace_deletion_scheduled`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CodedError'
  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.