API reference
Build a voice channel in three calls.
VoiceKernel is the voice infrastructure layer for regulated enterprise.
Create agents, place calls, ground answers in your own knowledge, and stream
every event into your systems - with tenant isolation, an audit trail and
signed webhooks as defaults rather than add-ons.
97operations covered
202models
20voice providers
26action types
Quickstart
Every VoiceKernel object is an API call. Authenticate with a key from
Settings → API keys, then create an agent and put it on a line.
1 · Create an agent
# An agent is a prompt, a model, a voice and the actions it may call.
curl http://localhost:8080/v1/agents \
-H "Authorization: Bearer $VK_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Card disputes",
"systemPrompt": "You are a card disputes specialist for a retail bank. Answer only from the supplied policy documents. If unsure, escalate to a human.",
"firstMessage": "Thanks for calling - how can I help with your card today?",
"model": { "provider": "anthropic", "model": "claude-sonnet-5", "temperature": 0.3 },
"voice": { "provider": "11labs", "voiceId": "matilda" },
"transcriber": { "provider": "deepgram", "model": "nova-3" }
}'
2 · Place a call
curl http://localhost:8080/v1/calls \
-H "Authorization: Bearer $VK_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ "to": "+61400000000", "agentId": "asst_…", "metadata": { "ticket": "INC-9912" } }'
3 · Receive the outcome
curl http://localhost:8080/v1/webhook-endpoints \
-H "Authorization: Bearer $VK_KEY" \
-d '{ "url": "https://crm.example.com/hooks/voicekernel", "events": ["call.ended"] }'
# The response carries the signing secret, once. Store it.
Switching models never touches the prompt. The upstream provider stores
the system prompt inside its model object, so a naive patch clobbers it.
PUT /v1/agents/:id/model preserves it.
Authentication & conventions
Pass your key as a bearer token. X-API-Key is also accepted, for
gateways that will not forward Authorization.
Authorization: Bearer vk_live_…
Keys are scoped. A key that lacks a scope is refused with 403 and told
which scope it needed - it does not silently return an empty list.
*agents:readagents:writecalls:readcalls:writephone-numbers:readphone-numbers:writetools:readtools:writefiles:readfiles:writesquads:readsquads:writecampaigns:readcampaigns:writechats:readchats:writesessions:readsessions:writeevals:readevals:writeanalytics:readanalytics:writewebhooks:readwebhooks:writeprovider:passthrough
Errors
Every failure has the same shape. Quote requestId when reporting a problem.
{
"error": {
"type": "permission_error",
"code": "permission_denied",
"message": "This API key lacks the \"agents:write\" scope.",
"requestId": "req_8f21…"
}
}
Idempotency
Send Idempotency-Key on any POST or PATCH. A replay returns the
original response rather than repeating the operation - so a timeout you retry
cannot place a second call. Reusing a key with a different body is a
409, because that is a client bug worth surfacing loudly.
Pagination
?limit=&offset=. Responses carry { data, pagination }.
Rate limits
X-RateLimit-Limit, -Remaining and -Reset on every response.
A 429 carries Retry-After.
SDKs
TypeScript available
npm install @voicekernel/sdk
import { VoiceKernel } from '@voicekernel/sdk';
const vk = new VoiceKernel({ apiKey: process.env.VK_API_KEY });
const agent = await vk.agents.create({
name: 'Card disputes',
systemPrompt: 'You are a card disputes specialist…',
model: { provider: 'anthropic', model: 'claude-sonnet-5' },
});
// An idempotency key is attached automatically - a retried timeout
// must never place a second call.
await vk.calls.create({ to: '+61400000000', agentId: agent.id });
// Walks every page.
for await (const call of vk.calls.iterate({ status: 'ended' })) { … }
// Anything not wrapped by a typed method.
await vk.provider('GET', '/assistant/abc123');
verifyWebhook() throws rather than returning false - a caller who
forgets to check a boolean silently accepts forgeries.
Python not yet available
Go not yet available
Until those ship, generate a client from the
OpenAPI document.
Webhooks
Register an endpoint and VoiceKernel posts every event to it, signed, retried
with exponential backoff, and individually replayable from the console.
Events
call.startedcall.endedcall.updatedcall.transcriptcall.status-updatecall.speech-updatecall.hangcall.analysis.completedtool.calledassistant.requestedtransfer.destination.requestedagent.createdagent.updatedagent.deletedbilling.threshold
Subscribe to * for everything, or a prefix like call.*.
Verifying a delivery
This is the security-critical half of the integration. Without it, anyone who
learns your endpoint URL can forge call events.
X-VoiceKernel-Signature: t=1785668467,v1=9f2c…
const [t, v1] = header.split(',').map(p => p.split('=')[1]);
const expected = crypto
.createHmac('sha256', process.env.VK_WEBHOOK_SECRET)
.update(`${t}.${rawBody}`)
.digest('hex');
// Constant time, and over the RAW body - re-serialising changes key order.
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) return res.sendStatus(401);
// A valid signature replayed next week is still an attack.
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return res.sendStatus(401);
Respond 2xx to acknowledge. Anything else is retried up to 8 times with
backoff, so acknowledge first and do slow work after.
API surface
| Route | Purpose |
/v1/agents | Voice agents - prompt, model, voice, actions |
/v1/calls | Place, inspect and end calls; transcripts and recordings |
/v1/analytics | Volume, containment, cost, and the latency budget |
/v1/catalog | Supported providers, models and action types |
/v1/webhook-endpoints | Signed event delivery into your systems |
/v1/events | Event history and the audit trail |
/v1/observe/monitors | Monitors and open issues |
/v1/governance/billing | Budget, alerts and the no-dead-line policy |
/v1/subjects/:number | Right to erasure, with a receipt |
/v1/api-keys | Credential management |
/v1/organization | Tenant settings and provider mode |
/v1/phone-numbers | CRUD for phone numbers |
/v1/squads | CRUD for squads |
/v1/tools | CRUD for tools |
/v1/files | CRUD for files |
/v1/campaigns | CRUD for campaigns |
/v1/chats | CRUD for chats |
/v1/sessions | CRUD for sessions |
/v1/evals | CRUD for evals |
/v1/structured-outputs | CRUD for structured outputs |
/v1/scorecards | CRUD for scorecards |
/v1/boards | CRUD for boards |
/v1/insights | CRUD for insights |
/v1/provider/* | All 97 upstream operations, mediated |
The native routes are ergonomics, not a cage. Anything they do not wrap is
reachable through /v1/provider/* with the same auth, tenant isolation, rate
limiting and audit. GET /v1/provider/_operations lists what your
organisation can reach.
Providers & models
Any agent can move between these without touching its prompt.
Generated from the upstream spec, so a value listed here is a value the API will
accept - GET /v1/catalog returns the same data at runtime.
Language models 17
| Provider | Known values |
anthropic | claude-3-opus-20240229claude-3-sonnet-20240229claude-3-haiku-20240307claude-3-5-sonnet-20240620claude-3-5-sonnet-20241022claude-3-5-haiku-20241022claude-3-7-sonnet-20250219claude-opus-4-20250514+7 |
anthropic-bedrock | claude-3-opus-20240229claude-3-sonnet-20240229claude-3-haiku-20240307claude-3-5-sonnet-20240620claude-3-5-sonnet-20241022claude-3-5-haiku-20241022claude-3-7-sonnet-20250219claude-opus-4-20250514+7 |
anyscale | any provider-specific identifier |
cerebras | llama3.1-8bllama-3.3-70b |
custom-llm | any provider-specific identifier |
deep-seek | deepseek-chatdeepseek-reasoner |
deepinfra | any provider-specific identifier |
google | gemini-3.5-flashgemini-3.1-flash-litegemini-3-flash-previewgemini-2.5-progemini-2.5-flashgemini-2.5-flash-litegemini-2.0-flash-thinking-expgemini-2.0-pro-exp-02-05+9 |
groq | openai/gpt-oss-20bopenai/gpt-oss-120bdeepseek-r1-distill-llama-70bllama-3.3-70b-versatilellama-3.1-405b-reasoningllama-3.1-8b-instantllama3-8b-8192llama3-70b-8192+6 |
inflection-ai | inflection_3_pi |
minimax | MiniMax-M2.7 |
openai | gpt-5.6-solgpt-5.6-terragpt-5.6-lunagpt-5.5chat-latestgpt-5.4gpt-5.4-minigpt-5.4-nano+119 |
openrouter | any provider-specific identifier |
perplexity-ai | any provider-specific identifier |
together-ai | any provider-specific identifier |
voicekernel | any provider-specific identifier |
xai | grok-betagrok-2grok-3grok-4-fast-reasoninggrok-4-fast-non-reasoninggrok-4.20-0309-reasoninggrok-4.20-0309-non-reasoninggrok-4.3 |
Voices 20
| Provider | Known values |
11labs | burtmarissaandreasarahphillipstevejosephmyra+7 |
azure | andrewbrianemma |
cartesia | any provider-specific identifier |
custom-voice | any provider-specific identifier |
deepgram | asterialunastellaathenaheraorionarcasperseus+62 |
hume | any provider-specific identifier |
inworld | AlexAshleyCraigDeborahDennisEdwardElizabethHades+57 |
lmnt | amyanselautumnavabrandoncalebcassianchloe+34 |
microsoft | de-DE-Klaus:MAI-Voice-2de-DE-Mia:MAI-Voice-2en-AU-Lisa:MAI-Voice-2en-US-Ethan:MAI-Voice-2en-US-Grant:MAI-Voice-2en-US-Harper:MAI-Voice-2en-US-Iris:MAI-Voice-2en-US-Jasper:MAI-Voice-2+38 |
minimax | any provider-specific identifier |
neuphonic | any provider-specific identifier |
openai | alloyechofableonyxnovashimmermarincedar |
playht | jennifermelissawillchrismattjackrubydavis+2 |
rime-ai | covemoonwildflowerevaambermayalagoonbreeze+42 |
sesame | any provider-specific identifier |
smallest-ai | emilyjasminearmanjamesmithaliaravindrajdiya+17 |
tavus | r52da2535a |
voicekernel | ClaraGodfreyElliotSavannahNicoKaiEmmaSagar+22 |
wellsaid | any provider-specific identifier |
xai | eveararexsalleo |
Transcribers 14
| Provider | Known values |
11labs | scribe_v1scribe_v2scribe_v2_realtime |
assembly-ai | any provider-specific identifier |
azure | any provider-specific identifier |
cartesia | ink-whisperink-2 |
custom-transcriber | any provider-specific identifier |
deepgram | nova-3nova-3-generalnova-3-medicalnova-2nova-2-generalnova-2-meetingnova-2-phonecallnova-2-finance+26 |
gladia | fastaccuratesolaria-1 |
google | gemini-3.5-flashgemini-3.1-flash-litegemini-3-flash-previewgemini-2.5-progemini-2.5-flashgemini-2.5-flash-litegemini-2.0-flash-thinking-expgemini-2.0-pro-exp-02-05+9 |
openai | gpt-4o-transcribegpt-4o-mini-transcribe |
soniox | stt-rt-v4stt-rt-v5 |
speechmatics | default |
talkscriber | whisper |
voicekernel | any provider-specific identifier |
xai | default |
Actions 26
| Type | Group | |
apiRequest | Enterprise systems | your endpoint |
bash | Enterprise systems | your endpoint |
code | Enterprise systems | your endpoint |
computer | Enterprise systems | your endpoint |
function | Enterprise systems | your endpoint |
output | Enterprise systems | built-in |
query | Enterprise systems | built-in |
textEditor | Enterprise systems | your endpoint |
ghl | Integrations | built-in |
gohighlevel.calendar.availability.check | Integrations | built-in |
gohighlevel.calendar.event.create | Integrations | built-in |
gohighlevel.contact.create | Integrations | built-in |
gohighlevel.contact.get | Integrations | built-in |
google.calendar.availability.check | Integrations | built-in |
google.calendar.event.create | Integrations | built-in |
google.sheets.row.append | Integrations | built-in |
make | Integrations | built-in |
mcp | Integrations | your endpoint |
slack.message.send | Integrations | built-in |
dtmf | Telephony | built-in |
endCall | Telephony | built-in |
handoff | Telephony | built-in |
sipRequest | Telephony | built-in |
sms | Telephony | built-in |
transferCall | Telephony | built-in |
voicemail | Telephony | built-in |
Upstream operations
97 operations, generated from the upstream OpenAPI
document - so this list is what the API accepts, not what someone remembered to
write down.
Analytics
| POST |
/v1/provider/analytics |
Create Analytics Queries |
shared-key restricted |
Assistants
| GET |
/v1/provider/assistant |
List Assistants |
|
| POST |
/v1/provider/assistant |
Create Assistant |
|
| GET |
/v1/provider/assistant/{id} |
Get Assistant |
|
| PATCH |
/v1/provider/assistant/{id} |
Update Assistant |
|
| DELETE |
/v1/provider/assistant/{id} |
Delete Assistant |
|
Board
| GET |
/v1/provider/reporting/board |
Get Boards |
|
| POST |
/v1/provider/reporting/board |
Create Board |
|
| GET |
/v1/provider/reporting/board/{id} |
Get Board |
|
| PATCH |
/v1/provider/reporting/board/{id} |
Update Board |
|
| DELETE |
/v1/provider/reporting/board/{id} |
Delete Board |
|
| GET |
/v1/provider/reporting/board/default/metrics-overview |
Get Default Metrics Overview Board |
shared-key restricted |
Calls
| GET |
/v1/provider/call |
List Calls |
|
| POST |
/v1/provider/call |
Create Call |
|
| GET |
/v1/provider/call/{id} |
Get Call |
|
| PATCH |
/v1/provider/call/{id} |
Update Call |
|
| DELETE |
/v1/provider/call/{id} |
Delete Call |
|
| GET |
/v1/provider/call/{id}/assistant-recording |
Download Call Assistant Recording |
|
| GET |
/v1/provider/call/{id}/call-logs |
Download Call Logs |
|
| GET |
/v1/provider/call/{id}/customer-recording |
Download Call Customer Recording |
|
| GET |
/v1/provider/call/{id}/mono-recording |
Download Call Mono Recording |
|
| GET |
/v1/provider/call/{id}/pcap |
Download Call Packet Capture (pcap) |
|
| GET |
/v1/provider/call/{id}/stereo-recording |
Download Call Stereo Recording |
|
| GET |
/v1/provider/call/{id}/video-recording |
Download Call Video Recording |
|
Campaigns
| GET |
/v1/provider/campaign |
List Campaigns |
|
| POST |
/v1/provider/campaign |
Create Campaign |
|
| GET |
/v1/provider/campaign/{id} |
Get Campaign |
|
| PATCH |
/v1/provider/campaign/{id} |
Update Campaign |
|
| DELETE |
/v1/provider/campaign/{id} |
Delete Campaign |
|
| GET |
/v1/provider/v2/campaign |
List Campaigns V2 |
|
| POST |
/v1/provider/v2/campaign |
Create Campaign V2 |
|
| GET |
/v1/provider/v2/campaign/{id} |
Get Campaign V2 |
|
| PATCH |
/v1/provider/v2/campaign/{id} |
Update Campaign |
|
| DELETE |
/v1/provider/v2/campaign/{id} |
Delete Campaign |
|
Chats
| GET |
/v1/provider/chat |
List Chats |
|
| POST |
/v1/provider/chat |
Create Chat |
|
| GET |
/v1/provider/chat/{id} |
Get Chat |
|
| DELETE |
/v1/provider/chat/{id} |
Delete Chat |
|
| POST |
/v1/provider/chat/responses |
Create Chat (OpenAI Compatible) |
|
Eval
| GET |
/v1/provider/eval |
List Evals |
|
| POST |
/v1/provider/eval |
Create Eval |
|
| GET |
/v1/provider/eval/{id} |
Get Eval |
|
| PATCH |
/v1/provider/eval/{id} |
Update Eval |
|
| DELETE |
/v1/provider/eval/{id} |
Delete Eval |
|
| GET |
/v1/provider/eval/run |
List Eval Runs |
|
| POST |
/v1/provider/eval/run |
Create Eval Run |
|
| GET |
/v1/provider/eval/run/{id} |
Get Eval Run |
|
| DELETE |
/v1/provider/eval/run/{id} |
Delete Eval Run |
|
Files
| GET |
/v1/provider/file |
List Files |
|
| POST |
/v1/provider/file |
Upload File |
|
| GET |
/v1/provider/file/{id} |
Get File |
|
| PATCH |
/v1/provider/file/{id} |
Update File |
|
| DELETE |
/v1/provider/file/{id} |
Delete File |
|
Insight
| GET |
/v1/provider/reporting/insight |
Get Insights |
|
| POST |
/v1/provider/reporting/insight |
Create Insight |
|
| GET |
/v1/provider/reporting/insight/{id} |
Get Insight |
|
| PATCH |
/v1/provider/reporting/insight/{id} |
Update Insight |
|
| DELETE |
/v1/provider/reporting/insight/{id} |
Delete Insight |
|
| POST |
/v1/provider/reporting/insight/{id}/run |
Run Insight |
|
| POST |
/v1/provider/reporting/insight/preview |
Preview Insight |
|
Observability/Scorecard
| GET |
/v1/provider/observability/scorecard |
List Scorecards |
|
| POST |
/v1/provider/observability/scorecard |
Create Scorecard |
|
| GET |
/v1/provider/observability/scorecard/{id} |
Get Scorecard |
|
| PATCH |
/v1/provider/observability/scorecard/{id} |
Update Scorecard |
|
| DELETE |
/v1/provider/observability/scorecard/{id} |
Delete Scorecard |
|
Phone Numbers
| GET |
/v1/provider/phone-number |
List Phone Numbers |
|
| POST |
/v1/provider/phone-number |
Create Phone Number |
|
| GET |
/v1/provider/phone-number/{id} |
Get Phone Number |
|
| PATCH |
/v1/provider/phone-number/{id} |
Update Phone Number |
|
| DELETE |
/v1/provider/phone-number/{id} |
Delete Phone Number |
|
| GET |
/v1/provider/v2/phone-number |
List Phone Numbers |
|
Provider Resources
| GET |
/v1/provider/provider/{provider}/{resourceName} |
List Provider Resources |
|
| POST |
/v1/provider/provider/{provider}/{resourceName} |
Create Provider Resource |
|
| GET |
/v1/provider/provider/{provider}/{resourceName}/{id} |
Get Provider Resource |
|
| PATCH |
/v1/provider/provider/{provider}/{resourceName}/{id} |
Update Provider Resource |
|
| DELETE |
/v1/provider/provider/{provider}/{resourceName}/{id} |
Delete Provider Resource |
|
Sessions
| GET |
/v1/provider/session |
List Sessions |
|
| POST |
/v1/provider/session |
Create Session |
|
| GET |
/v1/provider/session/{id} |
Get Session |
|
| PATCH |
/v1/provider/session/{id} |
Update Session |
|
| DELETE |
/v1/provider/session/{id} |
Delete Session |
|
Squads
| GET |
/v1/provider/squad |
List Squads |
|
| POST |
/v1/provider/squad |
Create Squad |
|
| GET |
/v1/provider/squad/{id} |
Get Squad |
|
| PATCH |
/v1/provider/squad/{id} |
Update Squad |
|
| DELETE |
/v1/provider/squad/{id} |
Delete Squad |
|
Structured Outputs
| GET |
/v1/provider/structured-output |
List Structured Outputs |
|
| POST |
/v1/provider/structured-output |
Create Structured Output |
|
| GET |
/v1/provider/structured-output/{id} |
Get Structured Output |
|
| PATCH |
/v1/provider/structured-output/{id} |
Update Structured Output |
|
| DELETE |
/v1/provider/structured-output/{id} |
Delete Structured Output |
|
| POST |
/v1/provider/structured-output/run |
Run Structured Output |
|
Tools
| GET |
/v1/provider/tool |
List Tools |
|
| POST |
/v1/provider/tool |
Create Tool |
|
| GET |
/v1/provider/tool/{id} |
Get Tool |
|
| PATCH |
/v1/provider/tool/{id} |
Update Tool |
|
| DELETE |
/v1/provider/tool/{id} |
Delete Tool |
|
Operations marked shared-key restricted aggregate an entire
upstream account. On the shared platform key that would span tenants, so they
are refused and answered from VoiceKernel's own org-scoped data instead. Adding
your own provider key enables them.