Technical developer portal
Virturing API & SDK documentation
One page for authentication, SDKs, numbers, routes, agents, call centres, realtime media, recordings, campaigns, webhooks, and API behavior.
On this page quickstart
Understand the four core resources.
A number is the reachable identity. A route decides where the call goes. An agent, queue, or media session handles it. Events record what happened.
Create a scoped credential for each environment. Never expose an API key, webhook secret, or media token in browser code.
- 01Create a server credential
Use a separate key for development and production, with only the scopes the application needs.
- 02Request a regional number
Choose a supported market, number type, capability, and intended use.
- 03Attach the handler
Publish a route to an AI agent, call-centre queue, webhook application, or realtime media worker.
- 04Listen for the outcome
Persist lifecycle and outcome events idempotently so retries cannot duplicate business actions.
Choose the SDK your service already uses.
The language switcher changes the real install command. All SDKs use the same resource model and server-side credentials.
npm install @virturing/sdk01VIRTURING_API_KEY="vt_live_..."02VIRTURING_WEBHOOK_SECRET="whsec_..."Make a first outbound call.
Use a provisioned number as the caller identity and name the agent or route that owns the conversation.
01import { Virturing } from "@virturing/sdk";0203const virturing = new Virturing({04 apiKey: process.env.VIRTURING_API_KEY05});0607const call = await virturing.calls.create({08 from: "number_94_colombo",09 to: "+94770000000",10 agent: "support-concierge@v7",11 context: { accountId: "acc_2084" }12});1314console.log(call.id, call.status);TypeScript: stream typed call events.
The TypeScript SDK exposes promises for resources and an async iterator for live events.
TYPESCRIPT · NODE 18+01const call = await virturing.calls.get("call_01J7N6BMQP");0203for await (const event of call.events()) {04 if (event.type === "tool.completed") {05 console.log(event.data.tool, event.data.durationMs);06 }0708 if (event.type === "call.completed") {09 console.log(event.data.outcome);10 }11}Python: create the same call without changing the model.
Python uses the same number, agent, route, and event identifiers as TypeScript.
PYTHON · 3.10+01from virturing import Virturing02import os0304client = Virturing(api_key=os.environ["VIRTURING_API_KEY"])0506call = client.calls.create(07 from_number="number_94_colombo",08 to="+94770000000",09 agent="support-concierge@v7",10 context={"account_id": "acc_2084"},11)1213print(call.id, call.status)Java: configure a typed server client.
Create one long-lived client per service and keep credential loading outside application code.
JAVA · 17+01import ai.virturing.Virturing;02import ai.virturing.calls.CreateCallRequest;0304var client = Virturing.builder()05 .apiKey(System.getenv("VIRTURING_API_KEY"))06 .build();0708var call = client.calls().create(CreateCallRequest.builder()09 .from("number_94_colombo")10 .to("+94770000000")11 .agent("support-concierge@v7")12 .build());Numbers and routes stay separate.
Ordering creates the regional identity. Publishing a route decides which agent, application, queue, or fallback receives its calls.
- 01Check market availability
Inventory, documentation, permitted capabilities, and approval time differ by country and intended use.
- 02Order the number
Supply country, type, voice capability, and a truthful intended-use value.
- 03Publish a route
Bind the number to a destination and declare what should happen after hours or on failure.
01const number = await virturing.numbers.order({02 country: "LK",03 type: "local",04 capabilities: ["voice"],05 intendedUse: "customer-support"06});0708await virturing.routes.publish({09 number: number.id,10 destination: { type: "queue", id: "support-primary" },11 fallback: { type: "callback", id: "after-hours" }12});Agents use explicit tools and handoff rules.
Deploy prompts, voices, tools, knowledge, and escalation behavior as a version. Historical calls retain the exact version that handled them.
01const agent = await virturing.agents.deploy({02 name: "support-concierge",03 mode: "adaptive",04 tools: ["lookup_account", "create_case", "book_callback"],05 handoff: {06 queue: "tier-2",07 include: ["transcript", "summary", "tool_results"]08 }09});modeStrict, adaptive, assistant, or programmable behavior for the job.
toolsNamed business actions with scoped credentials, schemas, and timeout behavior.
handoffThe queue, trigger conditions, and context included when a person takes over.
versionAn immutable deployed configuration for reproducible calls and review.
Build call-centre flows without hiding the queue.
Connect IVR or intent routing, AI agents, human teams, schedules, overflow, callbacks, recordings, transcripts, and quality outcomes in one published operation.
01const centre = await virturing.callCentres.publish({02 number: "number_94_colombo",03 schedule: "colombo-business-hours",04 flow: ["greeting", "intent", "support-queue"],05 queue: { ai: ["support-concierge"], people: ["tier-2"] },06 recording: { enabled: true, transcribe: true },07 overflow: "after-hours-callback"08});- 01Receive and orient
Answer on a local number, play the approved greeting, and identify the requested service.
- 02Route to AI or a person
Use intent, schedule, customer context, queue state, and policy to choose the next handler.
- 03Transfer with context
Carry the transcript, summary, verified fields, tool results, and reason into human handoff.
- 04Review the operation
Inspect recordings, wait time, transfer history, dispositions, quality signals, and follow-up ownership.
Bring your own voice worker over LiveKit or PCM16.
Use a media bridge when your application owns speech, reasoning, or orchestration. Virturing continues to own the number and telecom call state.
01const session = await virturing.media.create({02 callId: call.id,03 transport: "websocket",04 format: { codec: "pcm16", sampleRate: 16000 },05 events: ["media.started", "media.stopped", "call.completed"]06});0708// Connect with session.url and session.token.09// Refresh short-lived credentials before they expire.Authenticate the upgrade, validate the expected call identifier, handle reconnects, and stop sending audio as soon as the call closes.
Verify first. Acknowledge fast. Process once.
Verify the signature against the untouched request body, reject stale timestamps, return success quickly, and deduplicate with the event ID.
01import { verifyWebhook } from "@virturing/sdk/webhooks";0203export async function POST(request: Request) {04 const rawBody = await request.text();05 const event = verifyWebhook({06 rawBody,07 signature: request.headers.get("x-virturing-signature"),08 secret: process.env.VIRTURING_WEBHOOK_SECRET09 });1011 await processOnce(event.id, event);12 return new Response(null, { status: 204 });13}Recordings, transcripts, and outcomes are separate artifacts.
Enable recording only when the call purpose, notice, consent, access, and retention policy permit it. A recording-ready event links the artifacts to the call.
01{02 "id": "evt_01J7Q2K9",03 "type": "recording.ready",04 "callId": "call_01J7N6BMQP",05 "data": {06 "recordingId": "rec_01J7Q2JW",07 "transcriptId": "trn_01J7Q2K1",08 "durationSeconds": 184,09 "outcome": "case_created",10 "retentionPolicy": "support-90-days"11 }12}recordingIdThe audio artifact, governed by its configured access and retention policy.
transcriptIdThe timed transcript used for search, review, summaries, and handoff context.
outcomeA structured operational result such as resolved, booked, transferred, or follow-up required.
retentionPolicyThe named policy controlling expiry rather than an implicit permanent archive.
Campaigns wrap calls in contact policy.
Validate recipients, apply consent and suppression rules, constrain calling windows and concurrency, retry deliberately, and sync structured results.
01const campaign = await virturing.campaigns.create({02 name: "renewal-august",03 agent: "renewal-assistant@v4",04 recipients: customerIds,05 callingWindow: { timezone: "Asia/Colombo", from: "09:00", to: "17:00" },06 retries: { attempts: 2, delayMinutes: 90 },07 suppressionList: "global-opt-outs"08});The resource surface in one place.
SDK methods map onto versioned HTTP resources. Use the API directly when a generated or community client is a better fit.
/v1/numbersInventory, orders, leases, and capabilities/v1/routesDestinations, schedules, queues, and fallback/v1/callsCall creation, state, legs, and termination/v1/agentsVersions, tools, voices, and deployment/v1/call-centresFlows, queues, teams, and recording policy/v1/mediaLiveKit and signed PCM16 sessions/v1/campaignsRecipients, policy, progress, and outcomes/v1/recordingsAudio artifacts, transcripts, and retention/v1/eventsReplayable lifecycle and outcome events/v1/usageNumber, carrier, media, and agent metersRetry transport failures, not unclear business outcomes.
Every error has an HTTP status, stable code, request ID, and message. Use the request ID when correlating support and server logs.
400 / 422Invalid requestCorrect the payload; do not retry unchanged.401 / 403Credential or scopeFix the key, environment, or permission.409State conflictRead the resource before deciding the next action.429Rate limitedHonor Retry-After and use exponential backoff with jitter.5xxTemporary service faultRetry idempotent requests with a bounded backoff.Bring the target market, call direction, handler, tools, recording policy, and expected outcome.