: "${REFLECTIONS_KEY:?Set REFLECTIONS_KEY before running this example}"
curl --fail-with-body --max-time 30 'https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7' \
-H "Authorization: Bearer $REFLECTIONS_KEY" \
-H "Reflections-Version: 2026-10-15"import { env, exit } from "node:process";
const apiKey = env.REFLECTIONS_KEY;
if (!apiKey) throw new Error("Set REFLECTIONS_KEY before running this example");
const response = await fetch("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7", {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
"Reflections-Version": "2026-10-15",
},
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 os
from urllib.error import HTTPError
from urllib.request import Request, urlopen
apiKey = os.environ["REFLECTIONS_KEY"]
if not apiKey:
raise ValueError("Set REFLECTIONS_KEY before running this example")
headers = {
"Authorization": f"Bearer {apiKey}",
"Reflections-Version": "2026-10-15",
}
request = Request("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
method="GET", headers=headers)
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"
"time"
)
func main() {
apiKey := os.Getenv("REFLECTIONS_KEY")
if apiKey == "" {
panic("Set REFLECTIONS_KEY before running this example")
}
request, err := http.NewRequest("GET", "https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7", nil)
if err != nil {
panic(err)
}
request.Header.Set("Authorization", "Bearer " + apiKey)
request.Header.Set("Reflections-Version", "2026-10-15")
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": "lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
"object": "license_revision",
"livemode": true,
"license": "lic_k5zba2q8v1m3n7p4r6s9t0wxyh",
"number": 1,
"status": "current",
"source_kind": "issue",
"terms": {
"releasePolicy": "perOutputTalentReview",
"adjustments": {
"reframe": true,
"backgroundExtension": true,
"lighting": true,
"textOverlay": true,
"bodyAndAge": false,
"expression": false,
"hair": false,
"pose": false,
"wardrobe": true,
"objects": true,
"skinRetouch": false,
"endorsement": false
},
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
],
"startsAt": "2026-10-01T00:00:00-04:00",
"endsAt": "2027-03-31T00:00:00-04:00",
"windowTimeZone": "America/New_York",
"requiredAttributes": [
"identity.samePerson",
"appearance.bodyAndAge",
"appearance.expression",
"appearance.hair",
"appearance.pose",
"appearance.skinRetouch",
"context.endorsement"
],
"prohibitedChanges": [
"bodyAndAge",
"expression",
"hair",
"pose",
"skinRetouch",
"endorsement"
],
"neverExtras": [
"Do not show alcohol or tobacco."
],
"finalDeliverables": 24,
"isExclusive": false
},
"terms_digest": "sha256:39f18c8bef02b5226b9feaa92e526ed30b81b91650d8a10b503281b169f44431",
"canonicalization": "tlp-json-1",
"scope": {
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
],
"release_policy": "per_output_review"
},
"enforcement": [
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.channels",
"enforcement": "checked",
"stage": [
"check"
]
},
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.requiredAttributes",
"enforcement": "checked",
"stage": [
"generation"
]
},
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.neverExtras",
"enforcement": "checked",
"stage": [
"check",
"generation"
]
},
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.isExclusive",
"enforcement": "recorded",
"stage": []
}
],
"signatures": [
{
"party": "talent",
"account": null,
"name": "Maya Okafor",
"method": "passkey",
"signed_at": "2026-09-27T11:15:00Z"
},
{
"party": "licensee",
"account": "acct_2q8v1m3n7p4r6s9t0wxyhk5zba",
"name": "Ridgeline",
"method": "passkey",
"signed_at": "2026-09-28T16:02:00Z"
}
],
"document_url": "https://app.reflections.ai/l/K7Q4M2/revisions/1",
"created_at": "2026-09-27T11:15:00Z"
}{
"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"
}{
"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"
}{
"type": "https://docs.reflections.ai/errors/resource_not_found",
"title": "No such object",
"status": 404,
"code": "resource_not_found",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"type": "https://docs.reflections.ai/errors/rate_limited",
"title": "Too many requests",
"status": 429,
"code": "rate_limited",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "invalid_request",
"request_id": "<string>",
"detail": "<string>",
"param": "<string>",
"doc_url": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "invalid_request",
"request_id": "<string>",
"detail": "<string>",
"param": "<string>",
"doc_url": "<string>"
}Retrieve a license revision
Test mode available. Live mode unavailable. Uses fictional sandbox data only. See Sandbox for the supported forms and limits.
Returns one signed revision: the terms exactly as signed, their terms_digest, and a
normalized scope. Compute the digest yourself to confirm you hold the signed document.
Restricted keys need licenses:read.
: "${REFLECTIONS_KEY:?Set REFLECTIONS_KEY before running this example}"
curl --fail-with-body --max-time 30 'https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7' \
-H "Authorization: Bearer $REFLECTIONS_KEY" \
-H "Reflections-Version: 2026-10-15"import { env, exit } from "node:process";
const apiKey = env.REFLECTIONS_KEY;
if (!apiKey) throw new Error("Set REFLECTIONS_KEY before running this example");
const response = await fetch("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7", {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
"Reflections-Version": "2026-10-15",
},
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 os
from urllib.error import HTTPError
from urllib.request import Request, urlopen
apiKey = os.environ["REFLECTIONS_KEY"]
if not apiKey:
raise ValueError("Set REFLECTIONS_KEY before running this example")
headers = {
"Authorization": f"Bearer {apiKey}",
"Reflections-Version": "2026-10-15",
}
request = Request("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
method="GET", headers=headers)
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"
"time"
)
func main() {
apiKey := os.Getenv("REFLECTIONS_KEY")
if apiKey == "" {
panic("Set REFLECTIONS_KEY before running this example")
}
request, err := http.NewRequest("GET", "https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/revisions/lrv_p4r6s9t0wxyhk5zba2q8v1m3n7", nil)
if err != nil {
panic(err)
}
request.Header.Set("Authorization", "Bearer " + apiKey)
request.Header.Set("Reflections-Version", "2026-10-15")
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": "lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
"object": "license_revision",
"livemode": true,
"license": "lic_k5zba2q8v1m3n7p4r6s9t0wxyh",
"number": 1,
"status": "current",
"source_kind": "issue",
"terms": {
"releasePolicy": "perOutputTalentReview",
"adjustments": {
"reframe": true,
"backgroundExtension": true,
"lighting": true,
"textOverlay": true,
"bodyAndAge": false,
"expression": false,
"hair": false,
"pose": false,
"wardrobe": true,
"objects": true,
"skinRetouch": false,
"endorsement": false
},
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
],
"startsAt": "2026-10-01T00:00:00-04:00",
"endsAt": "2027-03-31T00:00:00-04:00",
"windowTimeZone": "America/New_York",
"requiredAttributes": [
"identity.samePerson",
"appearance.bodyAndAge",
"appearance.expression",
"appearance.hair",
"appearance.pose",
"appearance.skinRetouch",
"context.endorsement"
],
"prohibitedChanges": [
"bodyAndAge",
"expression",
"hair",
"pose",
"skinRetouch",
"endorsement"
],
"neverExtras": [
"Do not show alcohol or tobacco."
],
"finalDeliverables": 24,
"isExclusive": false
},
"terms_digest": "sha256:39f18c8bef02b5226b9feaa92e526ed30b81b91650d8a10b503281b169f44431",
"canonicalization": "tlp-json-1",
"scope": {
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
],
"release_policy": "per_output_review"
},
"enforcement": [
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.channels",
"enforcement": "checked",
"stage": [
"check"
]
},
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.requiredAttributes",
"enforcement": "checked",
"stage": [
"generation"
]
},
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.neverExtras",
"enforcement": "checked",
"stage": [
"check",
"generation"
]
},
{
"term": "license:lic_k5zba2q8v1m3n7p4r6s9t0wxyh/terms.isExclusive",
"enforcement": "recorded",
"stage": []
}
],
"signatures": [
{
"party": "talent",
"account": null,
"name": "Maya Okafor",
"method": "passkey",
"signed_at": "2026-09-27T11:15:00Z"
},
{
"party": "licensee",
"account": "acct_2q8v1m3n7p4r6s9t0wxyhk5zba",
"name": "Ridgeline",
"method": "passkey",
"signed_at": "2026-09-28T16:02:00Z"
}
],
"document_url": "https://app.reflections.ai/l/K7Q4M2/revisions/1",
"created_at": "2026-09-27T11:15:00Z"
}{
"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"
}{
"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"
}{
"type": "https://docs.reflections.ai/errors/resource_not_found",
"title": "No such object",
"status": 404,
"code": "resource_not_found",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"type": "https://docs.reflections.ai/errors/rate_limited",
"title": "Too many requests",
"status": 429,
"code": "rate_limited",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "invalid_request",
"request_id": "<string>",
"detail": "<string>",
"param": "<string>",
"doc_url": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "invalid_request",
"request_id": "<string>",
"detail": "<string>",
"param": "<string>",
"doc_url": "<string>"
}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}$Path Parameters
The license's ID.
^lic_[0-9a-hjkmnp-tv-z]{26}$The revision's ID, such as the license's current_revision or pending_revision.
^lrv_[0-9a-hjkmnp-tv-z]{26}$Response
The revision.
Unique identifier for the revision, lrv_….
^lrv_[0-9a-hjkmnp-tv-z]{26}$Always license_revision.
"license_revision"true for a live-mode revision, false for a test-mode one.
The license the revision belongs to.
^lic_[0-9a-hjkmnp-tv-z]{26}$The revision's position in its license, from 1 for the revision signed with the license.
x >= 1Where the revision stands. New checks are decided under the current revision only.
pending_acceptance, current, superseded, declined What produced the revision. issue: signed with the license. change_request: a change
the licensee asked for. amend: an amendment from the talent's side. renew: a
renewal, such as a new window.
issue, change_request, amend, renew The signed document, exactly as signed, with its own camelCase field names. Its
canonical form digests to terms_digest.
sha256: and the hex SHA-256 of terms in tlp-json-1 canonical form. Recompute it to
confirm you hold the signed document.
^sha256:[0-9a-f]{64}$The canonical JSON form the digest is computed over: UTF-8, object keys sorted by code point, no insignificant whitespace. Defined in the Standard under Tokens, canonical form.
"tlp-json-1"terms in normalized, snake_case form, for your code to read. Hash terms, never
scope.
Show child attributes
Show child attributes
Each term with its class: checked terms are enforced at the stages listed, recorded
terms are signed and shown only.
Show child attributes
Show child attributes
The talent's side signs first. The licensee's signature is added when it accepts.
Show child attributes
Show child attributes
When the talent's side signed the revision.
The signed document as a person reads it.