01 โ€” Quickstart

Up in under five minutes

From zero to a running multilingual voice agent. No telephony expertise needed.

01
Get your API key
Request early access at parlo-35.polsia.app. Your key ships in the onboarding email.
bash
# Set in your environment
export PARLO_API_KEY="parlo_live_xxxxxxxxxxxxxxxx"
02
Install the SDK
Official SDKs for Node.js, Python, and Go. Or call the REST API directly.
shell
# Node.js
npm install @parlo/sdk

# Python
pip install parlo

# Go
go get github.com/parlo-ai/go-sdk
03
Spin up your agent
Create a voice agent with a name, language detection mode, and instructions.
javascript
const agent = await client.agents.create({
  name: 'support-agent',
  language: 'auto',       // auto-detect any of 50+ languages
  voice: 'nova',
  instructions: 'You are a helpful support agent.'
});
04
Connect a phone number or SIP trunk
Assign a DID or point your SIP trunk at Parlo's ingest endpoint. The agent handles the rest.
javascript
// Provision a phone number
const number = await client.numbers.provision({
  country: 'US',
  agentId: agent.id
});

// Or use your own SIP trunk
await client.agents.update(agent.id, {
  sipIngest: 'sip:ingest.parlo.ai'
});
05
Handle events via webhook
Register a webhook URL to receive call lifecycle events, transcripts, and escalation triggers.
javascript
// Express handler โ€” receives signed POST requests
app.post('/webhooks/parlo', (req, res) => {
  const { event, call, transcript } = req.body;

  if (event === 'call.ended') {
    saveTranscript(call.id, transcript);
  }
  res.sendStatus(200);
});
02 โ€” SDK Examples

Agent ยท call ยท stream

Full examples for creating an agent, starting a call, and consuming the WebSocket audio stream.

import { ParloClient } from '@parlo/sdk';
import WebSocket from 'ws';

const client = new ParloClient({ apiKey: process.env.PARLO_API_KEY });

// โ”€โ”€ 1. Create agent
const agent = await client.agents.create({
  name:         'support-agent',
  language:     'auto',
  voice:        'nova',
  instructions: 'You are a helpful multilingual support agent. '
                + 'Respond in the caller\'s language. Be concise.'
});
console.log('Agent:', agent.id); // agt_01j9k...

// โ”€โ”€ 2. Outbound call
const call = await client.calls.create({
  agentId:  agent.id,
  to:       '+1-555-0100',
  from:     '+1-555-0199',
  metadata: { ticketId: 'TKT-4411' },
  webhook:  'https://your-server.com/webhooks/parlo'
});
console.log('Call:', call.id); // call_01j9k...

// โ”€โ”€ 3. Connect WebSocket stream (raw PCM-16 audio)
const ws = new WebSocket(
  `wss://stream.parlo.ai/v1/calls/${call.id}`,
  { headers: { 'Authorization': `Bearer ${process.env.PARLO_API_KEY}` } }
);

ws.on('message', (raw) => {
  const msg = JSON.parse(raw);

  switch (msg.type) {
    case 'transcript.final':
      console.log(`[${msg.lang}] ${msg.speaker}: ${msg.text}`);
      break;
    case 'language.detected':
      console.log('Detected:', msg.language, 'confidence:', msg.confidence);
      break;
    case 'call.ended':
      ws.close();
      break;
  }
});
import os
import json
import websocket
from parlo import ParloClient

client = ParloClient(api_key=os.environ["PARLO_API_KEY"])

# โ”€โ”€ 1. Create agent
agent = client.agents.create(
    name="support-agent",
    language="auto",
    voice="nova",
    instructions=(
        "You are a helpful multilingual support agent. "
        "Respond in the caller's language. Be concise."
    )
)
print(f"Agent: {agent.id}")  # agt_01j9k...

# โ”€โ”€ 2. Outbound call
call = client.calls.create(
    agent_id=agent.id,
    to="+1-555-0100",
    from_="+1-555-0199",
    metadata={"ticket_id": "TKT-4411"},
    webhook="https://your-server.com/webhooks/parlo"
)
print(f"Call: {call.id}")  # call_01j9k...

# โ”€โ”€ 3. WebSocket stream
def on_message(ws, message):
    msg = json.loads(message)
    if msg["type"] == "transcript.final":
        print(f"[{msg['lang']}] {msg['speaker']}: {msg['text']}")
    elif msg["type"] == "language.detected":
        print(f"Detected: {msg['language']}")
    elif msg["type"] == "call.ended":
        ws.close()

ws_app = websocket.WebSocketApp(
    f"wss://stream.parlo.ai/v1/calls/{call.id}",
    header=[f"Authorization: Bearer {os.environ['PARLO_API_KEY']}"],
    on_message=on_message
)
ws_app.run_forever()
package main

import (
    "fmt"
    "os"
    "github.com/parlo-ai/go-sdk/parlo"
)

