/v1 endpoint:
Two more pieces draw an agent’s mascot, its animated face, in your
own web page or Flutter app. See Mascot widgets.
Both retry rate limits, page through lists, send an idempotency key on calls,
test calls and top-ups, and raise errors carrying the API’s stable
code,
the request_id to quote and the doc_url to read. A test in each compares
its method table against the OpenAPI document in both
directions, so an endpoint cannot go unwrapped and a method cannot claim an
endpoint that does not exist.
Every other language works against the same HTTP API and the same
OpenAPI document. Integrate has a fifteen-line
client in Node and in Python for anyone who would rather not add a dependency.
Quickstart
agents.create, calls.list,
sipTrunks.status, billing.createTopup. Eighteen resources, and a method for
each of the 100 /v1 endpoints.
Pagination
Lists are cursor-paginated. Iterate the page to walk every page; the cursor and your filters are carried along.Errors
Match oncode. The message is written for people and may be reworded.
Idempotency
calls.create, agents.testCall, phoneNumbers.purchase and
billing.createTopup require an idempotency key. The SDKs generate one per call and reuse it
across their own retries, so a network timeout never becomes two phone calls.
Pass your own to make a retry from your side safe too.
Retries
The two SDKs share one policy:429: retried afterRetry-After, capped at ten seconds, up tomaxRetries(default 2). Rate-limited requests are never charged.- Network failures, timeouts and
502–504: retried only forGETand for requests carrying an idempotency key.DELETE,PATCHand unkeyedPOST(hanging up, starting or pausing a campaign, testing a trunk, rotating a key) are never repeated when the outcome is unknown. 500and other4xx: never retried.
Pinning a version
Wixzel-Version header, so an upgrade is something you do rather
than something that happens to you.
Options
Both expose an escape hatch,
client.request(method, path, …), that reaches
an endpoint the SDK does not model yet with the same auth, retries and error
handling.
In the browser and in Flutter
To put an agent in the page or app (a voice conversation with no phone line), mint a session on your server and connect from the client withwixzel-voice/realtime (browser) or RealtimeConnection (Dart). See
Realtime: web and mobile.
The API’s CORS policy does not yet expose Retry-After, X-Wixzel-Balance
or Idempotent-Replay to page scripts, so those read as empty in a browser.
Everything else works.
Mascot widgets
Every agent has a mascot: a small JSON spec of a shape, two eyes and a smile, drawn live. These two packages draw it in your own page or app, with the same runtime the share link, the website widget and the Wixzel Voice app use, so a mascot looks and moves the same everywhere. Both can lip-sync it to a realtime session.On the web: wixzel-voice/mascot
A subpath of the TypeScript SDK, from 0.10.0:
face.connect asks for the microphone, connects, and moves the mascot with
the call: thinking while it connects, listening while the user talks, and its
mouth in time with the agent’s audio. If you create the RealtimeSession
yourself, pass face.handlers(yourHandlers) to it instead.
Without agent or spec it draws the default green mascot. Pass
followPointer: true to make the eyes follow the pointer. DEFAULT_MASCOT, PRESETS,
normalizeSpec, MOVE_NAMES and the Mascot class are exported too. The main
wixzel-voice import does not load any of this, so server code pays nothing
for it.
In Flutter: wixzel_voice_flutter
Flutter widgets for the mascot, on pub.dev.
It works with the wixzel_voice Dart SDK and needs Flutter 3.27 or newer.
MascotRealtimeLink makes the mascot listen, think and talk in time with the
agent’s audio. It does not play or record audio: your app sends the
microphone with conn.sendAudio and plays the RealtimeAudio events, as in
Realtime: In Flutter or Dart. Pass each
microphone frame to link.micAudio(frame) too, and the mascot leans in while
the user talks.
The eyes follow the phone’s tilt (
followTilt, on by default), and a mascot
animates only while it is on screen.
Coming from wixzel-phone or wixzel_phone
Up to 0.3.0 the SDKs were published as wixzel-phone on npm and
wixzel_phone on pub.dev, from when the product was called Wixzel Phone. From
0.4.0 they are wixzel-voice and wixzel_voice. To move, change the package
name and the import: from 'wixzel-voice', and in Dart
package:wixzel_voice/wixzel_voice.dart. WixzelPhone still works as a
deprecated alias of WixzelVoice, so the rest of your code can follow later.
The old packages keep working where they are. They call api.phone.wixzel.com,
which serves the same API as api.voice.wixzel.com and always will.
Source
- TypeScript SDK:
wixzel-voiceon npm · source - Dart SDK:
wixzel_voiceon pub.dev · source - Flutter mascot widgets:
wixzel_voice_flutteron pub.dev - Issues and pull requests: aqeelshamz/wixzel-voice-sdks
- Building with an AI agent instead? See the MCP server.

