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 for managing calls, queues, SMS, and user data.

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

Voice360 supports two types of API keys. Both use the same X-API-Key header:

User API Key

For individual users accessing their own data.

Best For:
  • Mobile apps
  • Browser extensions
  • Personal integrations
Access:

Only your own profile, numbers, and call history

Key Format: abc123xyz...
Developer API Key

For account-level access to all data.

Best For:
  • Backend integrations
  • Dashboards
  • CRM integrations
Access:

All users, queues, and account-wide data

Key Format: v360_dev_...
Quick Comparison
Feature User Key Developer Key
Scope Single user Entire account
Access /user/* endpoints? ✅ Yes ❌ No
Access /queues, /availability? ❌ No ✅ Yes
HTTP Header (Both Key Types)
X-API-Key: your_api_key_here

💡 Pro Tip: Each endpoint in this documentation shows which key types it supports via colored badges. Look for User API Key or Developer API Key badges on each endpoint.

Rate Limit: 1000 requests per minute (applies to both key types)

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 Developer API Key

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 Developer API Key

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 Developer API Key

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 Developer API Key

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 Developer API Key

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 Developer API Key

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 User API Key Developer API Key

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);
};

User Profile & Numbers

GET /v3/voice/{account_id}/user/profile

Get the authenticated user's profile and extension details including voicemail settings, call forwarding, and device information.

Auth Required User API Key Only

Response Fields

pk integer User ID
presence_id string User's extension number
callerID string Display name for outbound calls
first_name string User's first name
last_name string User's last name
email string User's email address
voicemail_enabled boolean Whether voicemail is enabled
forward_enabled boolean Whether call forwarding is enabled
forward_number string Number to forward calls to

Example Response

JSON
{
  "result": {
    "pk": 123,
    "asterisk_user_id": 456,
    "presence_id": "1001",
    "callerID": "John Smith",
    "first_name": "John",
    "last_name": "Smith",
    "email": "john.smith@company.com",
    "voicemail_enabled": true,
    "forward_enabled": false,
    "forward_number": null,
    "time_zone": "America/New_York"
  },
  "error": false,
  "message": "User profile details"
}
GET /v3/voice/{account_id}/user/numbers

Get list of phone numbers (DIDs) assigned to the authenticated user for making calls and sending SMS.

Auth Required User API Key Only

Response Fields

pk integer Number ID
number string Phone number in E.164 format
friendly_name string User-friendly display name
sms_enabled boolean Whether SMS is enabled for this number
mms_enabled boolean Whether MMS is enabled for this number

Example Response

JSON
{
  "result": [
    {
      "pk": 789,
      "number": "+15551234567",
      "friendly_name": "Main Business Line",
      "sms_enabled": true,
      "mms_enabled": true
    },
    {
      "pk": 790,
      "number": "+15559876543",
      "friendly_name": "Support Line",
      "sms_enabled": true,
      "mms_enabled": false
    }
  ],
  "error": false,
  "message": "List of phone numbers assigned to user"
}

Example Request

JavaScript
const getUserNumbers = async () => {
  const response = await fetch('https://api.voice360.app/v3/voice/61/user/numbers', {
    method: 'GET',
    headers: {
      'X-API-Key': 'your_api_key'
    }
  });

  const result = await response.json();
  console.log('My phone numbers:', result.result);
};

Webhooks

Webhooks allow you to receive real-time notifications when events occur in your Voice360 account. Configure a webhook URL to receive HTTP POST requests for events like incoming calls, SMS messages, and queue activity.

How Webhooks Work

  1. Configure a webhook in your Voice360 portal with your endpoint URL and event type
  2. When the event occurs, Voice360 sends an HTTP POST request to your URL with event data
  3. Your server processes the webhook payload and responds with 200 OK
  4. If delivery fails, Voice360 automatically retries based on your retry configuration

Available Event Types

Call Events
INCOMING_EXTERNAL_CALL Fires when an external call comes in
CALL_ENDED Fires when any call ends
USER_DIAL Fires when a user initiates an outbound call
USER_ANSWER Fires when a user answers a call
USER_HANGUP Fires when an outbound call ends
SMS Events
SMS_RECEIVED Fires when an SMS is received
SMS_SENT Fires when an SMS is sent
SMS_DELIVERED Fires when carrier confirms delivery
Queue Events
QUEUE_NO_ANSWER Call not answered by any agent
QUEUE_HANGUP_TIMEOUT Caller times out waiting in queue
QUEUE_HANGUP_ABANDONED Caller hangs up while waiting

Example Webhook Payload

JSON
{
  "event_name": "SMS_RECEIVED",
  "account_id": "12345",
  "timestamp": 1704067200,
  "metadata": {
    "from_number": "+15551234567",
    "to_number": "+15559876543",
    "body": "Hello, this is a test message",
    "message_id": "msg_abc123"
  }
}

Configuring Webhooks

Webhooks are configured through the Voice360 portal at Settings → Webhooks. For each webhook, you'll configure:

  • Name: Descriptive name for the webhook
  • URL: Your endpoint URL (must be HTTPS in production)
  • Event Type: Which event to listen for
  • HTTP Method: GET or POST (POST recommended)
  • Retries: Number of retry attempts (1-5)
Best Practices
  • Always respond with 200 OK quickly (process asynchronously if needed)
  • Validate webhook payloads came from Voice360 (check source IP or add auth tokens to your URL)
  • Use HTTPS endpoints in production
  • Implement idempotency - you may receive the same event multiple times
  • Log all webhook requests for debugging

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());
        }
    }
}

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"
}