Developer Guide

Complete reference for integrating Voice Nexus Service (VNS) into your stack.

Overview

Voice Nexus Service (VNS) allows you to connect a telephone number to an AI voice workflow using OpenAI Realtime voice models such as gpt-realtime-2.1 and gpt-realtime-2.1-mini. VNS sits between the Voice Elements Cloud Platform and your customer-defined AI logic, making it possible to define instructions, invoke functions, and integrate with external systems during an active voice session.

  • Inbound AI voice handling — Connect numbers and WebRTC sessions to realtime AI agents.
  • Webhook-driven call setup — Your endpoint controls per-call instructions and billing context.
  • Function and MCP integration — Allow the AI agent to access scheduling, CRM, and business systems.
  • Outbound session support — Initiate outbound calls using the VNS API and a returned session token.

Two ways to build an agent

Managed in VnsPortal — start from a QuickStart template or a blank AI Voice Agent, publish it, and assign it to a number. VNS supplies the CallStart configuration for you; no webhook service required. Developer-managed webhooks — this guide — host your own CallStart, CallEnd, and tool endpoints when each call needs dynamic control.

Architecture

1

Carrier or WebRTC

An inbound call or browser-based session enters the Voice Elements environment.

2

Voice Elements Cloud Platform

Routes the call to Voice Nexus Service.

3

Voice Nexus Service (VNS)

Applies your published VnsPortal agent or calls your CallStart webhook, establishes the realtime AI session, and brokers tool execution.

4

OpenAI Realtime Voice

Handles the live conversational AI session.

5

Your APIs / Tools / MCP Servers

Provide business logic such as scheduling, lookups, and human escalation.

Quick Start

Setup is self-service in VnsPortal. These steps are for the developer-managed path; if you don't need per-call webhook logic, follow the Get Started guide to build an agent in the portal instead.

  1. Create your account at vnsportal.voiceelements.com.
  2. Create API Tokens for outbound API access and for authenticating your webhooks.
  3. Get a phone number in VnsPortal.
  4. Configure your CallStart and CallEnd webhook URLs and authentication.
  5. Test your webhooks, then make a live call.

Inbound Calls

  1. CallStart webhook — VNS sends a CallStart webhook to the endpoint defined for the DID.
  2. Instruction retrieval — Your endpoint returns JSON describing how the call should be handled.
  3. Realtime session — VNS establishes a WebSocket session with OpenAI Realtime and supplies the returned instructions.
  4. Tool execution — During the session the AI agent can invoke tools or MCP-connected systems.
  5. Call control — Transfers and other call control actions can be made available as tools.
  6. CallEnd webhook — At the end of the call VNS sends a CallEnd webhook containing call statistics.

Outbound Calls

  1. Dial request — Send a request to the VNS Web API containing the destination number, caller ID number, and caller ID name.
  2. Session creation — VNS returns a session token or call ID.
  3. CallStart webhook — VNS sends the CallStart webhook with the session token and marks the call as outbound initiated.
  4. Call placement — VNS dials the phone number and the session proceeds like an inbound AI call.
  5. Termination — When the call ends the CallEnd webhook is executed.

CallStart Webhook

VNS performs an HTTP POST to your configured CallStart endpoint at the start of each call.

Request Body

{
  "sessionGuid": "9e6a9d8e-6a92-4b3f-9a2c-1c63c1f3a8f1",
  "calledNumber": "7206999999",
  "callerId": "3032639999",
  "callerIdName": "John Smith",
  "outboundTriggered": false,
  "softwareVersion": "1.0.0.0",
  "callStart": "2026-03-12T10:42:15Z",
  "customerCallId": "Cust-001-12345"
}

Request Fields

Field Type Description
sessionGuidstringUnique identifier for the voice session.
calledNumberstringThe DID that received the inbound call.
callerIdstringThe originating phone number.
callerIdNamestringCaller display name, when available.
outboundTriggeredbooleanIndicates whether the call was initiated as an outbound VNS session.
softwareVersionstringVoice Nexus software version for the current runtime.
callStartdatetimeUTC timestamp when the call began.
customerCallIdstring | nullOptional customer-supplied call identifier associated with the session.

