Planned design guide. Fictional voice checks can be tested, but this full workflow requires
file uploads and live sessions, which are not served by the current sandbox. No provider voice
is provisioned by these examples.
Start with the runnable quickstart and sandbox support matrix.
Speech lines
1
Export your test key
2
Check the first line with reuse
A text-to-speech product speaks many short lines for one user. Ask for The authorization covers 50 generations for this end user until it expires:For speech, apply
reuse so one decision
covers up to 50 lines over 15 minutes, and pass on_escalate: "deny" so your user never
waits on a person.generation_instructions to the words: do not send a line that breaks one.3
Speak and submit each line
Send each line to your voice provider with Speech up to 60 seconds returns its decision in the response:Embed
authorization.token, then submit the audio. Short
lines can be sent inline as base64 data. The sandbox limit is 7 MiB decoded bytes in a
10 MiB JSON body; the protocol’s 10 MB inline limit is a future target. Under reuse, leave out candidate_index:
each line is its own generation and counts once against max_generations. Send the line’s
words as transcript; later lines are checked on their own audio and words.c2pa in the audio file’s C2PA manifest, write the disclosure text into its metadata,
and play it. When generations_used reaches 50 or the authorization expires, run a new check:
a generation past either returns 409 authorization_consumed or 409 check_expired.4
See what an interactive deny looks like
Run the check again with Tell your user the line cannot be spoken, using
rfl_test_escalate anywhere in the script. Without on_escalate
this would escalate to a person. With on_escalate: "deny" it returns at once:reasons[].sentence. retry_with_hold means
the same request with on_escalate: "hold" would go to a reviewer instead.Live session
A session runs one check at the start, then keeps a short-lived token alive. The token expires 5 minutes after issue; you renew it every 60 seconds, submit samples of what the voice says, and stop within one second if Reflections terminates the session.1
Create a session
status is denied, no token is issued and reasons say why. Otherwise show the
disclosure on screen, add the instructions to your voice model’s system prompt, and give the
provider the session token.2
Connect to the stream
The stream pushes The first message is
session.terminated the moment it happens, so connect before any audio
plays. From a client, authenticate with the session token as a WebSocket subprotocol; from a
server, you can send your secret key in Authorization instead. Send a ping every 25
seconds when nothing else is flowing, inside the 30-second limit.session.ready. session.warning arrives before something ends the
session: renewal_due, sample_overdue, license_ending or max_duration, each with an
act_by time.3
Renew every 60 seconds
Each renewal returns a fresh token. Pass it to your voice provider. A renewal fails with
409 session_not_active once the license is revoked, suspended or ends, or the session was
terminated: stop output at once. On a network error, 429 or 5xx, keep retrying, and stop
when the current token expires if no renewal succeeded.4
Submit samples
sampling sets the minimum: an audio window of at most 15 seconds for every 15 seconds of
speech, and the words of every turn. Audio goes as base64 WAV or Ogg, up to 2 MB per sample;
16 kHz mono WAV keeps a 15-second window well under that.5
Handle termination
Submit a transcript sample whose text contains and the stream pushes:Stop output within one second of whichever arrives first. Do not renew again. The
rfl_test_terminate. The sample is denied:session.terminated webhook reports the same termination; read data.object.termination. To
test a license ending instead, suspend the license with the
test helper and action: "suspend": the stream
carries license_suspended. Resume it with action: "resume" so the fixture keeps working.6
End the session
End every session when the call is over, including one Reflections terminated.This session was terminated, so it keeps that status and its
termination. A session your
user ends returns status: "ended".7
Report usage
The For the session, A rejected record carries
usage_report obligations ask for seconds within a day. Report the speech lines and the
session together: each record names the generation or session it settles.quantity is the seconds of speech it generated in her voice. Each record is
accepted or rejected on its own:rejection.code, such as exceeds_observed when you report more
than Reflections recorded. Send a correction as a new record with correction_of.Next
Voice platforms
Provider-held voices, scripts and sessions in production.
Real-time sessions
Renewal, sampling, termination and the one-second stop.
Session stream
Every message on the WebSocket.
Reporting usage
Batching, units, reconciliation and corrections.