Skip to the content
Menu: Moving to 2026-10-01

Moving to 2026-10-01

Keys made from 2026-10-01 are on the new contract already: nothing to do. This page is for integrations whose keys were made before, on 2026-07-08. They keep working as they are: move when you are ready, within the support window (see Versions).

The privacy and security changes of the same release apply to every contract, whether you move or not: see the changelog.

How to move#

  1. Read what changes below, and find the code that relies on it.
  2. Try it: send Zentiq-Version: 2026-10-01 on your requests (an SDK 1.x does this by default). The answers come in the new contract; your key stays pinned to the old one.
  3. Move your webhooks: PATCH /v1/webhooks/{id} with { "apiVersion": "2026-10-01" }. Deliveries switch to the new envelope from the next event. Update your receiver first.
  4. Make a new key in the console (with only the scopes it needs), switch your servers to it, then revoke the old one.

What changes#

AreaOn 2026-07-08On 2026-10-01What to change
Plan refusals403 { "error": "upgrade_required", "feature", "plan", "message", "limit"? }403 { "error": { "code": "upgrade_required", "message", "details": { "feature", "plan", "limit"? } } }Read error.code and error.details.
Portal and subject idsBare ids in answers and eventsportal_… and sub_… (bare ids still accepted on input)Store the prefixed ids; don't parse them.
A refused portal publish200 with the draft unchanged and publishRefused422 go_live_refused with details.problemsHandle the error. (Creating with publish: true stays 201 with publishRefused.)
Who speaks on a portalFace and voice by first nameBy id (avatarId, voiceId); names still accepted, but deprecatedSend ids.
Webhook envelope{ id, type, createdAt, data }Adds apiVersion and organizationId; every id in data prefixed; visitor details on leads, bookings and hand-offs under contact, leadScore renamed leadBand, inboxItemId addedUpdate your receiver, then move the webhook.
Scopessessions:read includes transcripts; portals:write includes embed tokens and publishing; personas:* includes duos and widgets; webhooks:manage includes the event logEach is its own scope (transcripts:read, embed:write, portals:publish, duos:*, widgets:*, content:*, events:read)Give new keys the scopes they use. Old keys keep what they had.
Full-access keysNever reach candidates, people, the inbox or consent recordsA new full-access key reaches them all, except candidates:data and consents:* (added by name)Nothing, unless you want an old key to reach them: an owner adds them by name.
Persona voice tiersettings.engine and settings.globalVoice can be writtenSet from the voice, read-onlyChoose the voice (voiceId); stop sending engine.
Refused transcripts403 forbidden403 candidate_interview or 403 learner_conversationMatch on the new codes.
Too large413 invalid_request413 too_largeMatch on the new code.
Summaries on getSession and sessionAnalyticsWith sessions:readNeed transcripts:readAdd the scope to keys that read summaries.

The SDKs#

SDK 1.x speaks 2026-10-01, and reads both contracts' error shapes. Moving from @zentiq/node 0.x:

  • Every operation is now a method named after its operation id: personas.create(…) is createPersona(…), sessions.createToken(…) is createSessionToken(…), knowledge.documents.list(id) is listDocuments(id). The reference shows each one.
  • An Idempotency-Key is sent for you on every operation that takes one (the reference marks them); pass your own as { idempotencyKey } in the last argument.
  • Errors are typed by kind (GoLiveRefusedError, VersionConflictError, …), still all ZentiqErrors.

Each package's own changelog lists the rest.