CallStart Response

Your CallStart endpoint must return the instructions and session configuration that will be applied to the OpenAI Realtime session.

Core VoiceElements_Instructions Fields

  • aiUrl.url — The OpenAI Realtime WebSocket URL, including the model name (e.g., gpt-realtime-2.1 or gpt-realtime-2.1-mini). For Azure, see Azure OpenAI GPT Realtime.
  • aiUrl.headers — HTTP headers sent to the AI provider. For OpenAI, send Authorization: Bearer <<vns-api-token:MyOpenAiKey>> using a VNS placeholder rather than a literal key.
  • maxSeconds — Maximum number of seconds the call may remain connected.
  • customerCallId — Optional identifier your system assigns to the session. Returned in the CallEnd webhook and in tool calls — in the VoiceElements_InvokeTool body object, or through the <<customerCallId>> URL adapter placeholder.
  • defaultToolsUrlBase.url — The endpoint VNS calls when the AI invokes a function.
  • defaultToolsUrlBase.headers — HTTP headers sent with every tool call request (e.g., Token or Authorization).
  • defaultToolsUrlAdapter — Controls how session metadata is injected into tool requests. See URL Adapter Patterns.
  • routeToNumberOnFailure — Phone number to transfer the caller to if the AI session cannot be established. Set to null to hang up instead.
  • messageToPlayOnFailure — Message played to the caller before routing or hanging up on failure.
  • logToolCallRequests — When true, VNS logs each tool invocation request payload. The logs are delivered in the CallEnd Request.
  • logToolCallReplies — When true, VNS logs each tool reply payload. The logs are delivered in the CallEnd Request.
  • logTranscription — When true, VNS logs a full call transcription. The logs are delivered in the CallEnd Request.
  • recordCall — When true, VNS records the call audio. See Call Recordings to learn how to retrieve the recording.
  • recordCallFormat — Audio format for the recording: opus, mp3, or wav.
  • recordCallPassword — Optional password if you wish the recording to be encrypted.
  • transcriptionToolName — If set, VNS delivers the transcription to this tool endpoint realtime phrase by phrase.

Additional VoiceElements_Instructions Fields

All of these are optional and additive — a CallStart response that omits them keeps working exactly as before. Follow the links for the full contract.

Area Field Purpose
Alternate AI / translationtranslateAiUrlAlternate AI endpoint used for translation. See the Live Translator sample.
Tool routingtoolkitsNamed tool endpoints, each with its own URL, headers, and adapter. Calling Multiple Tool Endpoints →
TransferstransferServicesNamed blind or attended transfer services, including dial mode, numbers, and attended hold media. Transfer Call Options →
addSecondsToMaxTimeOnTransferSeconds added to the maximum call time once a transfer connects.
onTransferToolNameYour tool that returns a transfer service dynamically at transfer time.
onTransferFailedToolNameYour tool that decides what happens when every transfer attempt fails.
SMSsmsNumbersFriendly keys mapped to the numbers vns_send_sms may send from. vns_send_sms →
smsToNumberUnrestrictedWhen true, also allows SMS to custom E.164 numbers. Default false limits recipients to caller, callednumber, or a friendly key from smsNumbers.
Idle / rate behaviormaxIdleStrikesIdle-strike limit for a caller who stops responding (for example 2). Call-flow steps with condition: "IdleStrikeLimitReached" run when it is reached.
idleTimeoutFarewellFarewell spoken when an idle caller's session is ended (for example "It looks like we've lost connection. Goodbye!").
rateLimitWarningThresholdNumeric threshold for AI provider rate-limit warnings (for example 0.2).
Static mediamediaCatalogMedia items referenced by call flow, hold media, and comfort audio. Static Media & Call Flow →
callFlowOrdered steps that play media, run the Realtime session, or end the call. Null or empty keeps the legacy single-session behavior.
Slow-tool audiotoolCallComfortAudioComfort audio the caller hears while a slow HTTP or MCP tool call is pending. Caller Comfort Audio →

