Voice360 API Documentation

Build powerful integrations with our comprehensive REST API

RESTful API
Secure Authentication
Real-time Data
99.9% Uptime

API Overview

The Voice360 API v3 provides programmatic access to your Voice360 account, enabling you to integrate telephony capabilities into your applications, build custom dashboards, and automate workflows.

Clean Architecture

RESTful design with predictable resource-oriented URLs and standard HTTP response codes.

Secure by Default

All API calls use HTTPS. Authentication via API key in request headers.

High Performance

Optimized for speed with response times under 200ms for most endpoints.

Developer Friendly

Comprehensive documentation, code examples in multiple languages, and Postman collections.

Real-time Data

Access live user availability, queue status, and call information as it happens.

Scalable

Built to handle thousands of requests per second with automatic scaling.

Authentication

The Voice360 API uses API Key authentication for all requests. Pass your API key in the request headers for secure access.

Authentication is moving to headers! Starting with v3, all authentication tokens should be passed in request headers rather than URL parameters for improved security.

How to Authenticate

API Key Authentication

Use your API key in the X-API-Key header for all authenticated requests.

HTTP Header
X-API-Key: your_api_key_here

Permissions: Full access to all non-administrative endpoints

Rate Limit: 1000 requests per minute

Public Endpoints (No Authentication)

Limited endpoints available without authentication for status pages and public dashboards.

Available Endpoints:

  • User availability status (online/offline only)
  • Queue basic information
  • Queue availability (agent counts)

Rate Limit: 100 requests per minute per IP

Base URL & Versioning

Production Environment

Base URL
https://api.voice360.app/v3/voice
All API requests must be made over HTTPS. Calls made over plain HTTP will be redirected to HTTPS automatically.

Response Format

All API responses follow a consistent JSON structure for predictable integration:

Standard Response
{
  "result": {
    // Response data goes here
  },
  "error": false,
  "message": "Success",
  "timestamp": "2024-01-15T10:30:00Z"
}
Error Response
{
  "result": null,
  "error": true,
  "message": "Invalid API key provided",
  "error_code": "AUTH_INVALID_KEY",
  "timestamp": "2024-01-15T10:30:00Z"
}

Response Fields

result object/array The actual response data. Will be null on error.
error boolean Indicates if the request was successful (false) or failed (true).
message string Human-readable message about the response.
error_code string Machine-readable error code (only present on errors).
timestamp string ISO 8601 timestamp of the response.

User Management Endpoints

GET /v3/voice/{account_id}/availability

Get real-time availability status for all users in an account. Shows online/offline state and active calls.

Optional Auth

Parameters

Parameter Type Required Description
account_id integer Required Your Voice360 account ID

Response Fields

pk integer User ID
presence_id string User's extension number
callerID string User's display name
first_name string User's first name
last_name string User's last name
devices_registered boolean Online status (true = online, false = offline)
channels array Array of active calls (requires authentication)

Example Response

JSON
{
  "result": [
    {
      "pk": 123,
      "presence_id": "1001",
      "callerID": "John Smith",
      "first_name": "John",
      "last_name": "Smith",
      "devices_registered": true,
      "channels": [
        {
          "to": "5551234",
          "from": "1001",
          "call_seconds": 45,
          "direction": "outbound"
        }
      ]
    }
  ],
  "error": false,
  "message": "User availability data"
}

Queue Operations

GET /v3/voice/{account_id}/queues

List all queues in your account. Internal system queues are automatically filtered out.

Auth Required

Response Example

JSON
{
  "result": [
    {
      "pk": 100134,
      "name": "100134",
      "queue_name": "Sales Queue",
      "extension": "8001",
      "strategy": "ringall",
      "musiconhold": "default",
      "timeout": 20,
      "retry": 5,
      "wrapuptime": 10,
      "maxlen": 0,
      "joinempty": "yes",
      "leavewhenempty": "no",
      "ringinuse": "no"
    },
    {
      "pk": 100135,
      "name": "100135",
      "queue_name": "Support Queue",
      "extension": "8002",
      "strategy": "fewestcalls",
      "musiconhold": "default",
      "timeout": 30,
      "retry": 5,
      "wrapuptime": 10,
      "maxlen": 0,
      "joinempty": "yes",
      "leavewhenempty": "no",
      "ringinuse": "no"
    }
  ],
  "error": false,
  "message": "List of queues"
}
GET /v3/voice/{account_id}/queues/{queue_id}

Get detailed information about a specific queue including configuration and assigned users.

