QTvoice Developer API

Integrate QTvoice with your CRM or business application. Access calls, SMS, contacts, and receive real-time webhooks.

Calls API

Access call history, initiate click-to-call, get call recordings

SMS API

Send and receive SMS messages programmatically

Contacts API

Sync contacts, screen pop for incoming calls

Webhooks

Real-time event notifications for calls, SMS, voicemail

Voicemail API

Access voicemails with transcriptions

Extensions API

Manage extensions and routing

Quick Start

1. Get Your API Key

Log in to your QTvoice dashboard and navigate to Settings → API Keys. Create a new API key with the permissions you need.

Important: Your API key is shown only once. Store it securely!

2. Make Your First Request

curl -X GET "https://test.qtvoice.com/api/v1/calls" \
  -H "Authorization: Bearer qtv_your_api_key_here" \
  -H "Content-Type: application/json"

3. Set Up Webhooks (Optional)

Register webhook endpoints to receive real-time notifications when calls come in, SMS messages are received, or voicemails are left.

Authentication

All API requests require authentication using an API key. Include your key in theAuthorization header:

Authorization: Bearer qtv_your_api_key_here

You can also use ApiKey scheme:

Authorization: ApiKey qtv_your_api_key_here

Rate Limits

Default rate limit is 1,000 requests per hour. Rate limit headers are included in responses:

  • X-RateLimit-Limit - Maximum requests per hour
  • X-RateLimit-Remaining - Remaining requests
  • X-RateLimit-Reset - Time until limit resets

Calls API

GET/api/v1/calls

List call history with filtering and pagination

Parameters

pageintegerPage number (default: 1)
limitintegerResults per page (max: 100, default: 50)
directionstringFilter by direction: inbound, outbound
statusstringFilter by status: completed, missed, voicemail
fromstringFilter by caller phone number
tostringFilter by destination phone number
start_dateISO 8601Filter calls after this date
end_dateISO 8601Filter calls before this date

Response

{
  "data": [
    {
      "id": "call_abc123",
      "callSid": "CA1234567890",
      "from": "+12155551234",
      "to": "+12155555678",
      "direction": "inbound",
      "status": "completed",
      "duration": 145,
      "recordingUrl": "https://...",
      "createdAt": "2024-01-15T10:30:00Z",
      "answeredAt": "2024-01-15T10:30:05Z",
      "endedAt": "2024-01-15T10:32:30Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 1234,
    "totalPages": 25
  }
}
POST/api/v1/calls

Initiate an outbound call (click-to-call)

Request Body

{
  "to": "+12155551234",
  "from": "+12155555678",  // optional
  "extension_id": "ext_abc123"  // optional
}

Response

{
  "id": "call_xyz789",
  "status": "initiated",
  "from": "+12155555678",
  "to": "+12155551234",
  "message": "Call initiation requested"
}
GET/api/v1/calls/{id}

Get details of a specific call

SMS API

GET/api/v1/sms

List SMS messages

Parameters

pageintegerPage number
limitintegerResults per page
directionstringFilter: inbound, outbound
fromstringFilter by sender
tostringFilter by recipient
POST/api/v1/sms

Send an SMS message

Request Body

{
  "to": "+12155551234",
  "message": "Hello from QTvoice!",
  "from": "+12155555678"  // optional
}

Contacts API

GET/api/v1/contacts

List contacts

Parameters

searchstringSearch by name, company, or email
phonestringSearch by phone number
GET/api/v1/contacts/lookup?phone={number}

Look up contact by phone number (for screen pop). Returns contact info and recent call history.

Response

{
  "found": true,
  "contact": {
    "id": "contact_123",
    "first_name": "John",
    "last_name": "Doe",
    "company": "Acme Inc",
    "email": "john@acme.com",
    "phone": "+12155551234"
  },
  "recent_calls": [
    {
      "id": "call_abc",
      "direction": "inbound",
      "status": "completed",
      "duration": 120,
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ]
}
POST/api/v1/contacts

Create a new contact

Request Body

{
  "first_name": "John",
  "last_name": "Doe",
  "company": "Acme Inc",
  "email": "john@acme.com",
  "phone": "+12155551234",
  "notes": "VIP customer"
}
PUT/api/v1/contacts/{id}

Update a contact

DELETE/api/v1/contacts/{id}

Delete a contact

Webhooks

Webhook Setup

Webhooks allow your application to receive real-time notifications when events occur. Register your webhook endpoint in the QTvoice dashboard under Settings → Webhooks.

Available Events

call.incoming- New incoming call
call.answered- Call was answered
call.completed- Call ended
call.missed- Call was not answered
call.voicemail- Voicemail was left
sms.received- SMS received
sms.sent- SMS sent
sms.delivered- SMS delivered
voicemail.new- New voicemail
voicemail.transcribed- Voicemail transcribed
contact.created- Contact created
contact.updated- Contact updated

Webhook Payload

Webhooks are sent as POST requests with JSON body:

{
  "event": "call.incoming",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "id": "call_abc123",
    "from": "+12155551234",
    "to": "+12155555678",
    "direction": "inbound"
  }
}

Verifying Webhook Signatures

Each webhook request includes a signature for verification:

  • X-QTvoice-Signature - HMAC-SHA256 signature
  • X-QTvoice-Timestamp - Unix timestamp
  • X-QTvoice-Delivery-ID - Unique delivery ID

Verify the signature like this:

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Voicemails & Extensions

GET/api/v1/voicemails

List voicemails

Parameters

is_readbooleanFilter by read status
fromstringFilter by caller
GET/api/v1/extensions

List all extensions

Error Handling

Errors are returned with appropriate HTTP status codes and JSON body:

{
  "error": "Invalid API key",
  "code": "UNAUTHORIZED"
}

Common Error Codes

StatusCodeDescription
400BAD_REQUESTInvalid request parameters
401UNAUTHORIZEDInvalid or missing API key
403FORBIDDENMissing required permission
404NOT_FOUNDResource not found
429RATE_LIMITEDRate limit exceeded
500SERVER_ERRORInternal server error

Ready to Integrate?

Get started with the QTvoice API today. Create your API key and start building.

Get Your API Key