Response Body Example

{
  "VoiceElements_Instructions": {
    "aiUrl": {
      "url": "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1",
      "headers": {
        "Authorization": "Bearer <<vns-api-token:MyOpenAiKey>>"
      }
    },
    "maxSeconds": 300,
    "customerCallId": "CallId-001",
    "defaultToolsUrlBase": {
      "url": "https://your-api.example.com/tools",
      "headers": {
        "Token": "<<vns-api-token:MyToolsApi>>"
      }
    },
    "defaultToolsUrlAdapter": null,
    "routeToNumberOnFailure": null,
    "messageToPlayOnFailure": "The AI system is currently offline. Please call back later.",
    "logToolCallRequests": false,
    "logToolCallReplies": false,
    "logTranscription": false,
    "recordCall": false,
    "recordCallFormat": "opus",
    "recordCallPassword": "YourPassword",
    "transcriptionToolName": "your_custom_tool_name_for_transcriptions",
    "maxIdleStrikes": 2,
    "idleTimeoutFarewell": "It looks like we've lost connection. Goodbye!",
    "rateLimitWarningThreshold": 0.2,
    "mediaCatalog": [
      {
        "mediaReference": "WelcomeGreeting"
      },
      {
        "mediaReference": "TransferHoldMusic"
      },
      {
        "mediaReference": "ApiWaitComfort"
      }
    ],
    "callFlow": [
      {
        "sequence": 10,
        "label": "Welcome greeting",
        "description": "Play a Media Library greeting before starting the AI.",
        "operation": "PlayMedia",
        "mediaReference": "WelcomeGreeting",
        "interruptDigits": "",
        "resolutionFailureMode": "Continue",
        "recordingFailurePolicy": {
          "onResolutionFailure": "NoChange",
          "onPlaybackFailure": "NoChange"
        },
        "callEndEvidence": "Full",
        "condition": "Always"
      },
      {
        "sequence": 20,
        "label": "AI receptionist",
        "operation": "RunRealtime",
        "condition": "Always"
      }
    ],
    "toolCallComfortAudio": {
      "mediaReference": "ApiWaitComfort",
      "startDelayMilliseconds": 2000,
      "maximumSeconds": 120
    },
    "transferServices": [
      {
        "name": "Support",
        "callerId": "+13035559999",
        "callerIdName": "Business Name",
        "attended": true,
        "useVnsNumberAsCallerId": false,
        "dialMode": "Sequential",
        "preTransferAnnouncement": "Please stay with me while I connect you.",
        "preTransferAnnouncementTimeoutSeconds": 15,
        "attendedDecisionTimeoutSeconds": 30,
        "holdMediaReferences": [
          "TransferHoldMusic"
        ],
        "transferNumbers": [
          {
            "number": "+13035551212",
            "dialTime": 30
          },
          {
            "number": "+13035551213",
            "dialTime": 20
          }
        ],
        "attendedTransferSessionUpdate": null,
        "failedTransferSessionUpdate": null
      }
    ]
  },
  "event_id": "start_1",
  "type": "session.update",
  "session": {
    "type": "realtime",
    "instructions": "You are a friendly agent. Explain that you can look up a name by a phone number or a phone number by a name. If the user gives you a phone number or name, call lookup_name_or_phone with the appropriate parameter. Before a potentially slow lookup, briefly tell the caller that you are checking. If the caller asks for Support, call vns_transfer_call with transferService set to Support. When the caller is finished, call vns_end_conversation with the complete farewell in farewell, wait for the tool result, and do not say a separate goodbye.",
    "model": "gpt-realtime-2.1",
    "audio": {
      "input": {
        "format": {
          "type": "audio/pcmu"
        },
        "transcription": {
          "model": "whisper-1"
        },
        "turn_detection": {
          "type": "server_vad",
          "threshold": 0.65,
          "prefix_padding_ms": 300,
          "silence_duration_ms": 300,
          "create_response": true,
          "interrupt_response": true,
          "idle_timeout_ms": 30000
        },
        "noise_reduction": null
      },
      "output": {
        "format": {
          "type": "audio/pcmu"
        },
        "voice": "alloy"
      }
    },
    "tool_choice": "auto",
    "tools": [
      {
        "name": "vns_end_conversation",
        "description": "If the user says something about ending the conversation, like goodbye, call this function to let the application know.",
        "type": "function",
        "parameters": {
          "type": "object",
          "properties": {
            "user_input": {
              "type": "string",
              "description": "Input from the user indicating they want to end the conversation."
            },
            "farewell": {
              "type": "string",
              "description": "The complete farewell to say to the caller before ending the call."
            }
          },
          "required": [
            "user_input",
            "farewell"
          ],
          "additionalProperties": false
        }
      },
      {
        "name": "vns_get_call_info",
        "description": "Call this function to get information about the Called Number, Caller Id, Caller Id Name, the Call Start Time (UTC), whether the call was inbound or outbound, the SessionGuid, and the CustomerCallId.",
        "type": "function",
        "parameters": {
          "type": "object",
          "properties": {},
          "additionalProperties": false
        }
      },
      {
        "name": "vns_get_utc_datetime",
        "description": "Retrieves the current UTC date and time.",
        "type": "function",
        "parameters": {
          "type": "object",
          "properties": {},
          "additionalProperties": false
        }
      },
      {
        "name": "vns_transfer_call",
        "description": "Transfers the current call using a configured transfer service.",
        "type": "function",
        "parameters": {
          "type": "object",
          "properties": {
            "transferService": {
              "type": "string",
              "description": "The configured transfer service to use.",
              "enum": [
                "Support"
              ]
            }
          },
          "required": [
            "transferService"
          ],
          "additionalProperties": false
        }
      },
      {
        "name": "lookup_name_or_phone",
        "description": "An example customer-specific tool that looks up a name from a phone number or a phone number from a name.",
        "type": "function",
        "parameters": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "description": "Name of the person to search for."
            },
            "phoneNumber": {
              "type": "string",
              "description": "Phone number to search, preferably in E.164 format such as +13035551212."
            }
          },
          "additionalProperties": false
        }
      }
    ]
  }
}

