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

# Generation checks

> What Reflections checks on the output bytes, which talent it checks, and when the decision arrives.

<Note>
  Production protocol reference. The sandbox binds submitted bytes to their SHA-256, then uses
  deterministic fixture rules and test markers. It does not inspect media for identity or
  content compliance. File uploads and webhook delivery remain planned.
  Start with the [runnable quickstart](/quickstart) and [sandbox support matrix](/sandbox).
</Note>

A **generation** is an output submitted to [`POST /v1/generations`](/api-reference/generations/create-a-generation)
before anyone sees it. It names the `check` the output was made under, and Reflections checks that
license's rules on the actual bytes. Deliver nothing until the generation's decision is `allow`.

## Binding the output to its check

A generation names its `check` and the `candidate_index` of the output among the check's
candidates, sends the bytes as an `artifact`, and
declares their `sha256`. The digest goes into the receipt. The talent's rules are about content,
so Reflections checks the bytes themselves.

* If the bytes do not match the declared `sha256`, the call fails with
  `422 artifact_digest_mismatch`.
* A second generation for the same check and candidate fails with
  `409 generation_already_submitted`, so unrelated bytes cannot ride a valid check.
* A check that is not `allow` refuses generations with `409 check_not_allowed`.

Send `execution.job_id`, the provider's ID for the job, so the output can be traced to the run that
made it.

The sandbox accepts base64 `data` up to 7 MiB decoded bytes in a 10 MiB JSON body, or an attested
SHA-256 digest. File IDs, URL fetching and the protocol's 10 MB inline target remain planned.

## What is checked on the bytes

| Check | From the license | Reason when it fails |
| - | - | - |
| The person is the same person | `required_attributes`, always including `identity.samePerson` | `identity_not_preserved` |
| Only licensed changes were made | `adjustments`, `prohibited_changes` | `prohibited_appearance_change`, `prohibited_endorsement` |
| The talent's own rules hold | `rules.never`, `rules.always`, `rules.brief`, voice rules | `prohibited_custom_term`, `voice_rule` |
| Words and motion are allowed | The spoken words, transcribed by Reflections, and motion in video | `prohibited_speech`, `narration_mismatch`, `prohibited_motion` |
| The delivery limit is not reached | `final_deliverables` | `delivery_limit_reached` |
| The license is still in force | Status and window | `license_revoked`, `license_suspended`, `window_ended`, `authority_changed` |

Reflections transcribes speech in every output. Send `transcript` if you have it; it does not
replace the transcription.

## Findings

Each rule checked becomes a finding:

| Field | Meaning |
| - | - |
| `term` | The term's address, such as `license:lic_…/terms.neverExtras` |
| `attribute` | The protected attribute, such as `identity.samePerson` |
| `rule` | The talent's rule, as written |
| `result` | `preserved`, `violated` or `unchecked` |

<Warning>
  A rule the talent wrote that could not be read is `unchecked`: the output is delivered and the
  term is listed in `unchecked_terms`, so the record shows it was not checked. A protected attribute,
  such as `identity.samePerson`, is never delivered unchecked: an output whose protected attributes
  cannot be confirmed is denied.
</Warning>

## When the decision arrives

Images, speech up to 60 seconds and text return their decision in the response. Video and longer
audio return `status: "checking"`, and the decision arrives as
[`generation.allowed`](/api-reference/webhooks/generation-allowed) or
[`generation.denied`](/api-reference/webhooks/generation-denied). Under a license with
`release_policy: "per_output_review"`, a passing output returns `escalate` and stays `held` until a
reviewer releases it. Video and longer audio under such a license return `held` at once: the
reviewer is asked only after the output passes its checks, and a failure arrives as
`generation.denied`.

```mermaid theme={null}
stateDiagram-v2
    [*] --> checking: video or long audio
    [*] --> allowed
    [*] --> denied
    [*] --> held: passes, needs release
    checking --> allowed
    checking --> denied
    held --> released: reviewer releases
    held --> denied: reviewer declines
    held --> expired: not reviewed in time
    held --> withdrawn: you withdraw it
    allowed --> withdrawn: no longer in use
    released --> withdrawn: no longer in use
```

Deliver only on `allowed` and `released`. Withdraw a held output you no longer need with
[`POST /v1/generations/{generation_id}/withdraw`](/api-reference/generations/withdraw-a-generation);
its delivery returns to the license's delivery limit.

## Which talent are checked

An output is checked only for the talent its check covered. Reflections does not match it against
other talent, and does not look for talent nobody named. A check whose inputs invoke no
protected talent returns `allow` with `talent: []` and no obligations, so its outputs need no
generation.

A talent or representative who finds an output of the talent's likeness can
[verify it](/build/verifying-content). A verified receipt names the license the output was made
under.

## Example: a held image for Ridgeline

Maya Okafor releases each output under Ridgeline's license. A passing image comes back held:

```json theme={null}
{
  "id": "gen_6s9t0wxyhk5zba2q8v1m3n7p4r",
  "object": "generation",
  "check": "chk_3m7p4r6s9t0wxyhk5zba2q8v1n",
  "candidate_index": 0,
  "status": "held",
  "decision": "escalate",
  "artifact": { "file": "file_2c4e6g8j0k2m4n6p8q0r2s4t6v", "sha256": "9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a", "media_type": "image/png" },
  "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": [],
  "escalation": { "id": "esc_hk5zba2q8v1m3n7p4r6s9t0wxy", "reason": "release_review", "reviewer": "talent", "status": "open", "expires_at": "2026-10-24T18:00:12Z" },
  "assurance": "observed",
  "receipt": null
}
```

Every rule held, so the output waits only for Maya Okafor. When she releases it, you receive
`generation.released` with `status: "released"`, `decision: "allow"`, the receipt and the `c2pa`
assertion to embed.

## Related

<Columns cols={2}>
  <Card title="Submitting outputs" icon="upload" href="/build/submitting-outputs">
    Uploads, candidates, digests and findings.
  </Card>

  <Card title="Escalation" icon="user-clock" href="/concepts/escalation">
    Release review and expiry.
  </Card>

  <Card title="What we enforce" icon="shield-check" href="/concepts/what-we-enforce">
    Observed and attested assurance.
  </Card>

  <Card title="Provenance" icon="receipt" href="/concepts/provenance">
    The receipt and the C2PA assertion.
  </Card>
</Columns>


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