Planned protocol reference. These are proposed Talent API MCP tool definitions, not a tool
list from a deployed server. The current sandbox is accessible over HTTP only.
Start with the runnable quickstart and sandbox support matrix.
lic_97bb8qgh1b9zk81anbjkmprxh4 (see Sandbox), so their objects have
livemode: false.
| Tool | Endpoint | Scope | Changes data |
|---|---|---|---|
resolve_talent | POST /v1/resolutions | talent:read | No |
check_use | POST /v1/checks | checks:write | Yes |
submit_generation | POST /v1/generations | generations:write | Yes |
get_check | GET /v1/checks/{check_id} | checks:write | No |
get_generation | GET /v1/generations/{generation_id} | generations:write | No |
get_license | GET /v1/licenses/{license_id} | licenses:read | No |
list_licenses | GET /v1/licenses | licenses:read | No |
request_license | POST /v1/license_requests | license_requests:write | Yes |
report_usage | POST /v1/usage_records | usage:write | Yes |
verify_receipt | POST /v1/verifications | None | No |
isError: true and holds the
problem details, with its code. A deny or escalate is not an error:
it is a normal result with a decision.
The four tools that change data take a required idempotency_key, which the server sends as the
endpoint’s Idempotency-Key. Use a new value for each new use and
the same value when a client retries the call, so a retry returns the first result instead of
checking, submitting or reporting twice. Each tool’s definition is the JSON that tools/list
returns, with its input schema and
annotations.
resolve_talent
Finds which talent a prompt, image or voice sample invokes. Calls Resolve talent. Scopetalent:read.
| Argument | Type | |
|---|---|---|
inputs | array of inputs | Required. 1 to 64, each with a role and text, or media as url with sha256. |
modality | string | The modality to resolve for, such as speech. |
exclude_talent | array of tal_ IDs | Talent the user said they did not mean. |
{
"inputs": [{ "role": "prompt", "text": "A podcast intro read by Maya Okafor" }],
"modality": "speech"
}
{
"id": "res_0wxyhk5zba2q8v1m3n7p4r6s9t",
"object": "resolution",
"livemode": false,
"status": "matched",
"candidates": [
{
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"name": "Maya Okafor",
"matched_by": "name",
"confidence": "high",
"licensed": true,
"declaration": "license_required"
}
],
"use_kind": "impersonation"
}
status: none means no protected talent was found. It is not permission; check_use still decides.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the Resolution object that POST /v1/resolutions returns.{
"name": "resolve_talent",
"title": "Resolve talent",
"description": "Find which protected talent a prompt, image or voice sample names or shows, before you check a use. A result with no candidates is not permission: call check_use before generating any real person.",
"inputSchema": {
"type": "object",
"required": ["inputs"],
"properties": {
"inputs": {
"type": "array",
"minItems": 1,
"maxItems": 64,
"items": {
"type": "object",
"description": "One part of the request a model receives, in order. Send text inline; send media as a file ID, or as `sha256` with a `url` Reflections can fetch.",
"required": ["role"],
"properties": {
"role": {
"type": "string",
"enum": [
"prompt",
"system",
"negative_prompt",
"rewritten_prompt",
"script",
"reference",
"voice_sample",
"mask",
"context"
],
"description": "`prompt`: the user's words. `system`: instructions you add. `rewritten_prompt`: your expansion of the prompt, if the model receives that instead. `script`: words to be spoken. `reference`, `voice_sample`, `mask`: media the model receives. `context`: conversation history the model receives."
},
"text": {
"type": "string",
"maxLength": 32000,
"description": "The text, for every role except `reference`, `voice_sample` and `mask`."
},
"file": {
"type": "string",
"pattern": "^file_[0-9a-hjkmnp-tv-z]{26}$",
"description": "A file ID from `POST /v1/files`, for a `reference`, `voice_sample` or `mask` input."
},
"url": {
"type": "string",
"format": "uri",
"description": "A URL Reflections can fetch the media from. Send `sha256` and `media_type` with it."
},
"sha256": {
"type": "string",
"description": "SHA-256 of the bytes, in hex: of the media at `url`, or of a text input's UTF-8 bytes when `prompt_handling.mode` is `withheld`.",
"pattern": "^[0-9a-f]{64}$"
},
"media_type": {
"type": "string",
"description": "The MIME type of the media at `url`, or `text/plain` for a withheld text input."
}
}
},
"description": "The parts of the request, in order, as you would send them on a check."
},
"modality": {
"type": "string",
"description": "What the model will generate, as in a check's `use.modality`.",
"enum": ["image", "video", "speech", "audio", "text"]
},
"exclude_talent": {
"type": "array",
"items": {
"type": "string",
"pattern": "^tal_[0-9a-hjkmnp-tv-z]{26}$"
},
"description": "Talent your user confirmed they did not mean. They are left out of `candidates`."
}
}
},
"annotations": {
"title": "Resolve talent",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
check_use
Decides whether a use may proceed, before anything is generated. Calls Create a check. Scopechecks:write.
| Argument | Type | |
|---|---|---|
inputs | array of inputs | Required. Everything the generation tool will receive: the prompt, system text, rewritten prompt and references. |
use | object | Required. modality, kind, purpose, commercial, and channels and territories when commercial. |
talent | array of tal_ IDs | Talent your user picked. The inputs are still resolved for anyone else. |
exclude_talent | array of tal_ IDs | Talent the user confirmed they did not mean. |
facet | fct_ ID | A specific facet, such as one of several voices. |
license | lic_ ID | A specific license. By default the narrowest license that allows the use is chosen. |
end_user | object | id, a stable ID for the person the agent acts for. Never an email or a name. |
execution | object | provider, model and candidates of the generation tool. |
on_escalate | string | hold (default) or deny. |
reuse | object | max_generations (up to 1,000) and ttl (up to PT15M). |
prompt_handling | object | mode and retention. |
metadata | object | Your own keys. |
idempotency_key | string | Required. Sent as the Idempotency-Key. Reuse it only when retrying this call. |
{
"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"]
},
"end_user": { "id": "usr_48213" },
"execution": { "provider": "example-image-provider", "model": "image-model-3", "candidates": 1 },
"on_escalate": "deny",
"idempotency_key": "a9bbbc20-9aeb-5252-a56d-983f8db19ea2"
}
{
"id": "chk_njtrx9ds0f6ttqpp538zqppeg7",
"object": "check",
"livemode": false,
"status": "allowed",
"decision": "allow",
"reasons": [],
"obligations": [
{ "type": "generation_check", "required": "all" },
{ "type": "generation_instructions", "instructions": ["Keep Maya Okafor the same person: face, skin tone and build unchanged."] },
{ "type": "disclosure", "level": "licensed", "placement": "both", "text": "Made with AI. Likeness used under license." },
{ "type": "c2pa_manifest" }
],
"authorization": {
"token": "eyJhbGciOiJFUzI1NiIs…",
"max_generations": 1,
"generations_used": 0,
"expires_at": "2026-10-17T18:15:00Z"
},
"remedy": null
}
allow, pass authorization.token to the generation tool with the same inputs, and add every
generation_instructions entry to what it receives. On deny, show reasons[].sentence; if
remedy.type is license_request or license_change, offer request_license. On escalate,
tell the user the request is with the talent’s reviewer, and read the outcome later with
get_check. An agent that cannot come back to a conversation passes
on_escalate: "deny".
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the Check object that POST /v1/checks returns.{
"name": "check_use",
"title": "Check a use",
"description": "Decide whether a use of a real person's name, likeness or voice may proceed, before you generate anything. Send everything the generation tool will receive. On allow, pass authorization.token to the generation tool and follow every obligation. On deny, show reasons[].sentence to the user and do not generate. On escalate, do not generate yet; read the decision later with get_check.",
"inputSchema": {
"type": "object",
"required": ["inputs", "use", "idempotency_key"],
"properties": {
"talent": {
"type": "array",
"description": "Talent your user picked. The inputs are still resolved for anyone else.",
"items": {
"type": "string",
"pattern": "^tal_[0-9a-hjkmnp-tv-z]{26}$"
},
"maxItems": 10
},
"exclude_talent": {
"type": "array",
"description": "Talent your user confirmed they did not mean.",
"items": {
"type": "string",
"pattern": "^tal_[0-9a-hjkmnp-tv-z]{26}$"
}
},
"facet": {
"type": "string",
"pattern": "^fct_[0-9a-hjkmnp-tv-z]{26}$",
"description": "A specific facet, such as one of several voices."
},
"license": {
"type": "string",
"pattern": "^lic_[0-9a-hjkmnp-tv-z]{26}$",
"description": "Use this license. By default the narrowest license that allows the use is chosen."
},
"inputs": {
"type": "array",
"minItems": 1,
"maxItems": 64,
"items": {
"type": "object",
"description": "One part of the request a model receives, in order. Send text inline; send media as a file ID, or as `sha256` with a `url` Reflections can fetch.",
"required": ["role"],
"properties": {
"role": {
"type": "string",
"enum": [
"prompt",
"system",
"negative_prompt",
"rewritten_prompt",
"script",
"reference",
"voice_sample",
"mask",
"context"
],
"description": "`prompt`: the user's words. `system`: instructions you add. `rewritten_prompt`: your expansion of the prompt, if the model receives that instead. `script`: words to be spoken. `reference`, `voice_sample`, `mask`: media the model receives. `context`: conversation history the model receives."
},
"text": {
"type": "string",
"maxLength": 32000,
"description": "The text, for every role except `reference`, `voice_sample` and `mask`."
},
"file": {
"type": "string",
"pattern": "^file_[0-9a-hjkmnp-tv-z]{26}$",
"description": "A file ID from `POST /v1/files`, for a `reference`, `voice_sample` or `mask` input."
},
"url": {
"type": "string",
"format": "uri",
"description": "A URL Reflections can fetch the media from. Send `sha256` and `media_type` with it."
},
"sha256": {
"type": "string",
"description": "SHA-256 of the bytes, in hex: of the media at `url`, or of a text input's UTF-8 bytes when `prompt_handling.mode` is `withheld`.",
"pattern": "^[0-9a-f]{64}$"
},
"media_type": {
"type": "string",
"description": "The MIME type of the media at `url`, or `text/plain` for a withheld text input."
}
}
},
"description": "Everything the model will receive, in order: the user's prompt, your system text, any rewritten prompt, references and conversation history."
},
"use": {
"type": "object",
"required": ["modality", "kind", "purpose", "commercial"],
"properties": {
"modality": {
"type": "string",
"description": "What will be generated.",
"enum": ["image", "video", "speech", "audio", "text"]
},
"kind": {
"type": "string",
"description": "How the talent appears in the output.",
"enum": ["depiction", "impersonation", "endorsement", "reference"]
},
"purpose": {
"type": "string",
"enum": [
"advertising",
"branded_content",
"entertainment",
"editorial",
"personal",
"education",
"political"
],
"description": "What the output is for."
},
"commercial": {
"type": "boolean",
"description": "Whether anyone earns money from the output, including through advertising."
},
"channels": {
"type": "array",
"items": {
"type": "string",
"description": "Where the output will appear.",
"enum": [
"social",
"web",
"in_app",
"streaming",
"tv",
"cinema",
"out_of_home",
"print",
"audio",
"email",
"retail",
"games",
"private"
]
},
"maxItems": 20,
"description": "Required when `commercial` is true."
},
"territories": {
"type": "array",
"items": {
"type": "string",
"description": "An ISO 3166-1 alpha-2 country code, or `WW` for worldwide.",
"pattern": "^([A-Z]{2})$"
},
"maxItems": 50,
"description": "Required when `commercial` is true."
}
},
"description": "How the output will be used. A different use needs a new check."
},
"end_user": {
"type": "object",
"description": "The person the request is for. Send it on every check made for a person.",
"required": ["id"],
"properties": {
"id": {
"type": "string",
"maxLength": 200,
"description": "Your stable ID for the person, up to 200 characters. Never an email or a name."
},
"type": {
"type": "string",
"enum": ["consumer", "business"],
"default": "consumer",
"description": "`consumer` for a person acting for themselves, `business` for one acting for a company."
}
}
},
"execution": {
"type": "object",
"description": "The model that will run the request and how many outputs it will make. `provider` and `model` are part of `request_digest`.",
"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."
}
}
},
"on_escalate": {
"type": "string",
"enum": ["hold", "deny"],
"default": "hold",
"description": "`deny`: never escalate; return `deny` with `review_required` instead. Use it for interactive products."
},
"reuse": {
"type": "object",
"description": "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`.",
"properties": {
"max_generations": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"description": "Generations the window covers, up to 1,000."
},
"ttl": {
"allOf": [
{
"type": "string",
"description": "An ISO 8601 duration, such as `PT60S` or `P30D`."
}
],
"description": "How long the window lasts. At most `PT15M`."
}
}
},
"prompt_handling": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": ["full", "redacted", "withheld"],
"default": "full",
"description": "`full`: text is sent as is. `redacted`: you removed personal data first, and the digest covers the redacted text. `withheld`: no text is sent. Send each text input as `role`, `sha256` of its UTF-8 bytes and `media_type: text/plain`, and name the talent in `talent`, because names cannot be matched in text Reflections does not see. Rules that need the text are checked on the output instead."
},
"retention": {
"type": "string",
"enum": ["default", "none"],
"default": "default",
"description": "`none`: delete text as soon as the check is decided, even on `deny` or `escalate`."
}
},
"description": "How text inputs reach Reflections: `full` by default, `redacted` or `withheld`."
},
"metadata": {
"type": "object",
"description": "Your own keys, returned on the check.",
"additionalProperties": {
"type": "string",
"maxLength": 500
},
"maxProperties": 50
},
"idempotency_key": {
"type": "string",
"maxLength": 255,
"description": "Sent as the Idempotency-Key. Use a new value for each new use, and the same value when you retry this call: a retry then returns the first result instead of running twice."
}
}
},
"annotations": {
"title": "Check a use",
"readOnlyHint": false,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
submit_generation
Checks an output before anyone sees it. Calls Create a generation. Scopegenerations:write.
| Argument | Type | |
|---|---|---|
check | chk_ ID | The check the output was made under. Required unless session is set. |
session | ses_ ID | The session the output was made in, instead of a check. |
candidate_index | integer | Which of the check’s candidates this is, from 0. Omit under reuse. |
artifact | object | Proposed output contract: url or base64 data (10 MB target), with sha256 (required), media_type and duration_ms. The current HTTP sandbox accepts at most 7 MiB decoded bytes in a 10 MiB JSON body and does not fetch URLs. |
execution | object | provider, model and job_id. |
transcript | string | Words spoken in the output, if you have them. |
watermark | object | algorithm and id of a watermark you applied. |
metadata | object | Your own keys. |
idempotency_key | string | Required. Sent as the Idempotency-Key. Reuse it only when retrying this call. |
{
"check": "chk_njtrx9ds0f6ttqpp538zqppeg7",
"candidate_index": 0,
"artifact": {
"url": "https://cdn.northlight.example/outputs/88213.png",
"sha256": "9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a",
"media_type": "image/png"
},
"execution": { "provider": "example-image-provider", "model": "image-model-3", "job_id": "job_88213" },
"idempotency_key": "1225df77-5ee5-5bff-8b55-cf555e6c6bee"
}
{
"id": "gen_ekqjdddns0qtrqjb6vt85722ky",
"object": "generation",
"livemode": false,
"status": "allowed",
"decision": "allow",
"assurance": "observed",
"receipt": "rcpt_e3g0e4fx2nzv12c20b2tkyj9xq",
"c2pa": {
"label": "ai.reflections.license",
"data": {
"receipt": "eyJhbGciOiJFUzI1NiIs…",
"verify_url": "https://app.reflections.ai/r/rcpt_e3g0e4fx2nzv12c20b2tkyj9xq"
}
}
}
decision is allow, after you embed c2pa as described in
C2PA assertion. Video and longer audio return
status: "checking"; read the decision with get_generation, or receive it as
a webhook to your platform.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the Generation object that POST /v1/generations returns.{
"name": "submit_generation",
"title": "Submit an output",
"description": "Submit an output made under an allowed check or session, before anyone sees it. Release the output only when the result's decision is allow, and embed the receipt it returns.",
"inputSchema": {
"type": "object",
"required": ["artifact", "idempotency_key"],
"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": {
"type": "object",
"description": "The output's bytes, as a file ID, a URL or base64 `data`, with their SHA-256.",
"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": {
"type": "string",
"description": "The SHA-256 of the bytes. If the bytes Reflections receives differ, the call fails with `422 artifact_digest_mismatch`.",
"pattern": "^[0-9a-f]{64}$"
},
"media_type": {
"type": "string",
"description": "The bytes' media type, such as `image/png`."
},
"duration_ms": {
"type": "integer",
"minimum": 0,
"description": "For audio and video."
}
}
},
"execution": {
"type": "object",
"description": "The run that made the output. Send `job_id` when the provider gives one.",
"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."
}
}
},
"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": {
"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."
}
},
"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": {
"type": "object",
"description": "Your own keys, returned on the generation.",
"additionalProperties": {
"type": "string",
"maxLength": 500
},
"maxProperties": 50
},
"idempotency_key": {
"type": "string",
"maxLength": 255,
"description": "Sent as the Idempotency-Key. Use a new value for each new use, and the same value when you retry this call: a retry then returns the first result instead of running twice."
}
}
},
"annotations": {
"title": "Submit an output",
"readOnlyHint": false,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
get_check
Reads a check, to follow an escalation to its decision. Calls Retrieve a check. Scopechecks:write.
| Argument | Type | |
|---|---|---|
check_id | chk_ ID | Required. |
{ "check_id": "chk_njtrx9ds0f6ttqpp538zqppeg7" }
status is escalated and escalation.expires_at
says when it becomes a deny. Once decided, decision is allow with an authorization, or
deny with reasons. Read it at most once every 5 seconds; a reviewer usually answers in hours,
not seconds, so a longer interval is better.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the Check object that GET /v1/checks/{check_id} returns.{
"name": "get_check",
"title": "Get a check",
"description": "Read a check, to learn the decision on an escalated check. Call it at most once every 5 seconds.",
"inputSchema": {
"type": "object",
"properties": {
"check_id": {
"type": "string",
"pattern": "^chk_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The check's ID."
}
},
"required": ["check_id"]
},
"annotations": {
"title": "Get a check",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
get_generation
Reads a generation, to collect the decision on a video, longer audio or a held output. Calls Retrieve a generation. Scopegenerations:write.
| Argument | Type | |
|---|---|---|
generation_id | gen_ ID | Required. |
{ "generation_id": "gen_ekqjdddns0qtrqjb6vt85722ky" }
status moves from checking or held to allowed, released or
denied. Deliver on allowed or released only, with the c2pa assertion embedded.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the Generation object that GET /v1/generations/{generation_id} returns.{
"name": "get_generation",
"title": "Get a generation",
"description": "Read a generation, to collect the decision on a held output, a video or longer audio. Call it at most once every 5 seconds.",
"inputSchema": {
"type": "object",
"properties": {
"generation_id": {
"type": "string",
"pattern": "^gen_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The generation's ID."
}
},
"required": ["generation_id"]
},
"annotations": {
"title": "Get a generation",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
get_license
Reads one license. Calls Retrieve a license. Scopelicenses:read.
| Argument | Type | |
|---|---|---|
license_id | lic_ ID | Required. |
{ "license_id": "lic_97bb8qgh1b9zk81anbjkmprxh4" }
status, handle, current_revision, terms_digest and normalized
scope:
{
"id": "lic_97bb8qgh1b9zk81anbjkmprxh4",
"object": "license",
"livemode": false,
"status": "active",
"handle": "T8M3QX",
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"licensee": "acct_7p4r6s9t0wxyhk5zba2q8v1m3n",
"current_revision": "lrv_11knr0923nvdw36qe404d6c55d",
"revision_number": 1,
"terms_digest": "sha256:4036ac3ffc579dc70d5a9132242e3cb588007d08bee1b2b92812b2d4e3ff7f4e",
"scope": {
"modalities": ["image", "video", "speech"],
"purposes": ["advertising"],
"commercial": true,
"channels": ["social", "web"],
"territories": ["US", "CA"]
}
}
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the License object that GET /v1/licenses/{license_id} returns.{
"name": "get_license",
"title": "Get a license",
"description": "Read one license: its scope, terms, window and status.",
"inputSchema": {
"type": "object",
"properties": {
"license_id": {
"type": "string",
"pattern": "^lic_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The license's ID."
}
},
"required": ["license_id"]
},
"annotations": {
"title": "Get a license",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
list_licenses
Lists the licenses the account holds or may use. Calls List licenses. Scopelicenses:read.
| Argument | Type | |
|---|---|---|
talent | tal_ ID | Only licenses for this talent. |
status | string | Only licenses with this status, such as active. |
limit | integer | 1 to 100. Default 20. |
cursor | string | The next_cursor from the previous result. |
{ "talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s", "status": "active" }
data, has_more and next_cursor.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the LicenseList object that GET /v1/licenses returns.{
"name": "list_licenses",
"title": "List licenses",
"description": "List the licenses the account holds or may use, optionally for one talent.",
"inputSchema": {
"type": "object",
"properties": {
"role": {
"type": "string",
"enum": ["licensee", "issuer"],
"default": "licensee",
"description": "`licensee` (the default): licenses you hold. `issuer`: licenses you issued as talent."
},
"talent": {
"type": "string",
"pattern": "^tal_[0-9a-hjkmnp-tv-z]{26}$",
"description": "Only licenses granted by this talent."
},
"status": {
"type": "string",
"description": "Only licenses with this status, such as `active`. Live reads also accept `void`; the sandbox status filter does not.",
"enum": [
"pending_acceptance",
"scheduled",
"active",
"suspended",
"expired",
"declined",
"revoked",
"void"
]
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20,
"description": "Number of objects to return, 1 to 100."
},
"cursor": {
"type": "string",
"description": "The `next_cursor` from the previous page."
}
}
},
"annotations": {
"title": "List licenses",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
request_license
Asks a talent for a new license, or a wider one. Calls Request a license. Scopelicense_requests:write.
| Argument | Type | |
|---|---|---|
kind | string | Required. new or change. |
talent | tal_ ID | Required. |
requested_scope | object | Required. The scope you ask for: facets, modalities, purposes, channels, territories, dates and more. |
license | lic_ ID | Required for change. |
check | chk_ ID | The denied check this request answers. The talent sees the use that prompted it. |
offer | object | What you offer to pay, as compensation. |
note | string | Shown to the talent as written, up to 2,000 characters. |
metadata | object | Your own keys. |
idempotency_key | string | Required. Sent as the Idempotency-Key. Reuse it only when retrying this call. |
{
"kind": "change",
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"license": "lic_97bb8qgh1b9zk81anbjkmprxh4",
"check": "chk_pmx6dzq8fwbhtagr03q59ehs40",
"requested_scope": { "channels": ["social", "web", "tv"] },
"note": "We would like to run the spring trail images as a TV spot in the US and Canada.",
"idempotency_key": "f4aced76-7a7e-5d3d-8202-2dea9eb75075"
}
status: "sent":
{
"id": "lrq_t0wxyhk5zba2q8v1m3n7p4r6s9",
"object": "license_request",
"livemode": false,
"kind": "change",
"status": "sent",
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"license": "lic_97bb8qgh1b9zk81anbjkmprxh4",
"check": "chk_pmx6dzq8fwbhtagr03q59ehs40"
}
acceptance_url, where a person on the licensee’s side signs. No tool can sign or
accept a license.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the LicenseRequest object that POST /v1/license_requests returns.{
"name": "request_license",
"title": "Request a license",
"description": "Ask a talent for a new license, or a change to one, when a check was denied with a license_request or license_change remedy. The talent's side decides; nothing is granted by this call.",
"inputSchema": {
"type": "object",
"required": ["kind", "talent", "requested_scope", "idempotency_key"],
"properties": {
"kind": {
"type": "string",
"enum": ["new", "change"],
"description": "`new` for a new license, or `change` for a new revision of the license in `license`, such as a wider scope."
},
"talent": {
"type": "string",
"pattern": "^tal_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The talent to ask. A talent whose `posture.accepts_requests` is `false` takes no requests through the API."
},
"license": {
"type": "string",
"pattern": "^lic_[0-9a-hjkmnp-tv-z]{26}$",
"description": "Required for `change`."
},
"check": {
"type": "string",
"pattern": "^chk_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The denied check this request answers. The talent sees the use that prompted it."
},
"requested_scope": {
"type": "object",
"description": "The terms you ask for. A denied check's `remedy.suggested_scope` is a starting point. For `change`, omitted fields keep the current license's terms.",
"properties": {
"facets": {
"type": "array",
"items": {
"type": "string",
"pattern": "^fct_[0-9a-hjkmnp-tv-z]{26}$"
},
"description": "The facets you ask for, by ID."
},
"facet_types": {
"type": "array",
"items": {
"type": "string",
"description": "`name`: the name in text. `likeness`: face and body in images and video. `voice`: the voice in speech. `twin`: a persona that speaks or writes as the talent. `knowledge`: a Volume of the talent's own words a model may draw on.",
"enum": ["name", "likeness", "voice", "twin", "knowledge"]
},
"description": "The facet types you ask for, such as `likeness`, when you do not name `facets`."
},
"modalities": {
"type": "array",
"items": {
"type": "string",
"description": "What will be generated. `speech` is a voice speaking words; `audio` is any other sound.",
"enum": ["image", "video", "speech", "audio", "text"]
},
"description": "What you want to generate."
},
"kinds": {
"type": "array",
"items": {
"type": "string",
"description": "How the talent appears. `depiction`: shown or heard. `impersonation`: speaks or writes as the talent. `endorsement`: implies the talent approves something. `reference`: talked about, without synthesis; needs no license.",
"enum": ["depiction", "impersonation", "endorsement", "reference"]
},
"description": "How the talent would appear."
},
"purposes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"advertising",
"branded_content",
"entertainment",
"editorial",
"personal",
"education",
"political"
]
},
"description": "What the outputs are for."
},
"commercial": {
"type": "boolean",
"description": "`true` to ask for commercial use."
},
"channels": {
"type": "array",
"items": {
"type": "string",
"description": "Where the output will appear.",
"enum": [
"social",
"web",
"in_app",
"streaming",
"tv",
"cinema",
"out_of_home",
"print",
"audio",
"email",
"retail",
"games",
"private"
]
},
"description": "Where outputs would appear. For `change`, list every channel you want, not only the new ones."
},
"territories": {
"type": "array",
"items": {
"type": "string",
"description": "An ISO 3166-1 alpha-2 country code, or `WW` for worldwide.",
"pattern": "^([A-Z]{2})$"
},
"description": "Where outputs would appear, as ISO 3166-1 alpha-2 codes or `WW`."
},
"starts_at": {
"type": "string",
"format": "date-time",
"description": "When you want the license to come into force."
},
"ends_at": {
"type": "string",
"format": "date-time",
"description": "When you want the license to end."
},
"adjustments": {
"type": "array",
"description": "Adjustments you ask to be allowed.",
"items": {
"type": "string",
"description": "A change the licensee may make to the talent's appearance or context.",
"enum": [
"reframe",
"background_extension",
"lighting",
"text_overlay",
"body_and_age",
"expression",
"hair",
"pose",
"wardrobe",
"objects",
"skin_retouch",
"endorsement"
]
}
},
"final_deliverables": {
"type": "integer",
"minimum": 1,
"description": "How many outputs you want to deliver in total."
},
"sessions": {
"type": "boolean",
"description": "Ask for live sessions."
},
"material_access": {
"type": "boolean",
"description": "`true` to ask to download the facets' reference material and send it to a model."
},
"platforms": {
"type": "array",
"items": {
"type": "string",
"pattern": "^acct_[0-9a-hjkmnp-tv-z]{26}$"
},
"description": "Platform accounts you want to run checks under the license."
},
"sublicense": {
"type": "string",
"enum": ["none", "end_users_personal"],
"description": "`end_users_personal` to ask that a platform's end users may make personal, non-commercial outputs."
}
}
},
"offer": {
"type": "object",
"description": "What you offer to pay. The talent's side may sign different compensation.",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"enum": ["none", "flat", "per_unit", "revenue_share"],
"description": "How the amount owed is set: `none` owes nothing, `flat` is a fixed fee, `per_unit` is a rate per unit of usage, and `revenue_share` is `revenue_share_bps` of revenue."
},
"flat": {
"type": "object",
"required": ["amount", "currency"],
"properties": {
"amount": {
"type": "integer",
"description": "In the currency's smallest unit, such as cents."
},
"currency": {
"type": "string",
"pattern": "^[a-z]{3}$",
"description": "ISO 4217, lowercase."
}
},
"description": "The fixed fee, for `type: flat`."
},
"per_unit": {
"type": "object",
"description": "The rate, for `type: per_unit`.",
"properties": {
"units": {
"type": "string",
"enum": ["outputs", "seconds", "characters", "placements", "impressions"],
"description": "What the rate counts. Reflections observes outputs, seconds and characters itself; placements and impressions come from usage you report."
},
"rate": {
"type": "object",
"required": ["amount", "currency"],
"properties": {
"amount": {
"type": "integer",
"description": "In the currency's smallest unit, such as cents."
},
"currency": {
"type": "string",
"pattern": "^[a-z]{3}$",
"description": "ISO 4217, lowercase."
}
},
"description": "The amount owed for each `per` units."
},
"per": {
"type": "integer",
"default": 1,
"description": "The rate is for this many units, such as 1000 impressions."
}
}
},
"revenue_share_bps": {
"type": "integer",
"minimum": 0,
"maximum": 10000,
"description": "Basis points of revenue the license names."
},
"minimum": {
"type": "object",
"required": ["amount", "currency"],
"properties": {
"amount": {
"type": "integer",
"description": "In the currency's smallest unit, such as cents."
},
"currency": {
"type": "string",
"pattern": "^[a-z]{3}$",
"description": "ISO 4217, lowercase."
}
},
"description": "The least the licensee owes, however little is used."
},
"schedule": {
"type": "string",
"enum": ["on_acceptance", "monthly", "quarterly"],
"description": "When the licensee pays: once on acceptance, each month, or each quarter."
}
}
},
"note": {
"type": "string",
"maxLength": 2000,
"description": "Shown to the talent as written."
},
"metadata": {
"type": "object",
"description": "Your own key-value pairs, returned on the request.",
"additionalProperties": {
"type": "string",
"maxLength": 500
},
"maxProperties": 50
},
"idempotency_key": {
"type": "string",
"maxLength": 255,
"description": "Sent as the Idempotency-Key. Use a new value for each new use, and the same value when you retry this call: a retry then returns the first result instead of running twice."
}
}
},
"annotations": {
"title": "Request a license",
"readOnlyHint": false,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
report_usage
Reports usage for generations and sessions. Calls Report usage. Scopeusage:write.
| Argument | Type | |
|---|---|---|
records | array | Required. 1 to 1,000 records. |
records[].subject | gen_ or ses_ ID | Required. What the record settles. |
records[].units | string | Required. outputs, seconds, characters, placements or impressions. |
records[].quantity | number | Required. |
records[].occurred_at | timestamp | Required. |
records[].placement | object | channel, territory and url, for placements and impressions. |
records[].correction_of | ur_ ID | The record this one replaces. |
idempotency_key | string | Required. Sent as the Idempotency-Key. Reuse it only when retrying this call. |
{
"records": [
{
"subject": "gen_ekqjdddns0qtrqjb6vt85722ky",
"units": "placements",
"quantity": 1,
"occurred_at": "2026-10-18T09:00:00Z",
"placement": { "channel": "social", "territory": "US" }
}
],
"idempotency_key": "1d0e4ed6-3f36-5fa6-bd39-91d188e6e7f2"
}
accepted or rejected with a rejection.code.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the UsageRecordList object that POST /v1/usage_records returns.{
"name": "report_usage",
"title": "Report usage",
"description": "Report how outputs and sessions were used, as the license's usage_report obligation requires.",
"inputSchema": {
"type": "object",
"required": ["records", "idempotency_key"],
"properties": {
"records": {
"type": "array",
"minItems": 1,
"maxItems": 1000,
"items": {
"type": "object",
"required": ["subject", "units", "quantity", "occurred_at"],
"properties": {
"subject": {
"type": "string",
"pattern": "^(gen|ses)_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The generation or session this record settles."
},
"license": {
"type": "string",
"pattern": "^lic_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The license the usage counts against. Required when the subject was decided under more than one license; send one record per license."
},
"units": {
"type": "string",
"enum": ["outputs", "seconds", "characters", "placements", "impressions"],
"description": "The unit `quantity` counts. Report the `units` the `usage_report` obligation names."
},
"quantity": {
"type": "number",
"minimum": 0,
"description": "How many `units`. May be fractional, such as `3.4` seconds."
},
"occurred_at": {
"type": "string",
"format": "date-time",
"description": "When the use happened."
},
"placement": {
"type": "object",
"description": "For `placements` and `impressions`.",
"properties": {
"channel": {
"type": "string",
"description": "Where the output was placed.",
"enum": [
"social",
"web",
"in_app",
"streaming",
"tv",
"cinema",
"out_of_home",
"print",
"audio",
"email",
"retail",
"games",
"private"
]
},
"territory": {
"type": "string",
"description": "The country where the output was placed or shown.",
"pattern": "^([A-Z]{2})$"
},
"url": {
"type": "string",
"format": "uri",
"description": "The placement's address, when it has one."
}
}
},
"correction_of": {
"type": "string",
"pattern": "^ur_[0-9a-hjkmnp-tv-z]{26}$",
"description": "The record this one replaces."
},
"metadata": {
"type": "object",
"description": "Your own keys, such as your batch ID. Returned on the record.",
"additionalProperties": {
"type": "string",
"maxLength": 500
},
"maxProperties": 50
}
}
},
"description": "1 to 1,000 records. Each is accepted or rejected on its own."
},
"idempotency_key": {
"type": "string",
"maxLength": 255,
"description": "Sent as the Idempotency-Key. Use a new value for each new use, and the same value when you retry this call: a retry then returns the first result instead of running twice."
}
}
},
"annotations": {
"title": "Report usage",
"readOnlyHint": false,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
verify_receipt
Verifies a receipt, a manifest or a file, and returns the receipt it matches with its live status. Calls Verify content. No scope is needed. Send exactly one argument:| Argument | Type | |
|---|---|---|
receipt | string | A receipt ID or JWS. |
manifest | string | A C2PA manifest store, base64. |
url | string | A file Reflections can fetch. |
sha256 | string | The hex SHA-256 of a file. |
fingerprint | object | A perceptual hash and embeddings. |
{ "receipt": "rcpt_e3g0e4fx2nzv12c20b2tkyj9xq" }
{
"id": "vrf_gf41f2za3zh7vv50jyheky90mc",
"object": "verification",
"result": "verified",
"method": "receipt",
"receipt": {
"id": "rcpt_e3g0e4fx2nzv12c20b2tkyj9xq",
"livemode": false,
"decision": "allow",
"assurance": "observed",
"use_status": "permitted"
}
}
result: "not_found" says nothing about whether the content is licensed. invalid means a
receipt or manifest is present and fails verification.
Tool definition
Tool definition
As
tools/list returns it. Its outputSchema is the JSON Schema of the Verification object that POST /v1/verifications returns.{
"name": "verify_receipt",
"title": "Verify a receipt",
"description": "Verify a receipt, a C2PA manifest or a file, and read the receipt it matches with its live use status. A not_found result says nothing about whether the content is licensed.",
"inputSchema": {
"type": "object",
"description": "Send exactly one of `receipt`, `manifest`, `url`, `sha256` or `fingerprint`.",
"properties": {
"receipt": {
"type": "string",
"description": "A receipt ID or JWS."
},
"manifest": {
"type": "string",
"contentEncoding": "base64",
"description": "A C2PA manifest store."
},
"url": {
"type": "string",
"format": "uri",
"description": "A file Reflections can fetch."
},
"sha256": {
"type": "string",
"description": "SHA-256 of the file's bytes, in hex. Matches only an exact copy of a registered output.",
"pattern": "^[0-9a-f]{64}$"
},
"fingerprint": {
"type": "object",
"description": "A fingerprint you computed, when the bytes cannot leave your platform.",
"properties": {
"perceptual_hash": {
"type": "object",
"description": "A perceptual hash of the file.",
"required": ["algorithm", "value"],
"properties": {
"algorithm": {
"type": "string",
"enum": ["pdq", "vpdq", "chromaprint"],
"description": "`pdq` for images, `vpdq` for video, `chromaprint` for audio."
},
"value": {
"type": "string",
"description": "The hash in the algorithm's standard text form, such as 64 hex characters for `pdq`."
}
}
},
"embeddings": {
"type": "array",
"items": {
"type": "object",
"required": ["model", "vector"],
"properties": {
"model": {
"type": "string",
"enum": ["reflections-face-1", "reflections-voice-1"],
"description": "The model that computed `vector`: `reflections-face-1` for faces, `reflections-voice-1` for voices."
},
"vector": {
"type": "string",
"contentEncoding": "base64",
"description": "Little-endian float32 values."
}
}
},
"description": "Optional face or voice embeddings of the file, used with the hash to look it up."
}
}
}
}
},
"annotations": {
"title": "Verify a receipt",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}
Related
MCP server
Proposed transport, OAuth and scopes.
Agent integration design
A check, a token and a generation tool, end to end.