Tool Execution

During an active AI session, when the model triggers a function, VNS augments the payload with metadata before forwarding the request to your webhook.

Tool Request Payload

{
  "name": "Ron"
}

Tool Request Payload with Session Info

When defaultToolsUrlAdapter is null in your CallStart response, VNS includes a VoiceElements_InvokeTool block in the tool payload with the tool name, session GUID, and — when your CallStart response supplied one — the customer call ID. Your endpoint can use these fields to maintain state or correlate tool calls back to a specific session.

{
  "VoiceElements_InvokeTool": {
    "toolName": "lookup_name_or_phone",
    "sessionGuid": "SOME SESSION GUID",
    "customerCallId": "CallId-001"
  },
  "name": "Ron"
}

Tool Reply

Your endpoint returns any JSON object. VNS feeds the result directly back into the AI session so the model can use it in the ongoing conversation.

{
  "matchType": "name",
  "contactFound": true,
  "contactName": "Ron Tanner",
  "phoneNumber": "+13035551212"
}

URL Adapter Patterns

Set defaultToolsUrlAdapter in your CallStart response to route metadata via URL path or query string instead of the request body. When set to null, the session ID, tool name, and customer call ID (when supplied) are included in the VoiceElements_InvokeTool body object. With an adapter, use the <<customerCallId>> placeholder to receive the customer call ID.

Variations for the defaultToolsUrlAdapter json

"defaultToolsUrlAdapter" : null
"defaultToolsUrlAdapter" : "/<<sessionguid>>/<<toolname>>/<<customerCallId>>"
"defaultToolsUrlAdapter" : "/<<toolname>>/<<sessionguid>>/<<customerCallId>>"
"defaultToolsUrlAdapter" : "/<<toolname>>"
"defaultToolsUrlAdapter" : "/<<toolname>>/<<customerCallId>>"
"defaultToolsUrlAdapter" : "?toolname=<<toolname>>&sessionguid=<<sessionguid>>&customerCallId=<<customerCallId>>"
"defaultToolsUrlAdapter" : "?toolname=<<toolname>>&sessionguid=<<sessionguid>>"

