Migrating to verified voice-cloning consent

Move from the consent field to the consent-challenge flow, pinned to Speechify-Version 2026-09-13

Creating a cloned voice now proves the speaker agreed, in place of the consent object you used to send. If your integration still posts a consent form field to POST /v1/voices, this page moves you to the verified consent-challenge flow. The change was announced in the changelog.

The old consent form field is deprecated as of 13 August 2026 and will be switched off. If your POST /v1/voices sends a consent string (JSON with fullName and email), migrate to the consent-challenge flow below and re-pin Speechify-Version: 2026-09-13. The switch-off date is announced in the changelog and to affected workspaces ahead of time — deliberately sooner than the standard 12-month sunset, because cloning a voice without checking the speaker agreed is a safety liability, not just an old shape. Existing cloned voices are unaffected. Can’t migrate in time? Contact support and we’ll work out an extension for your workspace.

What is changing

Consent used to be an assertion — a consent object carrying the speaker’s fullName and email. It is now verified: the speaker reads a phrase we issue, and you send that recording as the consent record.

Old (version 2026-08-07 and earlier)New (version 2026-09-13)
Proof of consentconsent form field: { "fullName": …, "email": … }A consent challenge the speaker reads aloud
POST /v1/voices fieldsconsentconsent_challenge_id + consent_recording (both required); consent is gone
Calls to clone a voiceone (POST /v1/voices)two (POST /v1/voices/consent-challenges, then POST /v1/voices)

A pinned default never moves on its own, so migrating means re-pinning Speechify-Version: 2026-09-13. Workspaces created on or after that date are on the verified flow already.

Are you affected?

You are affected if POST /v1/voices sends a consent form field. If your create already sends consent_challenge_id and consent_recording, you are on the new flow — nothing to do.

The new flow

Cloning is now two calls: a consent leg that proves agreement, then the create you already make.

When your speaker is ready to record, create a challenge with their full_name. It returns a phrase and an id.

POST
/v1/voices/consent-challenges
1curl -X POST https://api.speechify.ai/v1/voices/consent-challenges \
2 -H "Authorization: Bearer <token>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "full_name": "Jane Doe"
6}'

Show the phrase to the speaker exactly as it comes back and record them reading it aloud. A challenge is single use, bound to your workspace, and short-lived — create it at record time, not at the start of your flow. If it expires, create another and record again.

2. Create the voice with the recording

Send the recording as consent_recording alongside consent_challenge_id. Speechify transcribes it, checks it against the phrase it issued, and keeps it as the voice’s consent record.

POST
/v1/voices
1curl -X POST https://api.speechify.ai/v1/voices \
2 -H "Authorization: Bearer <token>" \
3 -H "Content-Type: multipart/form-data" \
4 -F avatar=@<file1> \
5 -F consent_challenge_id="string" \
6 -F consent_recording=@string \
7 -F gender="male" \
8 -F name="string" \
9 -F sample=@string

What moves, what’s gone

  • full_name moves from the old consent object onto the challenge call.
  • email is dropped — nothing replaces it.
  • consent_challenge_id and consent_recording become required on POST /v1/voices.
  • The endpoint, your existing voice ids, and every synthesis call are unchanged.

Handle the new refusals

Three new errors share HTTP 422, so branch on the code, not the status:

CodeMeansFix
consent_phrase_mismatchThe phrase was misreadHave the speaker read it again
consent_speaker_mismatchThe recording isn’t the voice being clonedThe consenting speaker must be the one being cloned
consent_recording_unusableSilence, too little speech, or an unreadable fileRecord it again

If you use an SDK

Each SDK release sends its own build date as the default version, so upgrading to an SDK published on or after 2026-09-13 moves you to the new flow — a deliberate break, not a silent one: consent_challenge_id and consent_recording are required arguments and the consent argument is gone, so the call stops compiling rather than failing at runtime. To upgrade the SDK without migrating yet, pass the old version explicitly:

1client = Speechify(token=os.environ["SPEECHIFY_API_KEY"], version="2026-08-07")

Migration checklist

1

Re-pin the version

Set Speechify-Version: 2026-09-13 (or pass it to your SDK client). A pinned default does not move on its own.

3

Send the recording on create

Replace the consent field with consent_challenge_id and consent_recording. Drop email — it has no replacement.

4

Handle the 422s

Branch on consent_phrase_mismatch, consent_speaker_mismatch, and consent_recording_unusable.

See also