Auth Required

Response Fields

pk integer Queue ID
name string Queue identifier (e.g. "100134")
queue_name string User-friendly queue name
extension string Queue extension number
strategy string Ring strategy (ringall, fewestcalls, random, etc.)
musiconhold string Music on hold class
timeout integer Ring timeout in seconds
retry integer Retry interval in seconds
wrapuptime integer Wrap-up time in seconds
maxlen integer Maximum queue length (0 = unlimited)
joinempty string Allow joining empty queue
leavewhenempty string Leave when queue becomes empty
ringinuse string Ring members already on calls
assigned_users array Array of assigned queue members

Queue Availability

GET /v3/voice/{account_id}/availability/queues

Get real-time agent availability metrics for all queues. Shows online agents and call activity.

Auth Required

Response Example

JSON
{
  "result": [
    {
      "pk": 100134,
      "name": "100134",
      "queue_name": "Sales Queue",
      "extension": "8001",
      "is_ready": true,
      "agents_online": 3,
      "agents_available": 2,
      "agents_on_call": 1,
      "active_calls": 5
    }
  ],
  "error": false,
  "message": "Queue availability data"
}
GET /v3/voice/{account_id}/availability/queues/{queue_id}

Get detailed availability for a specific queue.

Auth Required

Response Fields

pk integer Queue ID
name string Queue ID/number
queue_name string User-friendly queue name
extension string Queue extension number
is_ready boolean Queue has at least one online agent
agents_online integer Total agents logged in
agents_available integer Agents online but not on calls
agents_on_call integer Agents currently on calls
active_calls integer Active calls in this queue

Call Management

POST /v3/voice/{account_id}/call/outbound

Initiate an outbound call from an extension to an external number.

Auth Required

Request Body

Field Type Required Description
from string Required Extension number making the call
to string Required Destination phone number
caller_id string Optional caller ID to display
recording boolean Enable call recording (default: false)

Example Request

cURL
curl -X POST https://api.voice360.app/v3/voice/61/call/outbound \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "1001",
    "to": "+15551234567",
    "caller_id": "+15559876543",
    "recording": true
  }'

Example Response

JSON
{
  "result": {
    "call_id": "c12345-67890-abcdef",
    "status": "initiating",
    "from": "1001",
    "to": "+15551234567",
    "timestamp": "2024-01-15T10:30:00Z"
  },
  "error": false,
  "message": "Call initiated successfully"
}

SMS Services

POST /v3/voice/{account_id}/sms/send

Send an SMS message from your Voice360 phone number.

Auth Required

Request Body

Field Type Required Description
from string Required Your Voice360 phone number
to string Required Recipient phone number
message string Required SMS message content (max 160 chars)

Example Request

JavaScript
const sendSMS = async () => {
  const response = await fetch('https://api.voice360.app/v3/voice/61/sms/send', {
    method: 'POST',
    headers: {
      'X-API-Key': 'your_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      from: '+15559876543',
      to: '+15551234567',
      message: 'Hello from Voice360!'
    })
  });

  const result = await response.json();
  console.log(result);
};

Code Examples

Complete examples showing how to integrate with the Voice360 API in popular programming languages.

bash
#!/bin/bash

# Set your API credentials
API_KEY="your_api_key"
ACCOUNT_ID="61"
BASE_URL="https://api.voice360.app/v3/voice"

# Get user availability
echo "Fetching user availability..."
curl -H "X-API-Key: $API_KEY" \
  "$BASE_URL/$ACCOUNT_ID/availability"

# List all queues
echo "Fetching queues..."
curl -H "X-API-Key: $API_KEY" \
  "$BASE_URL/$ACCOUNT_ID/queues"

# Get queue availability
echo "Fetching queue availability..."
curl -H "X-API-Key: $API_KEY" \
  "$BASE_URL/$ACCOUNT_ID/availability/queues"

# Initiate an outbound call
echo "Initiating outbound call..."
curl -X POST "$BASE_URL/$ACCOUNT_ID/call/outbound" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "1001",
    "to": "+15551234567",
    "recording": true
  }'
JavaScript
class Voice360API {
  constructor(apiKey, accountId) {
    this.apiKey = apiKey;
    this.accountId = accountId;
    this.baseUrl = 'https://api.voice360.app/v3/voice';
  }