If defaultToolsUrlAdapter is null, the session id, tool name, and customer call id (when supplied) are included in the VoiceElements_InvokeTool body object.
Using MCP servers? When connecting an MCP server you must also include the vns_allow_mcp_calls built-in tool so VNS waits until all MCP servers are ready before the AI begins. See the MCP Integration guide →

Built-in VNS Tools

VNS ships with built-in tools that are handled entirely inside Voice Nexus Service — no webhook endpoint is required on your server. When the AI model invokes one of these tools, VNS intercepts the call and responds directly. Include any you need in the tools array of your CallStart response.

vns_end_conversation

Speaks the model's farewell to the caller, then gracefully terminates the voice session.

vns_transfer_call

Transfers the active call using a named transfer service — blind or attended.

vns_get_call_info

Returns caller ID, called number, session ID, and call start time.

vns_get_utc_datetime

Returns the current UTC date and time for scheduling and logging.

vns_send_sms

Sends an SMS from one of the numbers you authorize in smsNumbers. Details →

vns_allow_mcp_calls

Required when using MCP servers. Blocks the AI until all connected MCP servers are fully loaded and ready. See the MCP Integration guide →

For complete tool schemas, parameter definitions, and example instructions, see the Built-in VNS Tools reference →

Ending a call: vns_end_conversation

Define both user_input and farewell, and make both required. Tell the model to put its complete caller-facing closing sentence in farewell, wait for the tool result, and not speak another goodbye itself. VNS plays the farewell and lets it finish before ending the call, so the caller always hears it.

{
  "name": "vns_end_conversation",
  "description": "If the user says something about ending the conversation, like goodbye, call this function to let the application know.",
  "type": "function",
  "parameters": {
    "type": "object",
    "properties": {
      "user_input": {
        "type": "string",
        "description": "Input from the user indicating they want to end the conversation."
      },
      "farewell": {
        "type": "string",
        "description": "The complete farewell to say to the caller before ending the call."
      }
    },
    "required": ["user_input", "farewell"],
    "additionalProperties": false
  }
}

For backward compatibility, VNS still says a plain "Goodbye!" if farewell is missing. Treat that as error tolerance, not the recommended contract.

Transferring a call: vns_transfer_call

The recommended form lets the model choose a named transfer service that you configure in transferServices. List exactly those service names in enum. The model never sees or picks phone numbers directly.

{
  "name": "vns_transfer_call",
  "description": "Transfers the current call using a configured transfer service.",
  "type": "function",
  "parameters": {
    "type": "object",
    "properties": {
      "transferService": {
        "type": "string",
        "description": "The configured transfer service to use.",
        "enum": ["Support", "Billing"]
      }
    },
    "required": ["transferService"],
    "additionalProperties": false
  }
}

The legacy direct-number arguments (transferNumber, useVnsNumberAsCallerId, attended) remain supported for compatibility — see the Built-in VNS Tools reference. For service configuration, sequential and simultaneous dialing, attended decisions, caller restoration, and CallEnd evidence, see Transfer Call Options →

CallEnd Webhook

VNS performs an HTTP POST to your configured CallEnd endpoint after the call completes. Respond with {"status": 0, "errorMessage": "Success"} to acknowledge.

Request Body Example

