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

> ## Agent Instructions
> The OpenAPI document at /api-reference/openapi.yaml defines the target contract. Its x-reflections-availability field and each operation's availability notice identify supported test and live forms. Do not infer implementation from a schema or code sample. Live keys support account details, reads of the licenses the calling account holds as licensee or issued as talent (GET /v1/licenses?role=issuer), and GET /v1/generations?license=… for the state of outputs under such a license (summaries only: no prompt, reference, bytes or metadata). Live image checks, submissions and receipts are built but not activated: until activation, a live POST /v1/checks or /v1/generations returns 403 live_not_activated, which must not be retried. Discovery and JWKS are at the origin root (https://app.reflections.ai/.well-known/...), not under /v1.
> Three rules hold everywhere: a decision is never an error (deny and escalate are 200 responses, and a live check still evaluating is a 202 with status checking); generate nothing for a named talent without an allow; deliver nothing until the generation is allow.
> The sandbox accepts personal rk_test_ keys. Persist a separate Idempotency-Key and body for each logical /v1 POST; retry an unknown outcome with the same key and body. OAuth and Talent API MCP remain planned.

# Create a generation

> **Test mode available. Live mode available when configured.** Source support does not
establish production activation. Until activation, a live key receives `403`
[`live_not_activated`](/api-reference/errors#live_not_activated). Sandbox decisions are simulated; inline base64 or
SHA-256 attestation is supported, but file IDs and URL fetching are not.

The initial live implementation accepts one inline, still PNG, at most 7 MiB
(7,340,032 decoded bytes), in a JSON body of at most 10 MiB. Send its exact lowercase
SHA-256, `candidate_index: 0`, and the check's declared provider and model. A supplied
candidate count must be one; `job_id` is optional and may be assigned after the provider
starts. Digest-only attestation, files, URLs, sessions, video, audio, transcripts and
watermark inputs are unsupported. Reflections evaluates the submitted bytes; it does not
render or fetch the output.

Send an `Idempotency-Key`. The same caller key must hold both `checks:write` and
`generations:write`. Live admission requires the new signed external-image and retention
terms and an activated live signer, as described for [checks](/api-reference/checks/create-a-check).
Send the allowed `check` ID; the server reads its stored authorization token. There is
no separate token field in this request. The first successful submission must arrive
before `authorization.expires_at`, even if the provider job started earlier; otherwise
it fails with `409 check_expired`.
A successful POST always returns the immutable accepted `202` response, including on
replay. Poll the generation for `checking`, `held`, `released`, `denied` or `expired`.
Every image requires the talent's actual release before `decision: "allow"`; upload or
evaluator success alone never permits delivery. No live webhooks are delivered.

**Broader protocol contract:** the remaining description and examples include planned
forms beyond that initial live implementation.

Checks an output before anyone sees it.

The output is checked against the license its `check` relied on: the bytes are bound to the
check and candidate, and the talent's protected attributes and rules are checked on the
bytes. Only the talent the check covered are checked. Every generation names a `check`, or
a `session` for an output made in a live session.

Images, speech up to 60 seconds and text return a decision in the response. Video and longer
audio return `status: checking`, and the decision arrives as `generation.allowed` or
`generation.denied`. When the license has a person release every output, they return
`status: held` instead, and the decision arrives as `generation.released` or
`generation.denied`.

Deliver nothing until the decision is `allow`. Embed the `c2pa` assertion in the output's C2PA
manifest before you deliver it. Send `c2pa_signer` with the thumbprint of the certificate
that will sign that manifest's claim: the receipt then names it as `tlp.c2pa_signer`, and a
verifier that checks the manifest can reject a copy of the assertion in a manifest another
certificate signed. `POST /v1/verifications` does not read manifests yet. Without it, the
receipt is unbound to any file.

Restricted keys need `generations:write`.




## OpenAPI

````yaml /api-reference/openapi.yaml post /generations
openapi: 3.1.0
info:
  title: Reflections Talent API
  version: '2026-10-15'
  summary: The license server for a person's name, likeness and voice in generative AI.
  description: >
    This document defines the target Talent API contract. Each operation
    declares its current

    test and live availability. Test mode serves a limited fictional sandbox.
    Live keys support

    account details and reading the caller's own licenses. The initial live
    image check,

    submission and receipt implementation is deployed, but requires separate
    live signing

    activation and production acceptance. Start at
    https://docs.reflections.ai/quickstart for test mode.


    The target API lets any product that can generate a real person check
    whether a use is licensed,

    verify the output it made, prove that verification to anyone downstream,
    report usage, and

    honor revocations.


    Protected requests use a secret key in the `Authorization` header. The
    target contract defines test keys

    (`rk_test_…`) and live keys (`rk_live_…`) use the same base URL; the key
    decides the mode.


    A decision is never an error. `deny` and `escalate` are `200` responses that
    carry a decision.

    Errors use RFC 9457 problem details.
  contact:
    name: Reflections developer support
    url: https://docs.reflections.ai/production/support
    email: developers@reflections.ai
servers:
  - url: https://app.reflections.ai/v1
    description: >-
      Fictional test sandbox and conditional live support; availability and
      activation are separate
security:
  - SecretKey: []
tags:
  - name: Account
    description: The account that owns the calling key.
  - name: Talent
    description: >-
      People whose name, likeness and voice are protected and licensed through
      Reflections.
  - name: Facets
    description: >-
      The parts of a talent's identity a license can cover, such as a voice or a
      likeness.
  - name: Resolutions
    description: Find which talent a prompt, image or voice sample invokes.
  - name: Licenses
    description: Signed licenses and their revisions.
  - name: License requests
    description: Ask a talent for a new license or a wider one.
  - name: Connections
    description: A licensee's permission for a platform to use its licenses.
  - name: Files
    description: References and outputs uploaded for checks and generations.
  - name: Checks
    description: Decide whether a use may proceed, before anything is generated.
  - name: Generations
    description: Check an output against the license its check relied on.
  - name: Sessions
    description: Authorize live voice and video with short-lived tokens and sampled checks.
  - name: Receipts
    description: Signed, portable proof of a decision.
  - name: Verifications
    description: Verify a file, manifest or receipt.
  - name: Revocations
    description: Every narrowing of consent, and the platform's acknowledgement of it.
  - name: Usage records
    description: Report usage for settlement and audit.
  - name: Statements
    description: Monthly amounts owed under a license, reconciled against observed usage.
  - name: Mandates
    description: A representative's authority to act for a talent, and its powers.
  - name: Escalations
    description: >-
      The review queue. Checks and held outputs waiting for the talent's side to
      decide.
  - name: License drafts
    description: Terms prepared for a talent's signature. Only a person signs.
  - name: Webhook endpoints
    description: Where Reflections sends events.
  - name: Events
    description: The record of everything that happened to your objects.
  - name: Test helpers
    description: Act as a talent or reviewer in test mode.
  - name: Discovery
    description: The public discovery document and signing keys. Neither needs a key.
  - name: OAuth
    description: >
      Authorization for connections, MCP clients and RSL clients, and the
      metadata that describes it.
paths:
  /generations:
    post:
      tags:
        - Generations
      summary: Create a generation
      description: >
        **Test mode available. Live mode available when configured.** Source
        support does not

        establish production activation. Until activation, a live key receives
        `403`

        [`live_not_activated`](/api-reference/errors#live_not_activated).
        Sandbox decisions are simulated; inline base64 or

        SHA-256 attestation is supported, but file IDs and URL fetching are not.


        The initial live implementation accepts one inline, still PNG, at most 7
        MiB

        (7,340,032 decoded bytes), in a JSON body of at most 10 MiB. Send its
        exact lowercase

        SHA-256, `candidate_index: 0`, and the check's declared provider and
        model. A supplied

        candidate count must be one; `job_id` is optional and may be assigned
        after the provider

        starts. Digest-only attestation, files, URLs, sessions, video, audio,
        transcripts and

        watermark inputs are unsupported. Reflections evaluates the submitted
        bytes; it does not

        render or fetch the output.


        Send an `Idempotency-Key`. The same caller key must hold both
        `checks:write` and

        `generations:write`. Live admission requires the new signed
        external-image and retention

        terms and an activated live signer, as described for
        [checks](/api-reference/checks/create-a-check).

        Send the allowed `check` ID; the server reads its stored authorization
        token. There is

        no separate token field in this request. The first successful submission
        must arrive

        before `authorization.expires_at`, even if the provider job started
        earlier; otherwise

        it fails with `409 check_expired`.

        A successful POST always returns the immutable accepted `202` response,
        including on

        replay. Poll the generation for `checking`, `held`, `released`, `denied`
        or `expired`.

        Every image requires the talent's actual release before `decision:
        "allow"`; upload or

        evaluator success alone never permits delivery. No live webhooks are
        delivered.


        **Broader protocol contract:** the remaining description and examples
        include planned

        forms beyond that initial live implementation.


        Checks an output before anyone sees it.


        The output is checked against the license its `check` relied on: the
        bytes are bound to the

        check and candidate, and the talent's protected attributes and rules are
        checked on the

        bytes. Only the talent the check covered are checked. Every generation
        names a `check`, or

        a `session` for an output made in a live session.


        Images, speech up to 60 seconds and text return a decision in the
        response. Video and longer

        audio return `status: checking`, and the decision arrives as
        `generation.allowed` or

        `generation.denied`. When the license has a person release every output,
        they return

        `status: held` instead, and the decision arrives as
        `generation.released` or

        `generation.denied`.


        Deliver nothing until the decision is `allow`. Embed the `c2pa`
        assertion in the output's C2PA

        manifest before you deliver it. Send `c2pa_signer` with the thumbprint
        of the certificate

        that will sign that manifest's claim: the receipt then names it as
        `tlp.c2pa_signer`, and a

        verifier that checks the manifest can reject a copy of the assertion in
        a manifest another

        certificate signed. `POST /v1/verifications` does not read manifests
        yet. Without it, the

        receipt is unbound to any file.


        Restricted keys need `generations:write`.
      operationId: createGeneration
      parameters:
        - $ref: '#/components/parameters/ReflectionsVersion'
        - $ref: '#/components/parameters/ReflectionsAccount'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerationCreate'
            examples:
              sandbox_inline_png:
                summary: Supported sandbox request (replace object IDs with your own)
                value:
                  check: chk_3m7p4r6s9t0wxyhk5zba2q8v1n
                  candidate_index: 0
                  artifact:
                    data: >-
                      iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==
                    sha256: >-
                      20c1e1ec7a62d54fe8191b5c509e7a2c88b520a429bc1b74c55e7ccf72cbcc6d
                    media_type: image/png
              enforce:
                summary: An output under a check
                value:
                  check: chk_3m7p4r6s9t0wxyhk5zba2q8v1n
                  candidate_index: 0
                  artifact:
                    file: file_2c4e6g8j0k2m4n6p8q0r2s4t6v
                    sha256: >-
                      9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a
                  execution:
                    provider: example-image-provider
                    model: image-model-3
                    job_id: job_88213
              c2pa_bound:
                summary: An output whose receipt names its C2PA claim signer
                value:
                  check: chk_3m7p4r6s9t0wxyhk5zba2q8v1n
                  candidate_index: 0
                  artifact:
                    file: file_2c4e6g8j0k2m4n6p8q0r2s4t6v
                    sha256: >-
                      9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a
                  execution:
                    provider: example-image-provider
                    model: image-model-3
                    job_id: job_88213
                  c2pa_signer:
                    thumbprint: >-
                      sha256:5d2a8c0e4b6f1a3c5e7d9b0f2a4c6e8d0b2f4a6c8e0d2b4f6a8c0e2d4b6f8a1c
      responses:
        '200':
          description: The generation.
          headers:
            Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Generation'
              examples:
                held:
                  $ref: '#/components/examples/GenerationHeld'
                allowed:
                  $ref: '#/components/examples/GenerationAllowed'
                denied:
                  $ref: '#/components/examples/GenerationDenied'
        '202':
          description: >-
            The initial live image submission's immutable accepted object. POST
            retries replay this response; GET the generation for evaluation,
            talent review and its final decision.
          headers:
            Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Generation'
              examples:
                live_accepted:
                  summary: Accepted for live image evaluation, pending talent release
                  value:
                    id: gen_6s9t0wxyhk5zba2q8v1m3n7p4r
                    object: generation
                    livemode: true
                    check: chk_3m7p4r6s9t0wxyhk5zba2q8v1n
                    session: null
                    candidate_index: 0
                    status: checking
                    decision: null
                    artifact:
                      file: null
                      sha256: >-
                        20c1e1ec7a62d54fe8191b5c509e7a2c88b520a429bc1b74c55e7ccf72cbcc6d
                      media_type: image/png
                      duration_ms: null
                    execution:
                      provider: example-image-provider
                      model: image-model-3
                    findings: []
                    unchecked_terms: []
                    reasons: []
                    obligations: []
                    escalation: null
                    assurance: attested
                    receipt: null
                    c2pa: null
                    watermark: null
                    metadata: {}
                    created_at: '2026-10-18T18:00:12Z'
                    decided_at: null
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
        '503':
          $ref: '#/components/responses/Unavailable'
      security:
        - SecretKey:
            - generations:write
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >
            # Set a unique key once per new action; persist it and reuse it for
            every retry.

            : "${REFLECTIONS_KEY:?Set REFLECTIONS_KEY before running this
            example}"

            : "${REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY:?Set
            REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY before running this
            example}"


            curl --fail-with-body --max-time 30 -X POST
            'https://app.reflections.ai/v1/generations' \
              -H "Authorization: Bearer $REFLECTIONS_KEY" \
              -H "Reflections-Version: 2026-10-15" \
              -H "Idempotency-Key: $REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY" \
              -H "Content-Type: application/json" \
              --data-raw '{
              "check": "chk_3m7p4r6s9t0wxyhk5zba2q8v1n",
              "candidate_index": 0,
              "artifact": {
                "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==",
                "sha256": "20c1e1ec7a62d54fe8191b5c509e7a2c88b520a429bc1b74c55e7ccf72cbcc6d",
                "media_type": "image/png"
              }
            }'
        - lang: typescript
          label: TypeScript
          source: >
            import { env, exit } from "node:process";


            // Set a unique key once per new action; persist it and reuse it for
            every retry.

            const apiKey = env.REFLECTIONS_KEY;

            if (!apiKey) throw new Error("Set REFLECTIONS_KEY before running
            this example");

            const idempotencyKey =
            env.REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY;

            if (!idempotencyKey) throw new Error("Set
            REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY before running this
            example");


            const response = await
            fetch("https://app.reflections.ai/v1/generations", {
              method: "POST",
              headers: {
                Authorization: `Bearer ${apiKey}`,
                "Reflections-Version": "2026-10-15",
                "Idempotency-Key": idempotencyKey,
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                "check": "chk_3m7p4r6s9t0wxyhk5zba2q8v1n",
                "candidate_index": 0,
                "artifact": {
                  "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==",
                  "sha256": "20c1e1ec7a62d54fe8191b5c509e7a2c88b520a429bc1b74c55e7ccf72cbcc6d",
                  "media_type": "image/png"
                }
              }),
              signal: AbortSignal.timeout(30_000),
            });

            const responseBody = await response.text();

            if (!response.ok) {
              console.error(`HTTP ${response.status}: ${responseBody}`);
              exit(1);
            }

            console.log(responseBody);
        - lang: python
          label: Python
          source: >
            import json

            import os

            from urllib.error import HTTPError

            from urllib.request import Request, urlopen


            # Set a unique key once per new action; persist it and reuse it for
            every retry.

            apiKey = os.environ["REFLECTIONS_KEY"]

            if not apiKey:
                raise ValueError("Set REFLECTIONS_KEY before running this example")
            idempotencyKey =
            os.environ["REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY"]

            if not idempotencyKey:
                raise ValueError("Set REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY before running this example")

            headers = {
                "Authorization": f"Bearer {apiKey}",
                "Reflections-Version": "2026-10-15",
                "Idempotency-Key": idempotencyKey,
                "Content-Type": "application/json",
            }

            data = json.dumps({
                "check": "chk_3m7p4r6s9t0wxyhk5zba2q8v1n",
                "candidate_index": 0,
                "artifact": {
                    "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==",
                    "sha256": "20c1e1ec7a62d54fe8191b5c509e7a2c88b520a429bc1b74c55e7ccf72cbcc6d",
                    "media_type": "image/png",
                },
            }).encode("utf-8")

            request = Request("https://app.reflections.ai/v1/generations",
                              method="POST", headers=headers, data=data)
            try:
                with urlopen(request, timeout=30) as response:
                    print(response.read().decode("utf-8"))
            except HTTPError as error:
                error_body = error.read().decode("utf-8")
                raise RuntimeError(f"HTTP {error.code}: {error_body}") from error
        - lang: go
          label: Go
          source: |
            package main

            import (
                "fmt"
                "io"
                "net/http"
                "os"
                "strings"
                "time"
            )

            func main() {
                // Set a unique key once per new action; persist it and reuse it for every retry.
                apiKey := os.Getenv("REFLECTIONS_KEY")
                if apiKey == "" {
                    panic("Set REFLECTIONS_KEY before running this example")
                }
                idempotencyKey := os.Getenv("REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY")
                if idempotencyKey == "" {
                    panic("Set REFLECTIONS_CREATE_GENERATION_IDEMPOTENCY_KEY before running this example")
                }

                body := strings.NewReader(`{
                  "check": "chk_3m7p4r6s9t0wxyhk5zba2q8v1n",
                  "candidate_index": 0,
                  "artifact": {
                    "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==",
                    "sha256": "20c1e1ec7a62d54fe8191b5c509e7a2c88b520a429bc1b74c55e7ccf72cbcc6d",
                    "media_type": "image/png"
                  }
                }`)
                request, err := http.NewRequest("POST", "https://app.reflections.ai/v1/generations", body)
                if err != nil {
                    panic(err)
                }
                request.Header.Set("Authorization", "Bearer " + apiKey)
                request.Header.Set("Reflections-Version", "2026-10-15")
                request.Header.Set("Idempotency-Key", idempotencyKey)
                request.Header.Set("Content-Type", "application/json")
                client := &http.Client{Timeout: 30 * time.Second}
                response, err := client.Do(request)
                if err != nil {
                    panic(err)
                }
                defer response.Body.Close()
                responseBody, err := io.ReadAll(response.Body)
                if err != nil {
                    panic(err)
                }
                if response.StatusCode < 200 || response.StatusCode >= 300 {
                    panic(fmt.Sprintf("HTTP %d: %s", response.StatusCode, responseBody))
                }
                fmt.Print(string(responseBody))
            }
components:
  parameters:
    ReflectionsVersion:
      name: Reflections-Version
      in: header
      required: false
      description: >-
        The dated API version. Defaults to the version your account is pinned
        to.
      schema:
        type: string
        example: '2026-10-15'
    ReflectionsAccount:
      name: Reflections-Account
      in: header
      required: false
      description: >
        Act for a connected licensee. The value is the licensee's account ID.
        Requires an active

        connection between that account and yours.
      schema:
        type: string
        pattern: ^acct_[0-9a-hjkmnp-tv-z]{26}$
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >
        A unique key for this operation, up to 255 characters. In test mode,
        POST keys are scoped

        to your account and mode and bind the endpoint and body for 24 hours. A
        different endpoint

        or body with the same key is refused.


        Initial live check and generation creation require a nonempty key. Each
        operation has a

        separate account-scoped namespace; retain the same API key, body and
        idempotency key for

        retries within 24 hours of creation. A pending check returns `202` with
        `status: "checking"`.

        Completed checks replay their sealed response; successful generation
        POSTs replay the

        original accepted `202`, so use GET for current state. Live verification
        is a read-only

        query that returns a fresh verification ID on each call, without exact
        response caching.


        The broader delegated-account contract also scopes keys to
        `Reflections-Account`;

        delegated requests and the other planned live POST operations remain
        unsupported.
      schema:
        type: string
        maxLength: 255
  schemas:
    GenerationCreate:
      type: object
      required:
        - artifact
      oneOf:
        - required:
            - check
        - required:
            - session
      properties:
        check:
          type: string
          pattern: ^chk_[0-9a-hjkmnp-tv-z]{26}$
          description: >-
            The check this output was made under. Required unless `session` is
            set.
        session:
          type: string
          pattern: ^ses_[0-9a-hjkmnp-tv-z]{26}$
          description: The session this output was made in, instead of a `check`.
        candidate_index:
          type: integer
          minimum: 0
          maximum: 15
          description: >-
            Which of the check's `execution.candidates` this is, from 0. Omit
            under `reuse`.
        artifact:
          $ref: '#/components/schemas/Artifact'
          description: >-
            The output's bytes, as a file ID, a URL or base64 `data`, with their
            SHA-256.
        execution:
          $ref: '#/components/schemas/Execution'
          description: >-
            The run that made the output. Send `job_id` when the provider gives
            one.
        transcript:
          type: string
          maxLength: 32000
          description: >-
            Words spoken in the output, if you have them. Reflections
            transcribes regardless.
        watermark:
          type: object
          description: >-
            A watermark you applied, so verification can join it to this
            generation.
          properties:
            algorithm:
              type: string
              description: The watermarking method you used.
            id:
              type: string
              description: The watermark's identifier, as embedded in the output.
        c2pa_signer:
          $ref: '#/components/schemas/C2paSigner'
          description: >
            The certificate that will sign the output's C2PA claim. The receipt
            signs its

            thumbprint as `tlp.c2pa_signer`, as given; Reflections does not
            check it against a

            certificate. A verifier that checks the manifest can then reject the
            assertion in a

            manifest another certificate signed. Without it, the receipt is
            evidence of a decision,

            not of a particular file.
        metadata:
          $ref: '#/components/schemas/Metadata'
          description: Your own keys, returned on the generation.
    Generation:
      type: object
      required:
        - id
        - object
        - livemode
        - status
        - assurance
        - created_at
      properties:
        id:
          type: string
          pattern: ^gen_[0-9a-hjkmnp-tv-z]{26}$
          description: The generation's ID, `gen_` followed by 26 characters.
        object:
          type: string
          const: generation
          description: Always `generation`.
        livemode:
          type: boolean
          description: '`true` in live mode, `false` in test mode.'
        check:
          type:
            - string
            - 'null'
          pattern: ^chk_[0-9a-hjkmnp-tv-z]{26}$
          description: >-
            The check the output was made under. Null for an output made in a
            session.
        session:
          type:
            - string
            - 'null'
          pattern: ^ses_[0-9a-hjkmnp-tv-z]{26}$
          description: >-
            The session the output was made in. Null for an output made under a
            check.
        candidate_index:
          type:
            - integer
            - 'null'
          description: >
            Which of the check's candidates this is, from 0. Null under `reuse`
            and for an output

            made in a session.
        status:
          $ref: '#/components/schemas/GenerationStatus'
          description: Where the output is. Deliver only on `allowed` or `released`.
        decision:
          description: >
            `allow`, `deny`, or `escalate` while a reviewer must release the
            output. Null while

            `status` is `checking`.
          oneOf:
            - $ref: '#/components/schemas/Decision'
            - type: 'null'
        artifact:
          type:
            - object
            - 'null'
          description: The output that was checked.
          properties:
            file:
              type:
                - string
                - 'null'
              description: >
                The file the output was uploaded as. Null when it was sent as
                `url` or `data`.
            sha256:
              $ref: '#/components/schemas/Sha256Hex'
              description: >
                The SHA-256 of the checked bytes. The receipt carries it as
                `artifact_sha256`.
            media_type:
              type: string
              description: The output's media type, such as `image/png`.
            duration_ms:
              type:
                - integer
                - 'null'
              description: Length in milliseconds, for audio and video. Null otherwise.
        execution:
          $ref: '#/components/schemas/Execution'
          description: The run that made the output, as you stated it.
        findings:
          type: array
          items:
            $ref: '#/components/schemas/Finding'
          description: Each rule checked on the bytes, with its result.
        unchecked_terms:
          type: array
          items:
            $ref: '#/components/schemas/Address'
          description: >
            Addresses of rules the talent wrote that could not be checked on
            these bytes. They do

            not withhold the output.
        reasons:
          type: array
          items:
            $ref: '#/components/schemas/Reason'
          description: Why the output was denied or expired. Empty otherwise.
        obligations:
          type: array
          items:
            $ref: '#/components/schemas/Obligation'
          description: >
            What you must do with this output, such as embed `c2pa` and show the
            disclosure, or keep

            it private while `held`.
        escalation:
          description: >-
            The release review, when a person must release the output. Null
            otherwise.
          oneOf:
            - $ref: '#/components/schemas/Escalation'
            - type: 'null'
        assurance:
          type: string
          enum:
            - observed
            - attested
          description: >-
            `observed`: Reflections checked these bytes. `attested`: Reflections
            recorded what you stated without checking it.
        receipt:
          type:
            - string
            - 'null'
          pattern: ^rcpt_[0-9a-hjkmnp-tv-z]{26}$
          description: >
            The receipt that records the decision. Null while the output is
            `checking` or `held`,

            and after a withdrawal from review.
        c2pa:
          description: >
            The assertion to embed in the output's C2PA manifest before you
            deliver it. Null unless

            `decision` is `allow`.
          oneOf:
            - $ref: '#/components/schemas/C2paAssertion'
            - type: 'null'
        watermark:
          type:
            - object
            - 'null'
          description: The watermark you registered on the generation. Null if none.
          properties:
            algorithm:
              type: string
              description: The watermarking method you used.
            id:
              type: string
              description: The watermark's identifier, as embedded in the output.
        metadata:
          $ref: '#/components/schemas/Metadata'
          description: Your metadata from the request.
        created_at:
          type: string
          format: date-time
          description: When the output was submitted.
        decided_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When the output was allowed, released, denied or expired. Null
            otherwise.
    Artifact:
      type: object
      description: >-
        The sandbox accepts inline data or SHA-256 attestation. Inline data is
        at most 7 MiB decoded; the entire JSON body is at most 10 MiB. File IDs
        and URLs are planned contract forms.
      required:
        - sha256
      properties:
        file:
          type: string
          pattern: ^file_[0-9a-hjkmnp-tv-z]{26}$
          description: A file uploaded with `purpose=output`.
        url:
          type: string
          format: uri
          description: A URL Reflections can fetch the bytes from.
        data:
          type: string
          description: >-
            Base64 bytes. Sandbox limit: 7 MiB decoded (7,340,032 bytes); total
            JSON request limit: 10 MiB.
          contentEncoding: base64
        sha256:
          $ref: '#/components/schemas/Sha256Hex'
          description: >
            The SHA-256 of the bytes. If the bytes Reflections receives differ,
            the call fails with

            `422 artifact_digest_mismatch`.
        media_type:
          type: string
          example: image/png
          description: The bytes' media type, such as `image/png`.
        duration_ms:
          type: integer
          minimum: 0
          description: For audio and video.
    Execution:
      type: object
      description: >
        Which model will run, or ran, the request. Reflections records it as
        stated by the

        platform (`assurance: attested`).
      properties:
        provider:
          type: string
          maxLength: 100
          description: The model provider.
        model:
          type: string
          maxLength: 100
          description: The model's name at the provider.
        candidates:
          type: integer
          minimum: 1
          maximum: 16
          description: Outputs this request will produce.
        job_id:
          type: string
          maxLength: 200
          description: The provider's ID for the job.
    C2paSigner:
      type: object
      required:
        - thumbprint
      additionalProperties: false
      properties:
        thumbprint:
          type: string
          pattern: ^sha256:[0-9a-f]{64}$
          description: >
            `sha256:` and the lowercase hex SHA-256 of the DER encoding of the
            certificate that

            signs the C2PA claim, the end-entity certificate in the manifest's
            signature.
    Metadata:
      type: object
      description: >-
        Up to 50 keys of your own, each up to 40 characters, values up to 500
        characters. Never put personal data here.
      additionalProperties:
        type: string
        maxLength: 500
      maxProperties: 50
    GenerationStatus:
      type: string
      description: >
        `checking`: not decided yet. `allowed`: deliver. `denied`: never
        deliver. `held`: waiting

        for release. `released`: a reviewer released it; deliver. `expired`:
        never reviewed.

        `withdrawn`: you withdrew it.
      enum:
        - checking
        - allowed
        - denied
        - held
        - released
        - expired
        - withdrawn
    Decision:
      type: string
      description: >
        `allow`: proceed and meet the obligations. `deny`: do not proceed.
        `escalate`: wait; a

        person with authority will decide, and an unanswered escalation becomes
        `deny`.
      enum:
        - allow
        - deny
        - escalate
    Sha256Hex:
      type: string
      description: A SHA-256 digest of bytes, as 64 lowercase hex characters.
      pattern: ^[0-9a-f]{64}$
    Finding:
      type: object
      required:
        - term
        - result
      properties:
        term:
          $ref: '#/components/schemas/Address'
          description: The term's address, such as `license:lic_…/terms.neverExtras`.
        attribute:
          type: string
          description: A protected attribute, such as `identity.samePerson`.
        rule:
          type: string
          description: A rule the talent wrote, as written.
        result:
          type: string
          enum:
            - preserved
            - violated
            - unchecked
          description: >-
            `unchecked`: the check could not read this rule. Talent-written
            rules that are unchecked are delivered and recorded; protected
            attributes never are.
        detail:
          type: string
          description: What the check saw, for a `violated` result.
    Address:
      type: string
      description: >
        Where a reason or finding rests, written as an address:
        `license:<id>/terms.<key>` for a

        term, `talent:<id>` for a talent's standing boundary.
      example: license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.channels
    Reason:
      type: object
      required:
        - code
        - stage
        - sentence
      properties:
        code:
          $ref: '#/components/schemas/ReasonCode'
          description: A stable reason code. Branch on it.
        stage:
          type: string
          enum:
            - check
            - generation
            - session
          description: 'Where it was decided: `check`, `generation` or `session`.'
        talent:
          type: string
          pattern: ^tal_[0-9a-hjkmnp-tv-z]{26}$
          description: The talent the reason concerns.
        term:
          $ref: '#/components/schemas/Address'
          description: >-
            The license term or standing rule the reason rests on, as an
            address.
        sentence:
          type: string
          description: >-
            The reason in the license's own words. Show it to your user as
            written.
    Obligation:
      type: object
      description: >-
        Something you must do to proceed. Each type uses only the fields listed
        for it.
      required:
        - type
      properties:
        type:
          $ref: '#/components/schemas/ObligationType'
          description: >
            The kind of obligation. Treat a type you do not know as unmet: do
            not generate or

            deliver.
        required:
          type: string
          enum:
            - all
            - sampled
          description: >-
            `generation_check`: submit every output, or the sampled share in
            `sample_rate`.
        sample_rate:
          type: number
          minimum: 0
          maximum: 1
          description: >
            `generation_check` with `required: sampled`: the share of outputs to
            submit, from 0 to

            1, chosen at random.
        reviewer:
          type: string
          enum:
            - talent
            - representative
            - reflections
          description: '`hold_until_release`: who releases each output.'
        instructions:
          type: array
          items:
            type: string
          description: '`generation_instructions`: include these in what the model receives.'
        level:
          type: string
          enum:
            - licensed
            - brand
            - scope
          description: >-
            `disclosure`: `licensed` says the person's likeness is licensed;
            `brand` adds who licensed it; `scope` adds the use.
        text:
          type: string
          description: '`disclosure` and `attribution`: the words to show.'
        placement:
          type: string
          enum:
            - visible
            - metadata
            - both
          description: '`disclosure`: where the label goes.'
        material:
          type: string
          enum:
            - references
            - voice
            - outputs
          description: '`delete_material` and `no_training`: what the obligation covers.'
        within:
          allOf:
            - $ref: '#/components/schemas/Duration'
          description: >-
            The deadline. `delete_material`: counted from the decision.
            `usage_report`: from the generation's decision or the session's end.
        units:
          type: string
          enum:
            - outputs
            - seconds
            - characters
            - placements
            - impressions
          description: '`usage_report`: the unit to report.'
        term:
          $ref: '#/components/schemas/Address'
          description: The address of the license term the obligation comes from.
    Escalation:
      type: object
      required:
        - id
        - reason
        - reviewer
        - status
        - expires_at
      properties:
        id:
          type: string
          pattern: ^esc_[0-9a-hjkmnp-tv-z]{26}$
          description: The escalation's ID, `esc_` followed by 26 characters.
        reason:
          type: string
          enum:
            - judgment
            - unverifiable
            - evaluation_unavailable
            - release_review
          description: >
            `judgment`: a rule needs a person to read it. `unverifiable`: a
            protected attribute

            could not be confirmed. `evaluation_unavailable`: the check could
            not finish.

            `release_review`: every output under this license is released by a
            person.
        reviewer:
          type: string
          enum:
            - talent
            - representative
            - reflections
          description: >
            `talent`: the talent, or a representative whose mandate has
            `review_outputs`.

            `representative`: only the talent's representatives. `reflections`:
            Reflections trust

            and safety, under a platform license.
        status:
          type: string
          enum:
            - open
            - allowed
            - denied
            - expired
            - cancelled
          description: >
            `open` until it closes: `allowed` or `denied` by the reviewer,
            `expired` at

            `expires_at`, or `cancelled` when you cancel the check, withdraw the
            output, or another

            talent's escalation decides the check.
        expires_at:
          type: string
          format: date-time
          description: >
            When an unanswered escalation becomes `deny`: 7 days after it opens,
            or the license's

            shorter `escalation_window`.
        resolved_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When the escalation was decided, expired or cancelled. Null while
            `open`.
        note:
          type:
            - string
            - 'null'
          maxLength: 500
          description: The reviewer's note, if they wrote one.
    C2paAssertion:
      type: object
      description: Add this assertion to the output's C2PA manifest, under `label`.
      required:
        - label
        - data
      properties:
        label:
          type: string
          const: ai.reflections.license
          description: Always `ai.reflections.license`. Use it as the assertion's label.
        data:
          type: object
          description: >-
            The assertion's data, copied unchanged: the receipt JWS and its
            public page.
          required:
            - receipt
            - verify_url
          properties:
            receipt:
              type: string
              description: The receipt JWS.
            verify_url:
              type: string
              format: uri
              description: >-
                The receipt's public page,
                `https://app.reflections.ai/r/{receipt_id}`.
    Problem:
      type: object
      description: An RFC 9457 problem detail. Every error has this shape.
      required:
        - type
        - title
        - status
        - code
        - request_id
      properties:
        type:
          type: string
          format: uri
          description: A URL for this error, under `https://docs.reflections.ai/errors/`.
        title:
          type: string
          description: A short summary of the error.
        status:
          type: integer
          description: The HTTP status.
        detail:
          type: string
          description: What happened in this request.
        code:
          $ref: '#/components/schemas/ErrorCode'
          description: The stable error code. Branch on it, then on `status`.
        param:
          type: string
          description: The field at fault, as a path such as `use.territories[1]`.
        request_id:
          type: string
          description: >
            `req_…`, the same value as the `Request-Id` header. Include it when
            you contact support.
        doc_url:
          type: string
          format: uri
          description: A link to the documentation for this error.
    ReasonCode:
      type: string
      description: >-
        Why a use was denied or escalated, or a session terminated. See the
        reason code catalog.
      enum:
        - no_license
        - license_pending_acceptance
        - license_revoked
        - license_suspended
        - window_not_started
        - window_ended
        - terms_unreadable
        - account_not_licensee
        - material_unavailable
        - adjustment_not_licensed
        - facet_not_licensed
        - kind_not_licensed
        - modality_not_licensed
        - purpose_not_licensed
        - channel_not_licensed
        - territory_not_licensed
        - commercial_use_not_licensed
        - platform_not_licensed
        - delivery_limit_reached
        - monthly_limit_reached
        - talent_prohibits
        - prohibited_appearance_change
        - prohibited_endorsement
        - prohibited_custom_term
        - identity_not_preserved
        - prohibited_speech
        - prohibited_motion
        - narration_mismatch
        - voice_rule
        - unsupported_rule
        - attribute_unverifiable
        - output_unverifiable
        - ambiguous_talent
        - review_required
        - unverifiable_request
        - evaluation_unavailable
        - authority_changed
        - provenance_failed
        - hold_expired
        - review_declined
        - review_expired
        - session_not_permitted
        - renewal_missed
        - sample_missed
    ObligationType:
      type: string
      description: >
        `generation_check`: submit outputs before delivery.
        `hold_until_release`: deliver nothing

        until the reviewer releases it. `draft_watermark`: mark drafts shown
        while held.

        `generation_instructions`: pass the instructions to the model.
        `disclosure`,

        `attribution`: label the output as stated. `c2pa_manifest`: embed the
        `c2pa` assertion.

        `no_training`: never train on the material. `delete_material`: delete it
        within `within`.

        `usage_report`: report usage within `within`.
      enum:
        - generation_check
        - hold_until_release
        - draft_watermark
        - generation_instructions
        - disclosure
        - attribution
        - c2pa_manifest
        - no_training
        - delete_material
        - usage_report
    Duration:
      type: string
      description: An ISO 8601 duration, such as `PT60S` or `P30D`.
      example: P30D
    ErrorCode:
      type: string
      description: A stable error code. See the error code catalog.
      enum:
        - invalid_request
        - parameter_missing
        - parameter_invalid
        - unsupported_modality
        - unsupported_media_type
        - media_unreadable
        - version_unsupported
        - authorization_code_invalid
        - authentication_required
        - invalid_api_key
        - token_invalid
        - insufficient_scope
        - account_not_connected
        - mandate_required
        - livemode_mismatch
        - live_not_activated
        - platform_not_permitted
        - resource_not_found
        - idempotency_key_in_use
        - generation_already_submitted
        - authorization_consumed
        - check_not_allowed
        - check_expired
        - escalation_closed
        - license_draft_closed
        - invalid_state_transition
        - session_not_active
        - payload_too_large
        - idempotency_key_reused
        - artifact_digest_mismatch
        - rate_limited
        - internal_error
        - service_unavailable
        - evaluation_timeout
  headers:
    RequestId:
      description: Identifies this request. Include it when you contact support.
      schema:
        type: string
        example: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    RetryAfter:
      description: Seconds to wait before retrying.
      schema:
        type: integer
  examples:
    GenerationHeld:
      summary: Held for the talent's release
      value:
        id: gen_6s9t0wxyhk5zba2q8v1m3n7p4r
        object: generation
        livemode: true
        check: chk_3m7p4r6s9t0wxyhk5zba2q8v1n
        session: null
        candidate_index: 0
        status: held
        decision: escalate
        artifact:
          file: file_2c4e6g8j0k2m4n6p8q0r2s4t6v
          sha256: 9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a
          media_type: image/png
          duration_ms: null
        execution:
          provider: example-image-provider
          model: image-model-3
          job_id: job_88213
        findings:
          - term: license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.requiredAttributes
            attribute: identity.samePerson
            result: preserved
          - term: license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.adjustments
            attribute: appearance.wardrobe
            result: preserved
          - term: license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.neverExtras
            rule: Do not show alcohol or tobacco.
            result: preserved
        unchecked_terms: []
        reasons: []
        obligations:
          - type: hold_until_release
            reviewer: talent
          - type: draft_watermark
        escalation:
          id: esc_hk5zba2q8v1m3n7p4r6s9t0wxy
          reason: release_review
          reviewer: talent
          status: open
          expires_at: '2026-10-24T18:00:12Z'
          resolved_at: null
          note: null
        assurance: observed
        receipt: null
        c2pa: null
        watermark: null
        metadata: {}
        created_at: '2026-10-17T18:00:12Z'
        decided_at: null
    GenerationAllowed:
      summary: Allowed, with a receipt to embed
      value:
        id: gen_2q8v1m3n7p4r6s9t0wxyhk5zba
        object: generation
        livemode: true
        check: chk_m3n7p4r6s9t0wxyhk5zba2q8v1
        session: null
        candidate_index: 0
        status: allowed
        decision: allow
        artifact:
          file: file_8q0r2s4t6v8w0x2y4z6a8b0c2d
          sha256: 3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d
          media_type: audio/wav
          duration_ms: 3400
        execution:
          provider: example-voice-provider
          model: tts-2
          job_id: job_90417
        findings:
          - term: license:lic_ba2q8v1m3n7p4r6s9t0wxyhk5z/terms.requiredAttributes
            attribute: identity.samePerson
            result: preserved
          - term: license:lic_ba2q8v1m3n7p4r6s9t0wxyhk5z/terms.voiceLineGrant.never
            rule: Do not discuss politics or religion.
            result: preserved
        unchecked_terms: []
        reasons: []
        obligations:
          - type: disclosure
            level: licensed
            placement: metadata
            text: AI voice of Maya Okafor, licensed.
          - type: c2pa_manifest
          - type: usage_report
            units: seconds
            within: P1D
        escalation: null
        assurance: observed
        receipt: rcpt_hk5zba2q8v1m3n7p4r6s9t0wxy
        c2pa:
          label: ai.reflections.license
          data:
            receipt: >-
              eyJhbGciOiJFUzI1NiIsImtpZCI6InJmbC0yMDI2LTEwLWRvY3MzIiwidHlwIjoidGxwLXJlY2VpcHQrand0In0.eyJpYXQiOjE3OTIyNjAzNjMsImlzcyI6Imh0dHBzOi8vYXBwLnJlZmxlY3Rpb25zLmFpIiwianRpIjoicmNwdF9oazV6YmEycTh2MW0zbjdwNHI2czl0MHd4eSIsInN1YiI6Imdlbl8ycTh2MW0zbjdwNHI2czl0MHd4eWhrNXpiYSIsInRscCI6eyJhcnRpZmFjdF9zaGEyNTYiOiIzYjVkN2Y5YTFjM2U1YjdkOWYxYTNjNWU3YjlkMWYzYTVjN2U5YjFkM2Y1YTdjOWUxYjNkNWY3YTljMWUzYjVkIiwiYXNzdXJhbmNlIjoib2JzZXJ2ZWQiLCJkZWNpc2lvbiI6ImFsbG93Iiwia2luZCI6ImdlbmVyYXRpb24iLCJsaWNlbnNlZSI6ImFjY3RfN3A0cjZzOXQwd3h5aGs1emJhMnE4djFtM24iLCJsaWNlbnNlcyI6W3sibGljZW5zZSI6ImxpY19iYTJxOHYxbTNuN3A0cjZzOXQwd3h5aGs1eiIsInJldmlzaW9uIjoibHJ2XzdwNHI2czl0MHd4eWhrNXpiYTJxOHYxbTNuIiwidGFsZW50IjoidGFsXzl0MHd4eWhrNXpiYTJxOHYxbTNuN3A0cjZzIiwidGVybXNfZGlnZXN0Ijoic2hhMjU2OjhlMGEyYzRlNmI4ZDBmMmE0YzZlOGIwZDJmNGE2YzhlMGIyZDRmNmE4YzBlMmI0ZDZmOGEwYzJlNGI2ZDhmMGEifV0sIm9ibGlnYXRpb25zIjpbeyJsZXZlbCI6ImxpY2Vuc2VkIiwicGxhY2VtZW50IjoibWV0YWRhdGEiLCJ0ZXh0IjoiQUkgdm9pY2Ugb2YgTWF5YSBPa2Fmb3IsIGxpY2Vuc2VkLiIsInR5cGUiOiJkaXNjbG9zdXJlIn0seyJ0eXBlIjoiYzJwYV9tYW5pZmVzdCJ9LHsidHlwZSI6InVzYWdlX3JlcG9ydCIsInVuaXRzIjoic2Vjb25kcyIsIndpdGhpbiI6IlAxRCJ9XSwicGxhdGZvcm0iOiJhY2N0XzdwNHI2czl0MHd4eWhrNXpiYTJxOHYxbTNuIiwicmVxdWVzdF9kaWdlc3QiOiJzaGEyNTY6ZDRmNmI4YTBjMmU0ZDZmOGIwYTJjNGU2ZDhmMGIyYTRjNmU4ZDBmMmI0YTZjOGUwZDJmNGI2YThjMGUyZDRmNiIsInRhbGVudCI6WyJ0YWxfOXQwd3h5aGs1emJhMnE4djFtM243cDRyNnMiXSwidXNlIjp7ImNoYW5uZWxzIjpbImF1ZGlvIiwid2ViIl0sImNvbW1lcmNpYWwiOnRydWUsImtpbmQiOiJpbXBlcnNvbmF0aW9uIiwibW9kYWxpdHkiOiJzcGVlY2giLCJwdXJwb3NlIjoiYnJhbmRlZF9jb250ZW50IiwidGVycml0b3JpZXMiOlsiVVMiXX0sInZlciI6IjEuMCJ9fQ.K7AXwiCTQv-GS_xfIdystUTVdNl6u7p0FQ9XSkoh5amUnEehLLLpriZk7OA38gBo5UZHItmJm0rHf_8Eebj2rg
            verify_url: https://app.reflections.ai/r/rcpt_hk5zba2q8v1m3n7p4r6s9t0wxy
        watermark: null
        metadata: {}
        created_at: '2026-10-17T18:06:02Z'
        decided_at: '2026-10-17T18:06:03Z'
    GenerationDenied:
      summary: An output that broke one of the talent's rules
      value:
        id: gen_t6v8w0x2y4z6a8b0c2d4e6f8g0
        object: generation
        livemode: true
        check: chk_3m7p4r6s9t0wxyhk5zba2q8v1n
        session: null
        candidate_index: 1
        status: denied
        decision: deny
        artifact:
          file: file_3t5v7x9z1b3d5f7h9k1m3p5r7s
          sha256: 4c6e8a0b2d4f6a8c0e2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c6e8b0d2f4a6c
          media_type: image/png
          duration_ms: null
        execution:
          provider: example-image-provider
          model: image-model-3
          job_id: job_88214
        findings:
          - term: license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.requiredAttributes
            attribute: identity.samePerson
            result: preserved
          - term: license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.neverExtras
            rule: Do not show alcohol or tobacco.
            result: violated
            detail: A wine glass on the café table.
        unchecked_terms: []
        reasons:
          - code: prohibited_custom_term
            stage: generation
            talent: tal_9t0wxyhk5zba2q8v1m3n7p4r6s
            term: license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.neverExtras
            sentence: Do not show alcohol or tobacco.
        obligations: []
        escalation: null
        assurance: observed
        receipt: rcpt_w0x2y4z6a8b0c2d4e6f8g0h2j4
        c2pa: null
        watermark: null
        metadata: {}
        created_at: '2026-10-17T18:08:40Z'
        decided_at: '2026-10-17T18:08:41Z'
  responses:
    BadRequest:
      description: The request was malformed or a parameter was invalid.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: https://docs.reflections.ai/errors/parameter_invalid
            title: A parameter is invalid
            status: 400
            code: parameter_invalid
            param: use.territories[1]
            detail: '"UK" is not an ISO 3166-1 alpha-2 code. Use "GB".'
            request_id: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    Unauthorized:
      description: The key is missing, unknown or revoked.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: https://docs.reflections.ai/errors/invalid_api_key
            title: The API key is not valid
            status: 401
            code: invalid_api_key
            request_id: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    Forbidden:
      description: >-
        The key may not do this, the licensee is not connected, or live mode is
        not activated for this operation (`live_not_activated`).
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: https://docs.reflections.ai/errors/account_not_connected
            title: The licensee has not connected your platform
            status: 403
            code: account_not_connected
            detail: >-
              acct_2q8v1m3n7p4r6s9t0wxyhk5zba has no active connection with your
              account.
            request_id: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    NotFound:
      description: No such object for this account.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: https://docs.reflections.ai/errors/resource_not_found
            title: No such object
            status: 404
            code: resource_not_found
            request_id: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    Conflict:
      description: >-
        The request conflicts with the object's state or with a request still
        running.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: https://docs.reflections.ai/errors/idempotency_key_in_use
            title: A request with this key is still running
            status: 409
            code: idempotency_key_in_use
            detail: Retry with the same key after a short wait.
            request_id: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    PayloadTooLarge:
      description: >-
        The request exceeds its byte limit. Sandbox inline media is at most 7
        MiB decoded and the generation JSON body at most 10 MiB. Multipart
        uploads are planned.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    Unprocessable:
      description: The request is well formed but cannot be applied.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: https://docs.reflections.ai/errors/idempotency_key_reused
            title: This key was used for a different request
            status: 422
            code: idempotency_key_reused
            request_id: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    RateLimited:
      description: Too many requests.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          example:
            type: https://docs.reflections.ai/errors/rate_limited
            title: Too many requests
            status: 429
            code: rate_limited
            request_id: req_8f2k4m6p8r0t2v4x6z8b0d2f4h
    ServerError:
      description: Something failed on our side. Retry with the same idempotency key.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    Unavailable:
      description: >
        Reflections is temporarily unavailable. Do not generate a named talent
        without a valid

        authorization. Retry with the same idempotency key.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    SecretKey:
      type: http
      scheme: bearer
      description: >
        Your secret key, `rk_test_…` or `rk_live_…`, sent as `Authorization:
        Bearer <key>`. Keep it

        on your server. Restricted keys carry only the scopes you give them.

````

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