Protocol reference. Reuse and idempotency can be tested against fictional fixtures. The name
index, revocation feed, license events and production availability targets below are not
implemented by the current sandbox.
Start with the runnable quickstart and sandbox support matrix.
allow lets you generate a named talent, and nothing you cache
outlives a revocation.
What you may cache
Platforms that cache any decision read the revocation feed at least
every 60 seconds, in addition to webhooks.
A suspension is not a revocation and is not in the feed: there is no revocation object and nothing
to acknowledge. When you receive
license.suspended, drop every cached decision under
that license. Until license.resumed, checks deny with license_suspended, open sessions end,
and renewals fail with 409 session_not_active.
Held outputs stay held, and outputs already released are unaffected.
Reuse windows
Some products make many generations for one user in a few minutes: a text-to-speech app reading lines, an image tool producing variations. Ask for a reuse window so one decision covers them:use, for the same talent, model and end_user,
until authorization.expires_at or until authorization.generations_used reaches
max_generations. Every output in the window is still submitted as a generation, where its words
or pixels are checked against the license. A new user, a new use or a new model needs a new check.
Never turn a non-allow into an allow
Caching goes wrong when something that is not anallow is treated as one.
- An error, a timeout or a
503is not a decision. Generate nothing for a named talent. - A cached
denystays adenyfor that request. When it ages out of your cache, check again; do not assume the answer changed. escalateis not anallow. Wait forcheck.resolved.- A resolution with
status: none, or no local match in the name index, is not permission. Only a check resolves indirect references, such as “the runner from Ridgeline’s spring campaign”. - An
allowcovers its own request. A cached authorization never covers a different prompt, reference, model or use, unless it carries a reuse window for that use.
Retry safely
EveryPOST takes an Idempotency-Key, kept for 24 hours. Generate one key per logical request,
store it with the request, and reuse it on every retry.
deny or escalate is a 200 with a decision, not an error. Never retry a decision to get a
different one.
When Reflections is unavailable
Named talent: fail closed. If a check cannot complete for a request that names a talent intalent, matches the name index, or carries a reference or voice sample, do not generate. The one
exception is an authorization you already hold: while it has not expired and has generations left,
you may use it for the request it covers. Tell your user the request cannot run right now; do not
fall back to generating without a decision.
Requests that name and match no one: you may proceed. A request that names no talent, matches no
entry in your current name index, and
carries no reference or voice sample may be generated and delivered while the check cannot complete.
Nothing is sent later. With no index, or one past its expires_at, every request fails closed.
Live sessions may continue until the current session token expires, at most 5 minutes, never
past it. See Real-time sessions.
Revocations wait for you. When calls succeed again, read the feed from your stored cursor, and
any license.suspended events you missed with
GET /v1/events, before you serve any cached decision. The
acknowledgement deadlines do not move: acknowledge every action but withdraw_outputs by
acknowledge_by, and withdraw_outputs by post_revocation.withdraw_by.
The proposed production availability target for checks is 99.95% per month. It is not a confirmed
service commitment or a measured sandbox result. Current status and incidents are on
status.reflections.ai.
When evaluation is unavailable
Sometimes Reflections is up but cannot finish evaluating a rule. The check then returnsescalate
with escalation.reason: "evaluation_unavailable", or deny with review_required if you sent
on_escalate: "deny". At the generation, a rule the talent wrote that could not be read is recorded
in unchecked_terms and the output is delivered; a protected attribute that could not be read
denies the output.
In test mode, rfl_test_unavailable in a check’s text forces the evaluation_unavailable path.
Related
Failure modes
Fail-closed and fail-open rules in one place.
Idempotency
Keys, replay, and the three outcomes.
Rate limits
Limits, headers and raising them.
Handle revocations
The feed that invalidates your caches.