{
  "sessionGuid": "164ff386-b1b4-4521-97e4-440ca6b3b5c8",
  "callStart": "2026-04-17T16:26:12.5600000Z",
  "callConnected": "2026-04-17T16:26:13.4780000Z",
  "callEnd": "2026-04-17T16:27:45.8620000Z",
  "calledNumber": "+17206999209",
  "callerId": "+17205551212",
  "callerIdName": "Jane Doe",
  "status": 0,
  "errorMessage": "No Errors",
  "outboundTriggered": false,
  "outboundCallResult": "N/A",
  "customerCallId": "CallId-001",
  "callReferredOut": false,
  "transfers": [
    {
      "transferCalledNumber": "+13035551212",
      "transferCallerId": "+13035559999",
      "transferCallerIdName": "Business Name",
      "transferCallStart": "2026-04-17T16:26:33.2170000Z",
      "transferCallEnd": "2026-04-17T16:26:46.8670000Z",
      "transferCallConnect": "2026-04-17T16:26:38.2730000Z",
      "transferCallResult": "Connected",
      "attendedTransferOutcome": "RestoredAfterDestinationDecline",
      "attendedTransferOutcomeAtUtc": "2026-04-17T16:26:46.8670000Z",
      "callerHandoffCompleted": false,
      "callerHandoffAtUtc": null,
      "callerRestoreOutcome": "Completed",
      "callerRestoredAtUtc": "2026-04-17T16:26:47.0100000Z",
      "callerRestoreAudioOutcome": "AudioRendered",
      "callerRestoreAudioOutcomeAtUtc": "2026-04-17T16:26:50.2120000Z",
      "holdMediaOutcome": "Completed",
      "holdMediaFailureReason": null,
      "holdMediaFailureCode": null,
      "holdMediaPlaylist": [
        {
          "mediaReference": "TransferHoldMusic",
          "startedAtUtc": "2026-04-17T16:26:33.3000000Z",
          "endedAtUtc": "2026-04-17T16:26:47.0000000Z",
          "outcome": "Interrupted"
        }
      ],
      "holdMediaResumedAtIndex": 0
    }
  ],
  "logInformation": [
    "26/04/17 - 10:26:12.560 - Logging Started."
  ],
  "transcription": [
    "2026-04-17 10:26:20.046 AI  : Hello! How can I help you today?",
    "2026-04-17 10:26:21.952 User: Please connect me to support."
  ],
  "mediaEvidence": [
    {
      "sequence": 10,
      "mediaReference": "WelcomeGreeting",
      "mediaKey": "4dd6e7d8-278f-4e64-9e5f-bf373c15a523",
      "contentSha256": "d769757c84273726e2c945a7326f05614e1534521bc90b0fb35610254fe0679e",
      "resolvedScope": "Account",
      "origin": "Hosted",
      "resolutionOutcome": "Resolved",
      "resolutionFailureCode": null,
      "playbackStartedUtc": "2026-04-17T16:26:13.6000000Z",
      "playbackCompletedUtc": "2026-04-17T16:26:17.9000000Z",
      "playbackOutcome": "Completed",
      "playbackFailureCode": null,
      "failureReason": null,
      "resolutionFailureModeApplied": "Continue",
      "recordingFailureActionApplied": null,
      "recordingFailureCode": null,
      "recordingDisposition": "NotRequested",
      "cleanupOutcome": "NotRequired",
      "cleanupFailureCode": null
    }
  ],
  "realtimeExitReason": "Completed",
  "callFlowFailureCode": null
}

Request Fields

Field Type Description
sessionGuidstringUnique identifier for the voice session.
callStartdatetimeUTC timestamp when the call began.
callConnecteddatetime | nullUTC timestamp when the call connected, if answered.
callEnddatetimeUTC timestamp when the call ended.
calledNumberstringDID used for the call.
callerIdstringOriginating or remote party number.
callerIdNamestring | nullCaller display name, when available.
statusintegerCall completion status code.
errorMessagestring | nullError detail or status text.
outboundTriggeredbooleanWhether the session originated from an outbound-triggered call.
outboundCallResultstring | nullResult status of the outbound call; "N/A" for inbound sessions.
customerCallIdstring | nullCustomer-supplied call identifier carried through the session.
callReferredOutbooleanWhether the call was referred or transferred out.
transfersarray | nullTransfer records, if any occurred. Each entry includes transferCalledNumber, transferCallerId, transferCallerIdName, transferCallStart, transferCallConnect, transferCallEnd, and transferCallResult, plus attended-transfer outcome, handoff, restore, and hold-media fields. See Transfer evidence.
logInformationarray | nullArray of formatted diagnostic log strings. Present when call logging is active.
transcriptionarray | nullArray of formatted strings in the form "timestamp Speaker: text". Present when logTranscription is enabled.
mediaEvidencearray | nullOne entry per reported call-flow media step, controlled by each step's callEndEvidence setting: resolution and playback outcomes, timestamps, and recording and cleanup results. Never contains paths, URLs, Base64, headers, or secrets. See Static Media & Call Flow.
realtimeExitReasonstringWhy the Realtime AI session ended (for example "Completed").
callFlowFailureCodestring | nullSanitized failure code when a callFlow step could not complete.