  async request(endpoint, options = {}) {
    const url = `${this.baseUrl}/${this.accountId}${endpoint}`;
    const response = await fetch(url, {
      ...options,
      headers: {
        'X-API-Key': this.apiKey,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.status} ${response.statusText}`);
    }

    return response.json();
  }

  // User methods
  async getUserAvailability() {
    return this.request('/availability');
  }

  // Queue methods
  async getQueues() {
    return this.request('/queues');
  }

  async getQueueDetails(queueId) {
    return this.request(`/queues/${queueId}`);
  }

  async getQueueAvailability(queueId = null) {
    const endpoint = queueId
      ? `/availability/queues/${queueId}`
      : '/availability/queues';
    return this.request(endpoint);
  }

  // Call methods
  async initiateCall(from, to, options = {}) {
    return this.request('/call/outbound', {
      method: 'POST',
      body: JSON.stringify({ from, to, ...options })
    });
  }

  // SMS methods
  async sendSMS(from, to, message) {
    return this.request('/sms/send', {
      method: 'POST',
      body: JSON.stringify({ from, to, message })
    });
  }
}

// Usage example
async function main() {
  const api = new Voice360API('your_api_key', 61);

  try {
    // Get all online users
    const availability = await api.getUserAvailability();
    const onlineUsers = availability.result.filter(u => u.devices_registered);
    console.log(`${onlineUsers.length} users online`);

    // Check queue status
    const queues = await api.getQueueAvailability();
    const readyQueues = queues.result.filter(q => q.is_ready);
    console.log(`${readyQueues.length} queues have agents available`);

    // Make an outbound call
    const call = await api.initiateCall('1001', '+15551234567', {
      caller_id: '+15559876543',
      recording: true
    });
    console.log(`Call initiated: ${call.result.call_id}`);

  } catch (error) {
    console.error('API Error:', error);
  }
}

main();
Python
import requests
import json
from typing import Optional, Dict, Any

class Voice360API:
    """Voice360 API Client for Python"""

    def __init__(self, api_key: str, account_id: int):
        self.api_key = api_key
        self.account_id = account_id
        self.base_url = 'https://api.voice360.app/v3/voice'
        self.session = requests.Session()
        self.session.headers.update({
            'X-API-Key': api_key,
            'Content-Type': 'application/json'
        })

    def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]:
        """Make an API request"""
        url = f'{self.base_url}/{self.account_id}{endpoint}'
        response = self.session.request(method, url, **kwargs)
        response.raise_for_status()
        return response.json()

    def get_user_availability(self) -> Dict[str, Any]:
        """Get user availability status"""
        return self._request('GET', '/availability')

    def get_queues(self) -> Dict[str, Any]:
        """List all queues"""
        return self._request('GET', '/queues')

    def get_queue_details(self, queue_id: int) -> Dict[str, Any]:
        """Get details for a specific queue"""
        return self._request('GET', f'/queues/{queue_id}')

    def get_queue_availability(self, queue_id: Optional[int] = None) -> Dict[str, Any]:
        """Get queue availability metrics"""
        endpoint = f'/availability/queues/{queue_id}' if queue_id else '/availability/queues'
        return self._request('GET', endpoint)

    def initiate_call(self, from_ext: str, to_number: str, **options) -> Dict[str, Any]:
        """Initiate an outbound call"""
        data = {'from': from_ext, 'to': to_number, **options}
        return self._request('POST', '/call/outbound', json=data)

    def send_sms(self, from_number: str, to_number: str, message: str) -> Dict[str, Any]:
        """Send an SMS message"""
        data = {'from': from_number, 'to': to_number, 'message': message}
        return self._request('POST', '/sms/send', json=data)


def main():
    # Initialize the API client
    api = Voice360API('your_api_key', 61)

    try:
        # Get user availability
        availability = api.get_user_availability()
        online_users = [u for u in availability['result'] if u['devices_registered']]
        print(f"Online users: {len(online_users)}")

        # Check queue status
        queues = api.get_queue_availability()
        ready_queues = [q for q in queues['result'] if q['is_ready']]
        print(f"Queues with agents: {len(ready_queues)}")

        # Display queue details
        for queue in ready_queues:
            print(f"  - {queue['queue_name']}: {queue['agents_online']} agents online")

        # Initiate a call
        call = api.initiate_call(
            from_ext='1001',
            to_number='+15551234567',
            caller_id='+15559876543',
            recording=True
        )
        print(f"Call initiated: {call['result']['call_id']}")

        # Send an SMS
        sms = api.send_sms(
            from_number='+15559876543',
            to_number='+15551234567',
            message='Hello from Voice360!'
        )
        print(f"SMS sent: {sms['message']}")

    except requests.exceptions.RequestException as e:
        print(f"API Error: {e}")
    except KeyError as e:
        print(f"Unexpected response format: {e}")


if __name__ == '__main__':
    main()
PHP
<?php

class Voice360API {
    private $apiKey;
    private $accountId;
    private $baseUrl = 'https://api.voice360.app/v3/voice';

    public function __construct($apiKey, $accountId) {
        $this->apiKey = $apiKey;
        $this->accountId = $accountId;
    }

    private function request($method, $endpoint, $data = null) {
        $url = "{$this->baseUrl}/{$this->accountId}{$endpoint}";

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'X-API-Key: ' . $this->apiKey,
            'Content-Type: application/json'
        ]);

        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
        }

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode >= 400) {
            throw new Exception("API Error: HTTP {$httpCode}");
        }

        return json_decode($response, true);
    }

    public function getUserAvailability() {
        return $this->request('GET', '/availability');
    }

    public function getQueues() {
        return $this->request('GET', '/queues');
    }

    public function getQueueDetails($queueId) {
        return $this->request('GET', "/queues/{$queueId}");
    }

    public function getQueueAvailability($queueId = null) {
        $endpoint = $queueId
            ? "/availability/queues/{$queueId}"
            : '/availability/queues';
        return $this->request('GET', $endpoint);
    }

    public function initiateCall($from, $to, $options = []) {
        $data = array_merge(['from' => $from, 'to' => $to], $options);
        return $this->request('POST', '/call/outbound', $data);
    }

    public function sendSMS($from, $to, $message) {
        return $this->request('POST', '/sms/send', [
            'from' => $from,
            'to' => $to,
            'message' => $message
        ]);
    }
}

// Usage example
try {
    $api = new Voice360API('your_api_key', 61);

    // Get user availability
    $availability = $api->getUserAvailability();
    $onlineUsers = array_filter($availability['result'], function($u) {
        return $u['devices_registered'];
    });
    echo "Online users: " . count($onlineUsers) . "\n";

    // Check queue status
    $queues = $api->getQueueAvailability();
    foreach ($queues['result'] as $queue) {
        if ($queue['is_ready']) {
            echo "Queue {$queue['queue_name']}: {$queue['agents_online']} agents online\n";
        }
    }

    // Make a call
    $call = $api->initiateCall('1001', '+15551234567', [
        'caller_id' => '+15559876543',
        'recording' => true
    ]);
    echo "Call initiated: {$call['result']['call_id']}\n";

} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

?>
C#
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Text;
using Newtonsoft.Json;

public class Voice360API
{
    private readonly HttpClient client;
    private readonly string accountId;
    private readonly string baseUrl = "https://api.voice360.app/v3/voice";

    public Voice360API(string apiKey, int accountId)
    {
        this.accountId = accountId.ToString();
        client = new HttpClient();
        client.DefaultRequestHeaders.Add("X-API-Key", apiKey);
    }

    private async Task<T> RequestAsync<T>(HttpMethod method, string endpoint, object data = null)
    {
        var url = $"{baseUrl}/{accountId}{endpoint}";
        var request = new HttpRequestMessage(method, url);

        if (data != null)
        {
            var json = JsonConvert.SerializeObject(data);
            request.Content = new StringContent(json, Encoding.UTF8, "application/json");
        }

        var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();

        var responseJson = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<T>(responseJson);
    }

    public async Task<dynamic> GetUserAvailabilityAsync()
    {
        return await RequestAsync<dynamic>(HttpMethod.Get, "/availability");
    }

    public async Task<dynamic> GetQueuesAsync()
    {
        return await RequestAsync<dynamic>(HttpMethod.Get, "/queues");
    }

    public async Task<dynamic> InitiateCallAsync(string from, string to, object options = null)
    {
        var data = new { from, to };
        if (options != null)
        {
            // Merge options with data
            var json = JsonConvert.SerializeObject(data);
            var optionsJson = JsonConvert.SerializeObject(options);
            var merged = JsonConvert.DeserializeObject<dynamic>(json);
            var optionsObj = JsonConvert.DeserializeObject<dynamic>(optionsJson);
            foreach (var prop in optionsObj)
            {
                merged[prop.Name] = prop.Value;
            }
            data = merged;
        }

        return await RequestAsync<dynamic>(HttpMethod.Post, "/call/outbound", data);
    }
}

// Usage
class Program
{
    static async Task Main(string[] args)
    {
        var api = new Voice360API("your_api_key", 61);

        try
        {
            // Get user availability
            var availability = await api.GetUserAvailabilityAsync();
            Console.WriteLine($"Users fetched: {availability.result.Count}");

            // Get queues
            var queues = await api.GetQueuesAsync();
            Console.WriteLine($"Queues fetched: {queues.result.Count}");

            // Initiate a call
            var call = await api.InitiateCallAsync("1001", "+15551234567", new {
                caller_id = "+15559876543",
                recording = true
            });
            Console.WriteLine($"Call initiated: {call.result.call_id}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}
Java
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import java.util.HashMap;

public class Voice360API {
    private final HttpClient client;
    private final String apiKey;
    private final int accountId;
    private final String baseUrl = "https://api.voice360.app/v3/voice";
    private final ObjectMapper mapper;

    public Voice360API(String apiKey, int accountId) {
        this.apiKey = apiKey;
        this.accountId = accountId;
        this.client = HttpClient.newHttpClient();
        this.mapper = new ObjectMapper();
    }

    private Map<String, Object> request(String method, String endpoint, Map<String, Object> data) throws Exception {
        String url = baseUrl + "/" + accountId + endpoint;

        HttpRequest.Builder builder = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .header("X-API-Key", apiKey)
            .header("Content-Type", "application/json");

        if ("POST".equals(method) && data != null) {
            String json = mapper.writeValueAsString(data);
            builder.POST(HttpRequest.BodyPublishers.ofString(json));
        } else {
            builder.GET();
        }

        HttpRequest request = builder.build();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() >= 400) {
            throw new RuntimeException("API Error: " + response.statusCode());
        }

        return mapper.readValue(response.body(), Map.class);
    }

    public Map<String, Object> getUserAvailability() throws Exception {
        return request("GET", "/availability", null);
    }

    public Map<String, Object> getQueues() throws Exception {
        return request("GET", "/queues", null);
    }

    public Map<String, Object> initiateCall(String from, String to, Map<String, Object> options) throws Exception {
        Map<String, Object> data = new HashMap<>();
        data.put("from", from);
        data.put("to", to);
        if (options != null) {
            data.putAll(options);
        }
        return request("POST", "/call/outbound", data);
    }

    public static void main(String[] args) {
        Voice360API api = new Voice360API("your_api_key", 61);

        try {
            // Get user availability
            Map<String, Object> availability = api.getUserAvailability();
            System.out.println("Availability: " + availability);

            // Get queues
            Map<String, Object> queues = api.getQueues();
            System.out.println("Queues: " + queues);

            // Initiate call
            Map<String, Object> options = new HashMap<>();
            options.put("caller_id", "+15559876543");
            options.put("recording", true);

            Map<String, Object> call = api.initiateCall("1001", "+15551234567", options);
            System.out.println("Call initiated: " + call);

        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }
}

Support & Resources

API Support

Get help with API integration and technical questions.

Contact Support →

Documentation

Comprehensive API documentation with examples and guides.

You're already here!

Code Examples

Working examples in multiple programming languages.

View Examples →

Rate Limits

API rate limits are enforced to ensure fair usage and maintain service quality for all users.

Authentication Type Rate Limit Window Headers Returned
API Key 1000 requests Per minute X-RateLimit-Limit, X-RateLimit-Remaining
No Auth (Public) 100 requests Per minute per IP X-RateLimit-Limit, X-RateLimit-Remaining
Need higher limits? Contact our sales team at sales@voice360.app to discuss enterprise rate limits.

Error Handling

The API uses standard HTTP status codes to indicate success or failure of requests.

Status Code Error Code Description
200 - Success - Request completed successfully
400 BAD_REQUEST Invalid request parameters or malformed request
401 AUTH_REQUIRED Authentication required but not provided
403 AUTH_INVALID Invalid API key or insufficient permissions
404 NOT_FOUND Requested resource not found
429 RATE_LIMITED Too many requests - rate limit exceeded
500 INTERNAL_ERROR Internal server error - please try again
503 SERVICE_UNAVAILABLE Service temporarily unavailable

Error Response Example

JSON
{
  "result": null,
  "error": true,
  "message": "Invalid API key provided",
  "error_code": "AUTH_INVALID",
  "details": {
    "provided_key": "partial_key_xxx...",
    "help": "Please check your API key at https://voice360.app/settings/api"
  },
  "timestamp": "2024-01-15T10:30:00Z"
}