func main() {
    client := parlo.New(os.Getenv("PARLO_API_KEY"))

    // โ”€โ”€ 1. Create agent
    agent, err := client.Agents.Create(parlo.AgentParams{
        Name:         "support-agent",
        Language:     "auto",
        Voice:        "nova",
        Instructions: "You are a helpful multilingual support agent.",
    })
    if err != nil { panic(err) }
    fmt.Println("Agent:", agent.ID)

    // โ”€โ”€ 2. Outbound call
    call, err := client.Calls.Create(parlo.CallParams{
        AgentID:  agent.ID,
        To:       "+1-555-0100",
        From:     "+1-555-0199",
        Metadata: map[string]any{"ticketId": "TKT-4411"},
        Webhook:  "https://your-server.com/webhooks/parlo",
    })
    if err != nil { panic(err) }
    fmt.Println("Call:", call.ID)

    // โ”€โ”€ 3. WebSocket stream (goroutine)
    stream, err := client.Calls.Stream(call.ID)
    if err != nil { panic(err) }
    defer stream.Close()

    for msg := range stream.Messages() {
        switch msg.Type() {
        case parlo.EventTranscriptFinal:
            t := msg.(parlo.TranscriptEvent)
            fmt.Printf("[%s] %s: %s\n", t.Lang, t.Speaker, t.Text)
        case parlo.EventCallEnded:
            return
        }
    }
}
# โ”€โ”€ 1. Create agent
curl -X POST https://api.parlo.ai/v1/agents \
  -H "Authorization: Bearer $PARLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "support-agent",
    "language": "auto",
    "voice": "nova",
    "instructions": "You are a helpful multilingual support agent."
  }'

# Response:
# { "id": "agt_01j9kxxxxxx", "name": "support-agent", "language": "auto" }

# โ”€โ”€ 2. Start a call
curl -X POST https://api.parlo.ai/v1/calls \
  -H "Authorization: Bearer $PARLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agt_01j9kxxxxxx",
    "to": "+1-555-0100",
    "webhook": "https://your-server.com/webhooks/parlo"
  }'

# โ”€โ”€ 3. Fetch call status
curl https://api.parlo.ai/v1/calls/call_01j9kxxxxxx \
  -H "Authorization: Bearer $PARLO_API_KEY"

# โ”€โ”€ 4. Get transcript
curl https://api.parlo.ai/v1/transcripts/call_01j9kxxxxxx \
  -H "Authorization: Bearer $PARLO_API_KEY"
03 โ€” REST API

Core endpoints

Base URL: https://api.parlo.ai/v1 โ€” All requests require Authorization: Bearer <key>

Method Endpoint Description
POST /agents Create a voice agent with name, language, voice, and system instructions. Returns agent ID used to start calls.
GET /agents/:agentId Retrieve agent configuration, voice, language settings, and associated phone numbers.
POST /calls Initiate an outbound call or register an inbound call session. Returns call ID and WebSocket stream URL.
GET /calls/:callId Fetch call status, duration, detected language, and metadata. States: queued โ†’ ringing โ†’ active โ†’ ended.
POST /calls/:callId/transfer Warm or cold transfer an active call to a SIP URI or E.164 number. Optionally pass a JSON context object to the destination.
GET /transcripts/:callId Full call transcript with per-turn language tags, speaker labels, timestamps, and confidence scores.
POST /webhooks Register a webhook endpoint. Parlo signs every delivery with HMAC-SHA256. Retry policy: exponential backoff, 3 attempts.
GET /numbers List provisioned phone numbers, their assigned agents, and inbound call statistics broken down by country and language.
04 โ€” WebSocket

Streaming event types

Connect to wss://stream.parlo.ai/v1/calls/:callId for real-time audio and transcript events.

audio.in
Caller audio chunk โ€” base64-encoded PCM-16 at 16kHz mono. 20ms frames.
audio.out
Agent synthesis audio chunk โ€” same encoding. Use to record the full call.
transcript.partial
Low-latency in-progress transcript. Updates as the speaker continues. Not final.
transcript.final
Confirmed segment with speaker label, language tag, and confidence โ‰ฅ 0.85.
language.detected
Fired once on initial detection. BCP-47 language code + confidence score.
code_switch
Mid-call language switch detected. Contains previous and new language codes.
agent.speaking
Agent started (state: "start") or finished (state: "end") a turn.
call.ended
Call terminated. Includes reason, final duration, and language summary.
javascript โ€” event shape
// transcript.final
{
  type:       "transcript.final",
  callId:    "call_01j9k...",
  speaker:   "caller",  // | "agent"
  text:      "Tengo un problema con mi pedido",
  lang:      "es",
  confidence: 0.97,
  startMs:   4120,
  endMs:     6440
}

// language.detected
{
  type:       "language.detected",
  callId:    "call_01j9k...",
  language:  "es",
  confidence: 0.99,
  detectedMs: 820
}

// code_switch
{
  type:     "code_switch",
  callId:  "call_01j9k...",
  from:    "es",
  to:      "en",
  atMs:    12300
}
05 โ€” Webhooks

Event payloads

All webhook deliveries are HMAC-SHA256 signed. Verify with the X-Parlo-Signature header against your webhook secret.

call.started
Call connected, agent is active. Includes caller number, detected language, and agent ID.
call.ended
Call terminated for any reason. Includes duration, hangup cause, and primary language spoken.
transcript.completed
Full transcript ready, typically within 2 seconds of call.ended. Includes all turns with language tags.
language.changed
Mid-call language switch confirmed. Includes previous language, new language, and switch timestamp.
escalation.triggered
Agent determined human handoff is needed. Includes intent summary, caller language, and transcript context.
json โ€” call.ended payload
{
  "event":    "call.ended",
  "version": "2024-01",
  "call": {
    "id":           "call_01j9kxxxxxx",
    "agentId":      "agt_01j9kxxxxxx",
    "direction":    "inbound",
    "from":         "+52-555-0100",
    "to":           "+1-800-555-0199",
    "startedAt":   "2026-05-06T22:14:08Z",
    "endedAt":     "2026-05-06T22:17:34Z",
    "durationSec": 206,
    "hangupCause": "caller_hangup",
    "language":    "es",
    "languageLog": ["es", "en"],
    "metadata":    { "ticketId": "TKT-4411" }
  },
  "resolved": true,
  "escalated": false
}
Start building

Get your API key.

Early access is open. Keys ship in the onboarding email within 48 hours. First 250 minutes on us.