The initial live image implementation below is deployed, subject to signing activation and
production acceptance. The rest of this guide describes the broader planned contract.
The sandbox supports fixture checks and generations; test decisions do not authorize real use.
Start with the runnable quickstart and sandbox support matrix.
Initial live image implementation
This path is for a licensee using its own newly signed license for commercial advertising or branded content. It requires explicitexternalCreation: "images.v1" and
externalCreationPostRevocation: "retain" terms. Existing signatures grant neither by omission.
Protected activation of the live signer must follow its public key’s 30-day publication interval.
Deployment, signing activation, supplier processing and independent live acceptance remain
separate qualification requirements.
Retain the issued and accepted license document for its signed scope. Live license reads return
the current revision and terms digest with a partial scope; omitted channels or territories grant
nothing. The initial live API does not export the full signed revision or the talent’s original
signature. Match the license revision and digest to Reflections’ signed decision receipts; this
does not independently verify the talent’s original signature.
- Check the effective request. Send one explicit owned
license, text inputs totaling at most 64 KiB of UTF-8, imagedepiction,commercial: true, purposeadvertisingorbranded_content, and the intended channels and territories. Every value must match the signed scope; only signedWWgrants worldwide use. Setexecution.provider,execution.model,execution.candidates: 1andon_escalate: "deny". - Wait for the check. Persist the body and its
Idempotency-Key. While evaluation is pending, retry409 idempotency_key_in_usewith the same body and key afterRetry-After. Continue only afterdecision: "allow", and meet every obligation. A denial does not permit generation. - Generate one image in your tool. Use the checked request and declared provider and model
and leave enough time to finish and submit before
authorization.expires_at. Starting the provider job before expiry is not sufficient.job_idis optional and may be supplied after the provider starts. Reflections does not render the image or fetch provider output. - Submit the exact output. Send one inline still PNG of at most 7 MiB (7,340,032 decoded
bytes), its lowercase SHA-256,
candidate_index: 0, and matching provider/model. The JSON body may be at most 10 MiB. Use a new persisted idempotency key for this operation. The same caller key must hold bothchecks:writeandgenerations:write. Send the allowedcheckID; Reflections reads its stored authorization token, so no separate token field is submitted. The first successful submission must arrive beforeauthorization.expires_at; otherwise it fails with409 check_expired. - Poll and keep the output private. A successful POST returns
202with the accepted generation. Its retries always return that original response. GET the generation forchecking,held,released,deniedorexpired. An image that passes evaluation and retains authority moves to talent review; only the talent’s actual release permitsdecision: "allow". Denied and expired images stay private. - Verify the receipt before delivery. Follow the signed obligations for provenance and disclosure. Receipt retrieval and JSON verification by live receipt ID or JWS are public; lookup by artifact digest requires the owning account’s live key. Public responses exclude private request metadata.
404; signed receipts are kept separately for seven years.
Reflections-managed retention does not establish upstream provider deletion. See
Privacy.
Broader image and video contract
The remaining sections include planned forms beyond the initial live implementation above. An image or video platform calls Reflections at two points in its pipeline: a check after it has built the request the model will receive, and a generation for every output before anyone sees it. This guide places both calls, and the obligations between them, in a production pipeline.Decide whose license applies
Every check names one licensee and one platform.
A brand connects your platform through OAuth, and you receive
connection.created. From then on,
checks you send with its account ID use its licenses. See
Brands and agencies for the brand’s side and
Authentication for the OAuth flow.
Build the effective request
The check binds the request the model actually receives, so send it after your own prompt handling, not before.
Upload references with
purpose: "reference" and masks with purpose: "mask". If your interface
has a cast picker, pass the chosen talent in talent and skip resolution. When a talent has
several facets, name one with facet. Binding the request covers
edits, image-to-video and multi-step pipelines.
When the license includes material_access, you can send the talent’s own reference stills.
GET /v1/facets/{facet_id}/material returns
download URLs that expire after 5 minutes, each with its sha256. Send exactly those bytes, and
follow the obligations that come with them, such as delete_material and no_training.
Check before you generate
Setexecution.candidates to the number of outputs the model returns. One check covers them all,
and its authorization allows that many generations.
Pass
on_escalate: "deny" from interactive surfaces where a user is waiting. Batch and studio
workflows can leave the default, hold, and let a reviewer decide. See
Handling escalations.
Meet the obligations
Obligations are typed. Handle each one at the stage where it applies:
If a check returns an obligation type your code does not handle, treat it as unmet and do not
generate. Obligations describes each one.
Generate
Send the model the request you checked, plus the instructions. Send your providerauthorization.token so it can verify the request offline, and start the job before
authorization.expires_at. A provider that verifies tokens rejects one issued for a different
model or already used up. See Model providers.
Submit every output
Each output becomes a generation that names itscheck and candidate_index, with the SHA-256
of its bytes. Today, send the bytes inline as artifact.data (base64), at most 7 MiB decoded in a
10 MiB JSON body, as the quickstart does. The sandbox returns the decision in the
response; the initial live implementation returns 202 and you
poll. Planned: upload larger files with POST /v1/files,
multipart up to 100 MB or a JSON upload URL up to 5 GB. Neither mode serves file uploads or fetches
URLs yet.
- Images return a decision in the sandbox response.
- Video returns
status: "checking". The decision arrives asgeneration.allowedorgeneration.denied. The p95 target is half the video’s duration plus 5 seconds. - Held outputs return
escalatewithstatus: "held"and wait forgeneration.released,generation.deniedorgeneration.expired.
findings for what was checked on the bytes and unchecked_terms for talent-written rules
that could not be read: those outputs are delivered and the rule is recorded as unchecked.
Protected attributes, such as identity.samePerson, never pass unchecked. See
Submitting outputs and
Generation checks.
An output is checked only for the talent its check covered, so send every reference image your user
uploads as a check input: that is how a photo of a protected talent is matched.
Deliver
Embedc2pa in the output’s C2PA manifest with the standard c2pa.actions entry, show the
disclosure and any attribution, then deliver. Your platform signs the manifest; the receipt inside
is signed by Reflections. See Embedding provenance.
When Reflections cannot be reached
Fail closed for named talent. On503 service_unavailable, generate nothing for a named talent
unless you already hold an unexpired authorization, and then only within its max_generations.
Retry with the same Idempotency-Key. A request that names no talent, matches nothing in your
name index and carries no reference may still run. See Failure modes.
What can go wrong
Related
Image quickstart
Candidates, instructions, a held output and a receipt, in test mode.
Video integration design
Asynchronous checks and large uploads.
Handling revocations
What to stop, purge and acknowledge when consent narrows.
Production checklist
What a live integration must do.