# 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_RESUME_LICENSE_IDEMPOTENCY_KEY:?Set REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY before running this example}"
curl --fail-with-body --max-time 30 -X POST 'https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume' \
-H "Authorization: Bearer $REFLECTIONS_KEY" \
-H "Reflections-Version: 2026-10-15" \
-H "Idempotency-Key: $REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
--data-raw '{
"note": "Review complete. Placements may continue."
}'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_RESUME_LICENSE_IDEMPOTENCY_KEY;
if (!idempotencyKey) throw new Error("Set REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY before running this example");
const response = await fetch("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Reflections-Version": "2026-10-15",
"Idempotency-Key": idempotencyKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"note": "Review complete. Placements may continue."
}),
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_RESUME_LICENSE_IDEMPOTENCY_KEY"]
if not idempotencyKey:
raise ValueError("Set REFLECTIONS_RESUME_LICENSE_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({"note": "Review complete. Placements may continue."}).encode("utf-8")
request = Request("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume",
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_RESUME_LICENSE_IDEMPOTENCY_KEY")
if idempotencyKey == "" {
panic("Set REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY before running this example")
}
body := strings.NewReader(`{
"note": "Review complete. Placements may continue."
}`)
request, err := http.NewRequest("POST", "https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume", 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": "lic_k5zba2q8v1m3n7p4r6s9t0wxyh",
"object": "license",
"livemode": true,
"status": "active",
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"licensee": "acct_2q8v1m3n7p4r6s9t0wxyhk5zba",
"issued_by": {
"party": "talent",
"account": null
},
"handle": "K7Q4M2",
"current_revision": "lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
"revision_number": 1,
"pending_revision": null,
"terms_digest": "sha256:39f18c8bef02b5226b9feaa92e526ed30b81b91650d8a10b503281b169f44431",
"scope": {
"facets": [
"fct_5zba2q8v1m3n7p4r6s9t0wxyhk"
],
"modalities": [
"image"
],
"kinds": [
"depiction"
],
"purposes": [
"advertising"
],
"commercial": true,
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
],
"window": {
"starts_at": "2026-10-01T00:00:00-04:00",
"ends_at": "2027-03-31T00:00:00-04:00",
"time_zone": "America/New_York"
},
"adjustments": {
"reframe": true,
"background_extension": true,
"lighting": true,
"text_overlay": true,
"body_and_age": false,
"expression": false,
"hair": false,
"pose": false,
"wardrobe": true,
"objects": true,
"skin_retouch": false,
"endorsement": false
},
"prohibited_changes": [
"body_and_age",
"expression",
"hair",
"pose",
"skin_retouch",
"endorsement"
],
"required_attributes": [
"identity.samePerson",
"appearance.bodyAndAge",
"appearance.expression",
"appearance.hair",
"appearance.pose",
"appearance.skinRetouch",
"context.endorsement"
],
"rules": {
"never": [
"Do not show alcohol or tobacco."
],
"always": [],
"brief": null
},
"release_policy": "per_output_review",
"escalation_window": "P7D",
"final_deliverables": 24,
"sessions": {
"permitted": false
},
"material_access": [],
"platforms": {
"mode": "any_connected",
"accounts": []
},
"sublicense": "none",
"training": "prohibited",
"disclosure": "brand",
"attribution": null,
"post_revocation": {
"policy": "retain"
},
"exclusivity": {
"exclusive": false,
"category": null
},
"conflicts": [],
"compensation": {
"type": "per_unit",
"per_unit": {
"units": "placements",
"rate": {
"amount": 25000,
"currency": "usd"
},
"per": 1
},
"minimum": {
"amount": 500000,
"currency": "usd"
},
"schedule": "monthly"
}
},
"acceptance_url": null,
"accepted_at": "2026-09-28T16:02:00Z",
"suspended_at": null,
"revoked_at": null,
"declined_at": null,
"metadata": {},
"created_at": "2026-09-27T11:15:00Z"
}{
"type": "https://docs.reflections.ai/errors/parameter_invalid",
"title": "A parameter is invalid",
"status": 400,
"code": "parameter_invalid",
"param": "use.territories[1]",
"detail": "\"UK\" is not an ISO 3166-1 alpha-2 code. Use \"GB\".",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"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/mandate_required",
"title": "No mandate with the needed power",
"status": 403,
"code": "mandate_required",
"detail": "Your mandate for tal_9t0wxyhk5zba2q8v1m3n7p4r6s does not include review_outputs.",
"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/idempotency_key_in_use",
"title": "A request with this key is still running",
"status": 409,
"code": "idempotency_key_in_use",
"detail": "Retry with the same key after a short wait.",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"type": "https://docs.reflections.ai/errors/idempotency_key_reused",
"title": "This key was used for a different request",
"status": 422,
"code": "idempotency_key_reused",
"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>"
}Resume a license
Planned contract — unavailable in test and live modes. This operation is a protocol reference, not a callable endpoint. Start with the working sandbox quickstart.
Ends a suspension. Needs a mandate with revoke for the talent. Checks may allow uses
under the license again, and the licensee and connected platforms receive
license.resumed. Sessions that ended stay ended.
Restricted keys need licenses: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_RESUME_LICENSE_IDEMPOTENCY_KEY:?Set REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY before running this example}"
curl --fail-with-body --max-time 30 -X POST 'https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume' \
-H "Authorization: Bearer $REFLECTIONS_KEY" \
-H "Reflections-Version: 2026-10-15" \
-H "Idempotency-Key: $REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
--data-raw '{
"note": "Review complete. Placements may continue."
}'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_RESUME_LICENSE_IDEMPOTENCY_KEY;
if (!idempotencyKey) throw new Error("Set REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY before running this example");
const response = await fetch("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Reflections-Version": "2026-10-15",
"Idempotency-Key": idempotencyKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"note": "Review complete. Placements may continue."
}),
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_RESUME_LICENSE_IDEMPOTENCY_KEY"]
if not idempotencyKey:
raise ValueError("Set REFLECTIONS_RESUME_LICENSE_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({"note": "Review complete. Placements may continue."}).encode("utf-8")
request = Request("https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume",
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_RESUME_LICENSE_IDEMPOTENCY_KEY")
if idempotencyKey == "" {
panic("Set REFLECTIONS_RESUME_LICENSE_IDEMPOTENCY_KEY before running this example")
}
body := strings.NewReader(`{
"note": "Review complete. Placements may continue."
}`)
request, err := http.NewRequest("POST", "https://app.reflections.ai/v1/licenses/lic_k5zba2q8v1m3n7p4r6s9t0wxyh/resume", 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": "lic_k5zba2q8v1m3n7p4r6s9t0wxyh",
"object": "license",
"livemode": true,
"status": "active",
"talent": "tal_9t0wxyhk5zba2q8v1m3n7p4r6s",
"licensee": "acct_2q8v1m3n7p4r6s9t0wxyhk5zba",
"issued_by": {
"party": "talent",
"account": null
},
"handle": "K7Q4M2",
"current_revision": "lrv_p4r6s9t0wxyhk5zba2q8v1m3n7",
"revision_number": 1,
"pending_revision": null,
"terms_digest": "sha256:39f18c8bef02b5226b9feaa92e526ed30b81b91650d8a10b503281b169f44431",
"scope": {
"facets": [
"fct_5zba2q8v1m3n7p4r6s9t0wxyhk"
],
"modalities": [
"image"
],
"kinds": [
"depiction"
],
"purposes": [
"advertising"
],
"commercial": true,
"channels": [
"social",
"web"
],
"territories": [
"US",
"CA"
],
"window": {
"starts_at": "2026-10-01T00:00:00-04:00",
"ends_at": "2027-03-31T00:00:00-04:00",
"time_zone": "America/New_York"
},
"adjustments": {
"reframe": true,
"background_extension": true,
"lighting": true,
"text_overlay": true,
"body_and_age": false,
"expression": false,
"hair": false,
"pose": false,
"wardrobe": true,
"objects": true,
"skin_retouch": false,
"endorsement": false
},
"prohibited_changes": [
"body_and_age",
"expression",
"hair",
"pose",
"skin_retouch",
"endorsement"
],
"required_attributes": [
"identity.samePerson",
"appearance.bodyAndAge",
"appearance.expression",
"appearance.hair",
"appearance.pose",
"appearance.skinRetouch",
"context.endorsement"
],
"rules": {
"never": [
"Do not show alcohol or tobacco."
],
"always": [],
"brief": null
},
"release_policy": "per_output_review",
"escalation_window": "P7D",
"final_deliverables": 24,
"sessions": {
"permitted": false
},
"material_access": [],
"platforms": {
"mode": "any_connected",
"accounts": []
},
"sublicense": "none",
"training": "prohibited",
"disclosure": "brand",
"attribution": null,
"post_revocation": {
"policy": "retain"
},
"exclusivity": {
"exclusive": false,
"category": null
},
"conflicts": [],
"compensation": {
"type": "per_unit",
"per_unit": {
"units": "placements",
"rate": {
"amount": 25000,
"currency": "usd"
},
"per": 1
},
"minimum": {
"amount": 500000,
"currency": "usd"
},
"schedule": "monthly"
}
},
"acceptance_url": null,
"accepted_at": "2026-09-28T16:02:00Z",
"suspended_at": null,
"revoked_at": null,
"declined_at": null,
"metadata": {},
"created_at": "2026-09-27T11:15:00Z"
}{
"type": "https://docs.reflections.ai/errors/parameter_invalid",
"title": "A parameter is invalid",
"status": 400,
"code": "parameter_invalid",
"param": "use.territories[1]",
"detail": "\"UK\" is not an ISO 3166-1 alpha-2 code. Use \"GB\".",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"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/mandate_required",
"title": "No mandate with the needed power",
"status": 403,
"code": "mandate_required",
"detail": "Your mandate for tal_9t0wxyhk5zba2q8v1m3n7p4r6s does not include review_outputs.",
"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/idempotency_key_in_use",
"title": "A request with this key is still running",
"status": 409,
"code": "idempotency_key_in_use",
"detail": "Retry with the same key after a short wait.",
"request_id": "req_8f2k4m6p8r0t2v4x6z8b0d2f4h"
}{
"type": "https://docs.reflections.ai/errors/idempotency_key_reused",
"title": "This key was used for a different request",
"status": 422,
"code": "idempotency_key_reused",
"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"
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.
255Path Parameters
The license's ID.
^lic_[0-9a-hjkmnp-tv-z]{26}$Body
Shown to the licensee on the license page.
1000Response
The active license.
Unique identifier for the license, lic_….
^lic_[0-9a-hjkmnp-tv-z]{26}$Always license.
"license"true for a live-mode license, false for a test-mode one.
Where the license is in its life. Checks are decided on its terms only while it is
active; under every other status they deny.
pending_acceptance, scheduled, active, suspended, expired, declined, revoked, void The talent who granted the license.
^tal_[0-9a-hjkmnp-tv-z]{26}$The account that holds the license and answers for every use made under it. Null on a
pending_acceptance license its talent reads before anyone accepts the invitation.
^acct_[0-9a-hjkmnp-tv-z]{26}$A six-character name for the license that people can read aloud, such as K7Q4M2.
^[0-9BCDFGHJKMNPQRSTVWXYZ]{6}$The revision in force. While the license is pending_acceptance, the first revision, waiting to be accepted.
^lrv_[0-9a-hjkmnp-tv-z]{26}$The number of current_revision, starting at 1.
x >= 1The terms of current_revision in normalized form. A pending revision does not change
it until the licensee accepts.
Show child attributes
Show child attributes
When the talent's side signed the first revision.
Who signed the first revision.
Show child attributes
Show child attributes
A new revision the talent's side signed, such as a change the licensee requested, an
amendment or a renewal, waiting for the licensee to accept it at acceptance_url.
current_revision stays in force until then.
^lrv_[0-9a-hjkmnp-tv-z]{26}$The digest of the current revision's signed terms. Checks, authorizations and receipts
decided under that revision carry the same value. A live read returns the digest of
the full signed terms, not a digest of the partial scope; live revision retrieval
and live decision endpoints remain planned.
^sha256:[0-9a-f]{64}$The hosted page where the licensee reads and accepts the license, or its pending_revision. Present while pending_acceptance, and while a revision is pending.
When the licensee accepted the license. null until then.
When the current suspension began. null unless the license is suspended.
When the license was revoked. null unless it is revoked.
When the licensee declined the license. null unless it is declined.
Key-value pairs stored on the license.
Show child attributes
Show child attributes