# 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_CHECK_IDEMPOTENCY_KEY:?Set REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY before running this example}"
curl --fail-with-body --max-time 30 -X POST 'https://app.reflections.ai/v1/checks' \
-H "Authorization: Bearer $REFLECTIONS_KEY" \
-H "Reflections-Version: 2026-10-15" \
-H "Idempotency-Key: $REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
--data-raw '{
"inputs": [
{
"role": "prompt",
"text": "Maya Okafor running a mountain trail at sunrise"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social"
],
"territories": [
"US"
]
},
"execution": {
"provider": "sandbox-fixture",
"model": "one-pixel-png",
"candidates": 1
}
}'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_CHECK_IDEMPOTENCY_KEY;
if (!idempotencyKey) throw new Error("Set REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY before running this example");
const response = await fetch("https://app.reflections.ai/v1/checks", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Reflections-Version": "2026-10-15",
"Idempotency-Key": idempotencyKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"inputs": [
{
"role": "prompt",
"text": "Maya Okafor running a mountain trail at sunrise"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social"
],
"territories": [
"US"
]
},
"execution": {
"provider": "sandbox-fixture",
"model": "one-pixel-png",
"candidates": 1
}
}),
signal: AbortSignal.timeout(30_000),
});
const responseBody = await response.text();
if (!response.ok) {
console.error(`HTTP ${response.status}: ${responseBody}`);
exit(1);
}
console.log(responseBody);
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_CHECK_IDEMPOTENCY_KEY"]
if not idempotencyKey:
raise ValueError("Set REFLECTIONS_CREATE_CHECK_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({
"inputs": [{"role": "prompt", "text": "Maya Okafor running a mountain trail at sunrise"}],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": True,
"channels": ["social"],
"territories": ["US"],
},
"execution": {"provider": "sandbox-fixture", "model": "one-pixel-png", "candidates": 1},
}).encode("utf-8")
request = Request("https://app.reflections.ai/v1/checks",
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
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_CHECK_IDEMPOTENCY_KEY")
if idempotencyKey == "" {
panic("Set REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY before running this example")
}
body := strings.NewReader(`{
"inputs": [
{
"role": "prompt",
"text": "Maya Okafor running a mountain trail at sunrise"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social"
],
"territories": [
"US"
]
},
"execution": {
"provider": "sandbox-fixture",
"model": "one-pixel-png",
"candidates": 1
}
}`)
request, err := http.NewRequest("POST", "https://app.reflections.ai/v1/checks", 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))
}
{
"id": "chk_3m7p4r6s9t0wxyhk5zba2q8v1n",
"object": "check",
"livemode": true,
"status": "allowed",
"decision": "allow",
"talent": [
{
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"name": "Maya Okafor",
"matched_by": "name",
"confidence": "high",
"decision": "allow",
"facets": [
"fct_5zba2q8v1m3n7p4r6s9t0wxyhk"
],
"license": "lic_k5zba2q8v1m3n7p4r6s9t0wxyh",
"license_revision": "lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
"terms_digest": "sha256:39f18c8bef02b5226b9feaa92e526ed30b81b91650d8a10b503281b169f44431"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
]
},
"reasons": [],
"obligations": [
{
"type": "generation_check",
"required": "all"
},
{
"type": "hold_until_release",
"reviewer": "talent"
},
{
"type": "draft_watermark"
},
{
"type": "generation_instructions",
"instructions": [
"Keep Maya Okafor the same person: face, skin tone and build unchanged.",
"Do not show alcohol or tobacco.",
"Do not imply she endorses any product other than the one shown."
],
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.neverExtras"
},
{
"type": "disclosure",
"level": "brand",
"placement": "both",
"text": "Made with AI. Maya Okafor's likeness used under license by Ridgeline."
},
{
"type": "c2pa_manifest"
},
{
"type": "no_training",
"material": "outputs"
},
{
"type": "usage_report",
"units": "placements",
"within": "P30D"
}
],
"authorization": {
"token": "eyJhbGciOiJFUzI1NiIsImtpZCI6InJmbC0yMDI2LTEwLWRvY3MzIiwidHlwIjoidGxwLWF1dGgrand0In0.eyJhdWQiOiJhY2N0XzdwNHI2czl0MHd4eWhrNXpiYTJxOHYxbTNuIiwiZXhwIjoxNzkyMjYwOTAwLCJpYXQiOjE3OTIyNjAwMDAsImlzcyI6Imh0dHBzOi8vYXBwLnJlZmxlY3Rpb25zLmFpIiwianRpIjoiY2hrXzNtN3A0cjZzOXQwd3h5aGs1emJhMnE4djFuIiwic3ViIjoiYWNjdF8ycTh2MW0zbjdwNHI2czl0MHd4eWhrNXpiYSIsInRscCI6eyJkZWNpc2lvbiI6ImFsbG93IiwiZXUiOiIzZjljMWE3ZTViMmQ4ZjQwNjFjM2U5YTdiNWQyZjgwMTZlNGM5YTNiN2QxZjVlMmM4YTZiNGQwZjllM2M3YTE1IiwiZXhlY3V0aW9uIjp7Im1vZGVsIjoiaW1hZ2UtbW9kZWwtMyIsInByb3ZpZGVyIjoiZXhhbXBsZS1pbWFnZS1wcm92aWRlciJ9LCJmYWNldHMiOlsiZmN0XzV6YmEycTh2MW0zbjdwNHI2czl0MHd4eWhrIl0sImxpY2Vuc2VzIjpbeyJsaWNlbnNlIjoibGljX2s1emJhMnE4djFtM243cDRyNnM5dDB3eHloIiwicmV2aXNpb24iOiJscnZfcDRyNnM5dDB3eHloazV6YmEycTh2MW0zbjciLCJ0YWxlbnQiOiJ0YWxfOXQwd3h5aGs1emJhMnE4djFtM243cDRyNnMiLCJ0ZXJtc19kaWdlc3QiOiJzaGEyNTY6MzlmMThjOGJlZjAyYjUyMjZiOWZlYWE5MmU1MjZlZDMwYjgxYjkxNjUwZDhhMTBiNTAzMjgxYjE2OWY0NDQzMSJ9XSwibWF4X2dlbmVyYXRpb25zIjo0LCJvYmxpZ2F0aW9ucyI6WyJnZW5lcmF0aW9uX2NoZWNrIiwiaG9sZF91bnRpbF9yZWxlYXNlIiwiZHJhZnRfd2F0ZXJtYXJrIiwiZ2VuZXJhdGlvbl9pbnN0cnVjdGlvbnMiLCJkaXNjbG9zdXJlIiwiYzJwYV9tYW5pZmVzdCIsIm5vX3RyYWluaW5nIiwidXNhZ2VfcmVwb3J0Il0sInJlcXVlc3RfZGlnZXN0Ijoic2hhMjU2OmJmOTQ4MTc3NjZkNTZkOTIyMTFkMTJmNWZmNTFhM2RjMWE2ZDVjYjRiZTI4Nzc0MTdiMDgyNTFmZTM4YzM4NmEiLCJ0YWxlbnQiOlsidGFsXzl0MHd4eWhrNXpiYTJxOHYxbTNuN3A0cjZzIl0sInVzZSI6eyJjaGFubmVscyI6WyJzb2NpYWwiLCJ3ZWIiXSwiY29tbWVyY2lhbCI6dHJ1ZSwia2luZCI6ImRlcGljdGlvbiIsIm1vZGFsaXR5IjoiaW1hZ2UiLCJwdXJwb3NlIjoiYWR2ZXJ0aXNpbmciLCJ0ZXJyaXRvcmllcyI6WyJVUyIsIkNBIl19LCJ2ZXIiOiIxLjAifX0.sbcXipODRBifCQEGJacDUoBBDzW1YzLdbKAv-ky0fZXjfGRTx4JQd2nap26LYy7PlMRod-7rfqLFgmWE4tutdg",
"max_generations": 4,
"generations_used": 0,
"expires_at": "2026-10-17T18:15:00Z"
},
"escalation": null,
"remedy": null,
"request_digest": "sha256:bf94817766d56d92211d12f5ff51a3dc1a6d5cb4be2877417b08251fe38c386a",
"licensee": "acct_2q8v1m3n7p4r6s9t0wxyhk5zba",
"platform": "acct_7p4r6s9t0wxyhk5zba2q8v1m3n",
"session": null,
"receipt": "rcpt_0wxyhk5zba2q8v1m3n7p4r6s9t",
"metadata": {},
"created_at": "2026-10-17T18:00:00Z"
}Create a check
Test mode available. Live mode available when configured. This describes source support;
production activation is not established. Until activation, a live key receives 403
live_not_activated; do not retry it. Sandbox
checks evaluate fictional fixtures and text inputs; see Sandbox.
The initial live implementation requires one explicit owned license, text inputs totaling
at most 64 KiB, image depiction for commercial advertising or branded content, one candidate,
and on_escalate: "deny". Every channel and territory must match the signed scope; only
signed WW means worldwide. Declare execution.provider and execution.model for the
later output. job_id is optional. Reference media, talent/facet selection, end users,
reuse and nondefault prompt handling are unsupported.
The license must newly sign externalCreation: "images.v1" and
externalCreationPostRevocation: "retain". Live signing requires protected activation after
the public key’s 30-day publication period. Send an Idempotency-Key. While evaluation is
pending, the response is 202 with status: "checking", decision: null and
Retry-After; retry with the same body and key. Retries never start another paid
evaluation. See the initial live image journey.
Broader protocol contract: the remaining description and examples include planned forms beyond that initial live implementation.
Decides whether a use of a talent may proceed, before you generate anything. Send the request your model will actually receive: the user’s prompt, any system text you add, your rewritten prompt, and every reference.
The response always has a decision:
allow: generate, and meet every obligation, includinggeneration_check.deny: do not generate.reasonssay why in the license’s own words;remedysays what would change the answer.escalate: do not generate yet. A person with authority will decide. Listen forcheck.resolvedor poll this check. An unanswered escalation becomesdenyatescalation.expires_at.
Reflections resolves the inputs of every check. Talent named in talent are matched as
explicit, and anyone else the inputs name or show is added. If no protected talent is
found, the decision is allow with talent: [] and no obligations. Reflections checks only the talent
the check resolves; it does not screen outputs for talent nobody named.
Restricted keys need checks:write.
# 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_CHECK_IDEMPOTENCY_KEY:?Set REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY before running this example}"
curl --fail-with-body --max-time 30 -X POST 'https://app.reflections.ai/v1/checks' \
-H "Authorization: Bearer $REFLECTIONS_KEY" \
-H "Reflections-Version: 2026-10-15" \
-H "Idempotency-Key: $REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
--data-raw '{
"inputs": [
{
"role": "prompt",
"text": "Maya Okafor running a mountain trail at sunrise"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social"
],
"territories": [
"US"
]
},
"execution": {
"provider": "sandbox-fixture",
"model": "one-pixel-png",
"candidates": 1
}
}'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_CHECK_IDEMPOTENCY_KEY;
if (!idempotencyKey) throw new Error("Set REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY before running this example");
const response = await fetch("https://app.reflections.ai/v1/checks", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Reflections-Version": "2026-10-15",
"Idempotency-Key": idempotencyKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"inputs": [
{
"role": "prompt",
"text": "Maya Okafor running a mountain trail at sunrise"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social"
],
"territories": [
"US"
]
},
"execution": {
"provider": "sandbox-fixture",
"model": "one-pixel-png",
"candidates": 1
}
}),
signal: AbortSignal.timeout(30_000),
});
const responseBody = await response.text();
if (!response.ok) {
console.error(`HTTP ${response.status}: ${responseBody}`);
exit(1);
}
console.log(responseBody);
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_CHECK_IDEMPOTENCY_KEY"]
if not idempotencyKey:
raise ValueError("Set REFLECTIONS_CREATE_CHECK_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({
"inputs": [{"role": "prompt", "text": "Maya Okafor running a mountain trail at sunrise"}],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": True,
"channels": ["social"],
"territories": ["US"],
},
"execution": {"provider": "sandbox-fixture", "model": "one-pixel-png", "candidates": 1},
}).encode("utf-8")
request = Request("https://app.reflections.ai/v1/checks",
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
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_CHECK_IDEMPOTENCY_KEY")
if idempotencyKey == "" {
panic("Set REFLECTIONS_CREATE_CHECK_IDEMPOTENCY_KEY before running this example")
}
body := strings.NewReader(`{
"inputs": [
{
"role": "prompt",
"text": "Maya Okafor running a mountain trail at sunrise"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social"
],
"territories": [
"US"
]
},
"execution": {
"provider": "sandbox-fixture",
"model": "one-pixel-png",
"candidates": 1
}
}`)
request, err := http.NewRequest("POST", "https://app.reflections.ai/v1/checks", 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))
}
{
"id": "chk_3m7p4r6s9t0wxyhk5zba2q8v1n",
"object": "check",
"livemode": true,
"status": "allowed",
"decision": "allow",
"talent": [
{
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"name": "Maya Okafor",
"matched_by": "name",
"confidence": "high",
"decision": "allow",
"facets": [
"fct_5zba2q8v1m3n7p4r6s9t0wxyhk"
],
"license": "lic_k5zba2q8v1m3n7p4r6s9t0wxyh",
"license_revision": "lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
"terms_digest": "sha256:39f18c8bef02b5226b9feaa92e526ed30b81b91650d8a10b503281b169f44431"
}
],
"use": {
"modality": "image",
"kind": "depiction",
"purpose": "advertising",
"commercial": true,
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
]
},
"reasons": [],
"obligations": [
{
"type": "generation_check",
"required": "all"
},
{
"type": "hold_until_release",
"reviewer": "talent"
},
{
"type": "draft_watermark"
},
{
"type": "generation_instructions",
"instructions": [
"Keep Maya Okafor the same person: face, skin tone and build unchanged.",
"Do not show alcohol or tobacco.",
"Do not imply she endorses any product other than the one shown."
],
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.neverExtras"
},
{
"type": "disclosure",
"level": "brand",
"placement": "both",
"text": "Made with AI. Maya Okafor's likeness used under license by Ridgeline."
},
{
"type": "c2pa_manifest"
},
{
"type": "no_training",
"material": "outputs"
},
{
"type": "usage_report",
"units": "placements",
"within": "P30D"
}
],
"authorization": {
"token": "eyJhbGciOiJFUzI1NiIsImtpZCI6InJmbC0yMDI2LTEwLWRvY3MzIiwidHlwIjoidGxwLWF1dGgrand0In0.eyJhdWQiOiJhY2N0XzdwNHI2czl0MHd4eWhrNXpiYTJxOHYxbTNuIiwiZXhwIjoxNzkyMjYwOTAwLCJpYXQiOjE3OTIyNjAwMDAsImlzcyI6Imh0dHBzOi8vYXBwLnJlZmxlY3Rpb25zLmFpIiwianRpIjoiY2hrXzNtN3A0cjZzOXQwd3h5aGs1emJhMnE4djFuIiwic3ViIjoiYWNjdF8ycTh2MW0zbjdwNHI2czl0MHd4eWhrNXpiYSIsInRscCI6eyJkZWNpc2lvbiI6ImFsbG93IiwiZXUiOiIzZjljMWE3ZTViMmQ4ZjQwNjFjM2U5YTdiNWQyZjgwMTZlNGM5YTNiN2QxZjVlMmM4YTZiNGQwZjllM2M3YTE1IiwiZXhlY3V0aW9uIjp7Im1vZGVsIjoiaW1hZ2UtbW9kZWwtMyIsInByb3ZpZGVyIjoiZXhhbXBsZS1pbWFnZS1wcm92aWRlciJ9LCJmYWNldHMiOlsiZmN0XzV6YmEycTh2MW0zbjdwNHI2czl0MHd4eWhrIl0sImxpY2Vuc2VzIjpbeyJsaWNlbnNlIjoibGljX2s1emJhMnE4djFtM243cDRyNnM5dDB3eHloIiwicmV2aXNpb24iOiJscnZfcDRyNnM5dDB3eHloazV6YmEycTh2MW0zbjciLCJ0YWxlbnQiOiJ0YWxfOXQwd3h5aGs1emJhMnE4djFtM243cDRyNnMiLCJ0ZXJtc19kaWdlc3QiOiJzaGEyNTY6MzlmMThjOGJlZjAyYjUyMjZiOWZlYWE5MmU1MjZlZDMwYjgxYjkxNjUwZDhhMTBiNTAzMjgxYjE2OWY0NDQzMSJ9XSwibWF4X2dlbmVyYXRpb25zIjo0LCJvYmxpZ2F0aW9ucyI6WyJnZW5lcmF0aW9uX2NoZWNrIiwiaG9sZF91bnRpbF9yZWxlYXNlIiwiZHJhZnRfd2F0ZXJtYXJrIiwiZ2VuZXJhdGlvbl9pbnN0cnVjdGlvbnMiLCJkaXNjbG9zdXJlIiwiYzJwYV9tYW5pZmVzdCIsIm5vX3RyYWluaW5nIiwidXNhZ2VfcmVwb3J0Il0sInJlcXVlc3RfZGlnZXN0Ijoic2hhMjU2OmJmOTQ4MTc3NjZkNTZkOTIyMTFkMTJmNWZmNTFhM2RjMWE2ZDVjYjRiZTI4Nzc0MTdiMDgyNTFmZTM4YzM4NmEiLCJ0YWxlbnQiOlsidGFsXzl0MHd4eWhrNXpiYTJxOHYxbTNuN3A0cjZzIl0sInVzZSI6eyJjaGFubmVscyI6WyJzb2NpYWwiLCJ3ZWIiXSwiY29tbWVyY2lhbCI6dHJ1ZSwia2luZCI6ImRlcGljdGlvbiIsIm1vZGFsaXR5IjoiaW1hZ2UiLCJwdXJwb3NlIjoiYWR2ZXJ0aXNpbmciLCJ0ZXJyaXRvcmllcyI6WyJVUyIsIkNBIl19LCJ2ZXIiOiIxLjAifX0.sbcXipODRBifCQEGJacDUoBBDzW1YzLdbKAv-ky0fZXjfGRTx4JQd2nap26LYy7PlMRod-7rfqLFgmWE4tutdg",
"max_generations": 4,
"generations_used": 0,
"expires_at": "2026-10-17T18:15:00Z"
},
"escalation": null,
"remedy": null,
"request_digest": "sha256:bf94817766d56d92211d12f5ff51a3dc1a6d5cb4be2877417b08251fe38c386a",
"licensee": "acct_2q8v1m3n7p4r6s9t0wxyhk5zba",
"platform": "acct_7p4r6s9t0wxyhk5zba2q8v1m3n",
"session": null,
"receipt": "rcpt_0wxyhk5zba2q8v1m3n7p4r6s9t",
"metadata": {},
"created_at": "2026-10-17T18:00:00Z"
}Authorizations
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.
Headers
The dated API version. Defaults to the version your account is pinned to.
"2026-10-15"
Act for a connected licensee. The value is the licensee's account ID. Requires an active connection between that account and yours.
^acct_[0-9a-hjkmnp-tv-z]{26}$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.
255Body
Everything the model will receive, in order: the user's prompt, your system text, any rewritten prompt, references and conversation history.
1 - 64 elementsShow child attributes
Show child attributes
How the output will be used. A different use needs a new check.
Show child attributes
Show child attributes
Talent your user picked. The inputs are still resolved for anyone else.
10^tal_[0-9a-hjkmnp-tv-z]{26}$Talent your user confirmed they did not mean.
^tal_[0-9a-hjkmnp-tv-z]{26}$A specific facet, such as one of several voices.
^fct_[0-9a-hjkmnp-tv-z]{26}$Use this license. By default the narrowest license that allows the use is chosen.
^lic_[0-9a-hjkmnp-tv-z]{26}$The person the request is for. Send it on every check made for a person.
Show child attributes
Show child attributes
The model that will run the request and how many outputs it will make. provider and
model are part of request_digest.
Show child attributes
Show child attributes
deny: never escalate; return deny with review_required instead. Use it for interactive products.
hold, deny Let one decision cover several generations of the same use, talent, execution and end
user until max_generations or ttl runs out, even when later inputs differ. Each
generation is still checked on its output. Generations under reuse omit
candidate_index.
Show child attributes
Show child attributes
How text inputs reach Reflections: full by default, redacted or withheld.
Show child attributes
Show child attributes
Your own keys, returned on the check.
Show child attributes
Show child attributes
Response
The check, with its decision.
The check's ID, chk_ followed by 26 characters.
^chk_[0-9a-hjkmnp-tv-z]{26}$Always check.
"check"true in live mode, false in test mode.
Where the check is now. An allow can later become consumed, expired or
cancelled; an escalate ends allowed, denied or cancelled.
checking, allowed, denied, escalated, consumed, expired, cancelled allow, deny or escalate. An escalated check's decision becomes allow or deny
when a person decides or the escalation expires. Null while status is checking.
allow, deny, escalate Each protected talent the request invokes, with that talent's own decision and license. Empty when none is found.
Show child attributes
Show child attributes
The use the check decided, as you sent it.
Show child attributes
Show child attributes
Why the use was denied or escalated. Empty on allow.
Show child attributes
Show child attributes
What you must do to proceed. Empty unless decision is allow.
Show child attributes
Show child attributes
Digest of the inputs, use and execution this check decided. Without reuse, the authorization covers only this request; with reuse, it also covers later generations of the same use, talent, execution and end user.
^sha256:[0-9a-f]{64}$When the check was created.
Proof of the allow. Pass token to the tool or provider that generates. Null unless
decision is allow.
Show child attributes
Show child attributes
The escalation, when the check is escalated or was decided by a person. When several
talent are escalated, each has their own, named in talent[].escalation. While the
check is open, this field shows the open one that expires first, so its expires_at is
when the check becomes deny. Once decided, it shows the one that decided: the first
deny or expiry, or the last allow. The others still open are then cancelled.
Show child attributes
Show child attributes
What would change a deny. Null for other decisions, and when no change can help, as
with talent_prohibits.
Show child attributes
Show child attributes
The account that holds the license: the licensee named in Reflections-Account, or your
own account under a platform license.
^acct_[0-9a-hjkmnp-tv-z]{26}$The account that ran the check.
^acct_[0-9a-hjkmnp-tv-z]{26}$The session this check started, for a check run by POST /v1/sessions. Null otherwise.
^ses_[0-9a-hjkmnp-tv-z]{26}$The receipt that records the decision. Null until an escalated check is decided.
^rcpt_[0-9a-hjkmnp-tv-z]{26}$Your metadata from the request.
Show child attributes
Show child attributes