API Reference v1

PhoneVoice API

Build the future of voice communication.

Make a Call

Pro Tip: Seamlessly integrate our voice AI capabilities into your own applications. Full control, low latency, and infinite scalability.

curl -X POST https://api.phonevoice.ai/v1/calls \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "",
    "assistant_id": "",
    "webhook_url": ""
  }'
const response = await fetch('https://api.phonevoice.ai/v1/calls', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phone_number: '',
    assistant_id: '',
    webhook_url: ''
  })
});

const data = await response.json();
console.log(data);
import requests

url = "https://api.phonevoice.ai/v1/calls"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
}
data = {
    "phone_number": "",
    "assistant_id": "",
    "webhook_url": ""
}

response = requests.post(url, json=data, headers=headers)
print(response.json())
require 'uri'
require 'net/http'
require 'json'

uri = URI('https://api.phonevoice.ai/v1/calls')
req = Net::HTTP::Post.new(uri,
  'Authorization' => 'Bearer YOUR_API_KEY',
  'Content-Type' => 'application/json'
)
req.body = {
  phone_number: '',
  assistant_id: '',
  webhook_url: ''
}.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(req)
end

puts res.body
<?php
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://api.phonevoice.ai/v1/calls');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    'phone_number' => '',
    'assistant_id' => '',
    'webhook_url' => ''
]));

$headers = [
    'Authorization: Bearer YOUR_API_KEY',
    'Content-Type: application/json'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
curl_close($ch);
?>

Real-time Webhooks

Receive JSON payloads for call started, transcription updates, and call completed events. Use these to trigger actions in your own system.

Call Started

Event triggered immediately when the call connects. Contains call ID and initial metadata.

Transcription

Real-time alerts whenever a user speaks or the assistant responds.

Call Ended

Final webhook with duration, cost, and full recording URL.

POST /webhooks
{
  "event": "call.completed",
  "call_id": "call_873912bsd8",
  "timestamp": 1709218291,
  "data": {
    "duration_seconds": 142,
    "cost": 0.024,
    "recording_url": "https://api.phonevoice.ai/rec/...",
    "analysis": {
       "sentiment": "positive",
       "intent": "book_appointment"
    }
  }
}
                

HTTP Method & Headers

POST JSON Payload
PhoneVoice-Signature: t=1709...,v1=h8d9s...
Content-Type: application/json

Payload Fields

event
Event Name (e.g. call.completed)
call_id
Unique Call Identifier
timestamp
Unix Timestamp
data
Event Specific Data

Security & Verification

const crypto = require('crypto');

function verifyWebhook(req, secret) {
  const signature = req.headers['phonevoice-signature'];
  const [t, v1] = signature.split(',').map(p => p.split('=')[1]);
  
  const payload = `${t}.${JSON.stringify(req.body)}`;
  const computeParams = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
    
  return crypto.timingSafeEqual(
    Buffer.from(v1), 
    Buffer.from(computeParams)
  );
}
import hmac
import hashlib
import json

def verify_signature(request, secret):
    signature_header = request.headers.get('PhoneVoice-Signature')
    timestamp, signature = [p.split('=')[1] for p in signature_header.split(',')]
    
    payload = f"{timestamp}.{request.body.decode('utf-8')}"
    computed_signature = hmac.new(
        key=secret.encode('utf-8'),
        msg=payload.encode('utf-8'),
        digestmod=hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, computed_signature)
require 'openssl'

def verify_webhook(request, secret)
  signature_header = request.headers['PhoneVoice-Signature']
  timestamp = signature_header.split(',').first.split('=').last
  signature = signature_header.split(',').last.split('=').last

  payload = "#{timestamp}.#{request.body.read}"
  computed_signature = OpenSSL::HMAC.hexdigest(
    OpenSSL::Digest.new('sha256'), 
    secret, 
    payload
  )

  ActiveSupport::SecurityUtils.secure_compare(signature, computed_signature)
end
function verifyWebhook($payload, $headers, $secret) {
    $signatureHeader = $headers['PhoneVoice-Signature'];
    parse_str(str_replace(',', '&', $signatureHeader), $parts);
    
    $timestamp = $parts['t'];
    $signature = $parts['v1'];
    
    $signedPayload = "$timestamp.$payload";
    $computedSignature = hash_hmac('sha256', $signedPayload, $secret);
    
    return hash_equals($signature, $computedSignature);
}
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "strings"
)

func VerifySignature(payload []byte, header string, secret string) bool {
    parts := strings.Split(header, ",")
    timestamp := strings.Split(parts[0], "=")[1]
    signature := strings.Split(parts[1], "=")[1]

    signedPayload := fmt.Sprintf("%s.%s", timestamp, string(payload))
    
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write([]byte(signedPayload))
    expectedMAC := hex.EncodeToString(mac.Sum(nil))
    
    return hmac.Equal([]byte(signature), []byte(expectedMAC))
}

Programmatic Call Control

Initiate, answer, and manage calls via simple HTTP requests.

Real-time Webhooks

Receive live events for every stage of the call (start, end, transcription, etc.).

Custom LLM Integration

Connect your own logic or LLM to control the agent's responses.

Translation missing: en.api_page.features.analytics.title

Translation missing: en.api_page.features.analytics.description