The HTTP API
One route accepts an API key rather than a console session, and it does one thing: start a call.
POST https://app.voqalize.com/api/v1/sessions.connectAuthorization: Bearer sk_…Content-Type: application/jsonIt answers with the pipecat transport’s argument and nothing else —
webrtc_request_params and session_id. Relay that body to the browser
verbatim: it is what startBotAndConnect takes, so there is no field to pick
out and no object to rebuild.
Everything else — creating an agent, pointing its brain_url at your route,
minting and revoking keys, listing sessions, reading logs and usage — is the
MCP server, authenticated over OAuth.
The body
Section titled “The body”It is strict: an undeclared top-level key is a 422 naming it, rather than a
session that quietly runs on defaults.
| Field | ||
|---|---|---|
agent_id | required | Which agent answers. The key is scoped to it. |
init | optional | The opaque blob your brain reads as session.init. Same word at every hop. Send identifiers, not personal data — it is stored on the session record. |
config | optional | This call’s tts, stt and idle, plus record. Parsed as canonical proto3 JSON, so a bad field or an unservable language is a 400 naming it — see error codes. |
display_name | optional | A label for your own console and lists. |
metadata | optional | Your own flat string map for correlating a call with your systems. At most 10 keys, each value at most 256 characters. |
Which key signs the request, how a publishable key differs, and what the browser does with the response are all on connect a browser — that page owns the handshake and this one does not repeat it.
Start one call; there is no second step
Section titled “Start one call; there is no second step”There was once a create_meeting then start_meeting pair. It is gone: nothing
ever created a connection and then declined to use it, and the gap between them
was a state nobody guarded.
The route was called sessions.create until 2026-08-26. That name is gone,
not aliased: it answers 404. If you find it in an older example, change the
word — the body and the credential are unchanged, and the response is the
connect params rather than the whole session record every caller had to dig
through. If you want the record too, read it back with
get_session — over MCP or in the console, where
reads belong.
Why management is MCP and not a bearer key
Section titled “Why management is MCP and not a bearer key”The audience for a management API is a developer and the developer’s coding agent, and MCP is the surface an agent already holds: the tools describe themselves, the auth is interactive and revocable, and there is no long-lived credential sitting in an environment variable to leak. It is rate limited at 120 tool calls per minute per tenant.
The obvious alternative is a tenant-scoped bearer key. We had one, called ak_,
and removed it on 2026-08-12.
Every key now names an agent, of every kind. ak_ did not, which meant a
credential could start a session for any agent in the tenant — so a key
baked into one public demo page could spend on every other agent that tenant
owned. Nothing was narrowing it. A credential that names no resource is one
whose blast radius can only be discovered by reading code.
Reintroducing a bearer key for management reintroduces exactly that: the operations a management API is for — create an agent, mint a key — cannot be authorized by a credential issued by one agent, so such a key has to be tenant-wide by construction. It would be the same key, with the same reach, back under a different name.
The OpenAPI document is generated by the service and served in development only, for the same reason: publishing a schema for routes whose only credential is a console cookie describes a surface nobody can call.
If you need HTTP access, ask
Section titled “If you need HTTP access, ask”This is a decision about defaults, not a refusal. If your integration genuinely cannot hold an OAuth client — a CI job that provisions agents, a product creating tenants on behalf of its own customers, a stack where MCP is not available — HTTP access can be enabled for your account. Ask us, and tell us which operations you need; the narrower the answer, the faster it is.
What we will not do is hand every account a tenant-wide key by default and call it convenience.
Read next
Section titled “Read next”- The MCP server — the management surface, tool by tool.
- Connect a browser — the handshake, and which key to hold.
- Keys —
sk_andpk_, and how rotation works. - Usage and limits — the counters behind the calls.