Transfer evidence

transferCallResult: "Connected" means the destination leg answered. It does not prove that the original caller was handed off. Read callerHandoffCompleted and attendedTransferOutcome for the caller-facing result.

For attended transfers, each transfers[] entry records what actually happened to the caller. The full field list is on Transfer Call Options.

The request body example above shows a destination that answered ("Connected") and then declined, so the caller was restored to the AI. Compare it with a completed handoff (other CallEnd fields omitted):

Destination accepted — caller handoff completed

{
  "transfers": [
    {
      "transferCalledNumber": "+13035551212",
      "transferCallerId": "+13035559999",
      "transferCallerIdName": "Business Name",
      "transferCallStart": "2026-09-22T17:10:02.4400000Z",
      "transferCallEnd": "2026-09-22T17:16:55.0120000Z",
      "transferCallConnect": "2026-09-22T17:10:07.9310000Z",
      "transferCallResult": "Connected",
      "attendedTransferOutcome": "CallerHandoffCompleted",
      "attendedTransferOutcomeAtUtc": "2026-09-22T17:10:29.6070000Z",
      "callerHandoffCompleted": true,
      "callerHandoffAtUtc": "2026-09-22T17:10:29.6070000Z",
      "callerRestoreOutcome": "NotRequired",
      "callerRestoredAtUtc": null,
      "callerRestoreAudioOutcome": "NotRequired",
      "callerRestoreAudioOutcomeAtUtc": null,
      "holdMediaOutcome": "NotConfigured",
      "holdMediaFailureReason": null,
      "holdMediaFailureCode": null,
      "holdMediaPlaylist": null
    }
  ]
}

Acknowledgement Response

{
  "status": 0,
  "errorMessage": "Success"
}

Outbound Call API

This endpoint allows your system to initiate an outbound call through Voice Nexus Service.

Authentication required: All VNS API requests must include your API key in a Token header. See the API Authentication Guide → for details on obtaining and using your key.

Request

{
  "customerCallId": "abc123",
  "calledNumber": "3032639999",
  "callerId": "7206999999",
  "callerIdName": "John Smith"
}

Response

{
  "status": 0,
  "customerCallId": "abc123",
  "sessionGuid": "9e6a9d8e-6a92-4b3f-9a2c-1c63c1f3a8f1",
  "errorMessage": "Success"
}

Initial Setup

OpenAI Prerequisite: Before testing, ensure you have a properly configured OpenAI API Platform account with billing enabled and access to the Realtime voice models. See the OpenAI Account Setup Guide →

Using a managed agent instead? Follow the Get Started guide — you won't need the webhook steps (4 and 5) below.

  1. Create your account at vnsportal.voiceelements.com. Setup is self-service from there.
  2. Create API Tokens. There are two types:
    • VNS Services Access — tokens used when calling https://vnsapi.voiceelements.com for outbound calls, retrieving recordings, or SMS services.
    • Your API Tokens — tokens that VNS uses when calling your webhooks, such as the CallStart webhook.
  3. Get a phone number on the Phone Numbers page in VnsPortal. To port a number you already have, contact us.
  4. Add URLs and authentication to your CallStart and CallEnd webhooks.
  5. Press the Test button on your webhooks to verify they respond correctly.
  6. Test by calling the phone number.

Ready to Automate Your Phone Lines?

Create your account in VnsPortal and set up your first agent from a template today — or book a live demo and we'll walk you through it.

Questions first? Contact sales