This page documents the API contracts between VoxCore and external systems. Use this if you’re building your own orchestrator (replacing VoxBridge) or integrating VoxCore into an existing platform.

How VoxCore works

VoxCore is a stateless pipeline worker. It doesn’t store bots, users, or call history. For each call:
  1. It fetches bot configuration from a URL you provide (VOXBRIDGE_CONFIG_URL)
  2. It runs the voice pipeline (STT → LLM → TTS)
  3. It POSTs call results to the webhook_url from the config
You implement two endpoints:
  • Config endpoint — VoxCore calls this to get bot config at call start
  • Results webhook — VoxCore calls this to deliver call results at call end

1. Config endpoint (you implement)

VoxCore fetches bot configuration at the start of every call.

Request (VoxCore → your system)

GET {VOXBRIDGE_CONFIG_URL}/{bot_id}?caller_id={caller}&stream_id={stream}&connected_event={json}
X-VoxCore-Secret: {secret}
ParameterSourceDescription
bot_idURL path from WebSocket route or dialout requestWhich bot to load
caller_idDialler handshake or SIP headersCustomer phone number
stream_idDialler handshakeUnique call identifier from the dialler
connected_eventURL-encoded JSONFull handshake payload from dialler (CRM fields, call direction, etc.)
X-VoxCore-Secret.env on fleet serverShared secret for authentication

Response (your system → VoxCore)

Return 200 with the full bot config JSON. See Bot config schema for the complete field reference. Minimal example:
{
  "session_id": "uuid-you-generate",
  "webhook_url": "https://your-api.com/call-results",
  "system_prompt": "You are a helpful assistant...",
  "opening_message": "Hello! How can I help you today?",
  "stt": {
    "provider": "deepgram",
    "api_key": "your-deepgram-key",
    "model": "nova-3",
    "language": "en"
  },
  "llm": {
    "provider": "google",
    "api_key": "your-google-key",
    "model": "gemini-2.5-flash",
    "temperature": 0.7,
    "max_tokens": 256
  },
  "tts": {
    "provider": "elevenlabs",
    "api_key": "your-elevenlabs-key",
    "voice_id": "your-voice-id",
    "model": "eleven_flash_v2_5",
    "language": "en"
  }
}
Error responses:
StatusMeaningVoxCore behavior
200Config returnedCall proceeds
404Bot not foundCall rejected, WebSocket closed
503Outside active hoursCall rejected, WebSocket closed
OtherErrorCall rejected, WebSocket closed
The session_id you return must be unique per call. VoxCore uses it to correlate the results webhook back to this call. Generate a UUID.

2. Results webhook (you implement)

VoxCore POSTs call results when a call ends. The URL comes from webhook_url in the config response.

Request (VoxCore → your system)

POST {webhook_url}
Content-Type: application/json
X-VoxCore-Secret: {secret}

Payload

{
  "session_id": "uuid-from-config",
  "stream_id": "dialler-stream-id",
  "caller_id": "+919876543210",
  "call_duration_seconds": 141.1,
  "call_direction": "inbound",
  "disconnected_by": "customer",
  "transcript": [
    {"speaker": "bot", "text": "Hello! How can I help?", "ts": 2.1},
    {"speaker": "customer", "text": "Hi, I have a question", "ts": 5.3},
    {"speaker": "bot", "text": "Sure, go ahead!", "ts": 7.8}
  ],
  "recording_url": "https://storage.example.com/recording.wav",
  "recording_key": "calls/session-id.wav",
  "post_call_analysis": {
    "disposition": "INTERESTED",
    "summary": "Customer asked about pricing..."
  },
  "qc_analysis": null,
  "latency": {
    "stt_avg_ms": 450.0,
    "llm_avg_ms": 520.0,
    "tts_avg_ms": 200.0,
    "total_avg_response_ms": 1170.0
  },
  "events": [
    {"event": "connected", "ts": 0.0},
    {"event": "pipeline_started", "ts": 0.5},
    {"event": "opening_message_queued", "ts": 0.5},
    {"event": "disconnected", "ts": 141.0, "by": "customer"},
    {"event": "pipeline_finished", "ts": 141.1}
  ],
  "usage_metrics": [
    {"type": "llm", "processor": "GoogleLLMService", "model": "gemini-2.5-flash", "prompt_tokens": 8000, "completion_tokens": 150, "total_tokens": 8150},
    {"type": "tts", "processor": "ElevenLabsTTSService", "model": "eleven_flash_v2_5", "characters": 450}
  ],
  "pipeline_config": {
    "transport_type": "websocket",
    "stt_provider": "deepgram",
    "stt_model": "nova-3",
    "llm_provider": "google",
    "llm_model": "gemini-2.5-flash",
    "tts_provider": "elevenlabs",
    "tts_model": "eleven_flash_v2_5",
    "tts_voice_id": "your-voice-id",
    "tts_language": "en"
  }
}

Field reference

FieldTypeDescription
session_idstringSession ID from config response
stream_idstringDialler-assigned call identifier
caller_idstringCustomer phone number
call_duration_secondsfloatTotal call length in seconds
call_directionstring"inbound" or "outbound"
disconnected_bystringWho ended the call (see table below)
transcriptlistConversation transcript
recording_urlstringURL to call recording (WAV)
recording_keystringS3 key for generating signed URLs

disconnected_by values

ValueMeaning
botBot called end_call tool, closure phrase, or dead air timeout
customerCustomer hung up
voicemailVoicemail detected
RNRDead air — customer picked up but stayed silent
outside_hoursCall rejected — bot outside active hours
no_answerSIP 408/480 — callee didn’t answer (outbound only)
rejectedSIP 486/603 — callee rejected (outbound only)
timeoutMax call duration exceeded
errorPipeline startup failure or unhandled exception

Your response

Return 200 to acknowledge. VoxCore does not retry on failure — if your webhook is down, the results are lost.

3. Dialout endpoint (on VoxCore)

Trigger outbound calls by POSTing to VoxCore’s dialout endpoint. This requires LiveKit SIP to be configured on the fleet server.

Request (your system → VoxCore)

POST https://fleet.example.com/livekit/dialout
Content-Type: application/json
X-VoxCore-Secret: {secret}
{
  "bot_id": "your-bot-id",
  "to_number": "+919876543210",
  "from_number": "+911234567890",
  "connected_event": {
    "customer_name": "Rahul Sharma",
    "loan_number": "LN123456",
    "amount_due": "15000"
  },
  "config_url": "https://your-api.com/api/v1/config"
}
FieldTypeRequiredDescription
bot_idstringYesBot ID passed to config endpoint
to_numberstringYesCustomer phone number to dial
from_numberstringNoCaller ID / DID. Uses default trunk number if omitted.
connected_eventdictNoCRM data available as {{call.field}} in prompts
config_urlstringNoOverride config endpoint URL. Falls back to VOXBRIDGE_CONFIG_URL env var.
config_url lets a shared VoxCore fleet serve multiple orchestrators. Each orchestrator passes its own config URL so VoxCore fetches the right bot config.

Response

{
  "status": "ok",
  "call_id": "abc123-def456"
}
StatusMeaning
200Call initiated (runs in background)
403Invalid X-VoxCore-Secret
503LiveKit not configured, or worker at capacity
The call runs asynchronously. Results are delivered via the webhook URL from the config response.

Sequence diagram


Inbound calls (WebSocket)

For inbound WebSocket calls, the dialler connects directly to VoxCore:
wss://fleet.example.com/ws/{bot_id}
See WebSocket protocol for the handshake and message format. The same config fetch and results webhook flow applies — VoxCore calls your config endpoint at call start and your webhook at call end.