Skip to main content
Sandbox and protocol reference. Test escalations can be resolved with the sandbox helper and read by polling. Webhook delivery and a production human review queue are not available through this API. Start with the runnable quickstart and sandbox support matrix.
escalate means a person with authority has to decide before anything is generated or delivered. The response comes back at once; nobody waits on an open connection. Your product shows a pending state, learns the answer from a webhook or by polling, and acts on it.

What an escalation is

At the check, escalate means: do not generate yet. At the generation, it means: the output is held, and you deliver nothing until a reviewer releases it. Both carry an escalation object.
reviewer says who decides. Under a customer license it is the talent, or a representative with the review_outputs power. Under a platform license it is Reflections trust and safety, with a response target of one business day. A missing license never escalates. It is a deny with no_license and a license_request remedy.

Show a pending state

1

Store the check ID with the job

Keep check.id and escalation.expires_at next to your user’s job, so a webhook or a poll can find it later.
2

Tell the user what is happening

Say the request is waiting for approval and show the reason sentence as written. Show when it expires. Do not show a draft or a partial result: nothing has been generated.
3

Freeze the request

The answer covers exactly the request you escalated. If your user edits it, cancel the check and send a new one.

Listen for check.resolved

When the reviewer answers, or the escalation expires, your endpoint receives check.resolved with the check as it is now. The authorization in a resolved check has its own expires_at, like any other. Start the generation when the event arrives. escalation.note holds the reviewer’s note, if they wrote one.
jobs stands for your own job store. Webhooks arrive at least once, so make the handler safe to run twice.

Poll as a fallback

If you cannot receive webhooks, or one is late, read the check with GET /v1/checks/{check_id}. Poll at most once every 5 seconds while status is escalated, and slow down for escalations that take hours.

Cancel what you no longer need

When your user leaves, deletes the job or edits the request, cancel the check. The reviewer is told, and the check’s status becomes cancelled.
If the reviewer answered first, the call returns 409 escalation_closed. Read the check and act on its decision, or discard it. You can also cancel an allowed check to void its authorization early.

Interactive products: on_escalate: "deny"

A chat reply or a live voice call cannot wait days for a person. Send on_escalate: "deny" on every check from an interactive surface. Anything that would escalate returns deny at once:
The retry_with_hold remedy tells you the request could go to review. Offer that in a surface where waiting makes sense, such as a saved draft, and send it again with on_escalate: "hold". Sessions always behave this way.

Expiry

An escalation stays open for 7 days (P7D), or for the license’s shorter escalation_window. After escalation.expires_at, the check’s status becomes denied, with decision deny and the reason hold_expired, and you receive check.resolved. A check whose status is expired is a different case: it was allowed, and its authorization expired before you used it. Run a new check if you still need the output.

Held outputs at the generation

When a license has a person release every output, the generation returns decision: "escalate", status: "held" and escalation.reason: "release_review".
  • Keep the output private. If the generation carries a draft_watermark obligation, you may show a preview with the visible draft mark. Otherwise show nothing.
  • On generation.released, the generation carries its receipt. Embed it and deliver the clean output.
  • On generation.denied, discard it. Its status is denied, with review_declined when the reviewer declined it, or license_revoked when the license was revoked before release.
  • On generation.expired, discard it. Nobody released it in time: its status is expired, its decision deny and its reason review_expired. Held outputs expire after 7 days.
  • If your user no longer wants a held output, withdraw it. Its delivery returns to the license’s delivery limit.

Test it

In test mode, put rfl_test_escalate, rfl_test_unverifiable or rfl_test_unavailable in a text input to force each kind of escalation. Generations for Jonah Reyes (tal_4n6p8r0t2v4x6z8b0d2f4h6j8k) are held. Answer any of them with POST /v1/test_helpers/escalations/{escalation_id}/resolve, using allow, deny or expire.

Escalation

Who reviews, how long it takes, and what expiry means.

check.resolved

The event and its payload.

Submit outputs

Holds, releases and findings at the generation.

Sandbox

Force every escalation in test mode.