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.
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_hereYou can also use ApiKey scheme:
Authorization: ApiKey qtv_your_api_key_hereRate Limits
Default rate limit is 1,000 requests per hour. Rate limit headers are included in responses:
X-RateLimit-Limit- Maximum requests per hourX-RateLimit-Remaining- Remaining requestsX-RateLimit-Reset- Time until limit resets
Calls API
/api/v1/callsList call history with filtering and pagination
Parameters
| page | integer | Page number (default: 1) |
| limit | integer | Results per page (max: 100, default: 50) |
| direction | string | Filter by direction: inbound, outbound |
| status | string | Filter by status: completed, missed, voicemail |
| from | string | Filter by caller phone number |
| to | string | Filter by destination phone number |
| start_date | ISO 8601 | Filter calls after this date |
| end_date | ISO 8601 | Filter 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
}
}/api/v1/callsInitiate 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"
}/api/v1/calls/{id}Get details of a specific call
SMS API
/api/v1/smsList SMS messages
Parameters
| page | integer | Page number |
| limit | integer | Results per page |
| direction | string | Filter: inbound, outbound |
| from | string | Filter by sender |
| to | string | Filter by recipient |
/api/v1/smsSend an SMS message
Request Body
{
"to": "+12155551234",
"message": "Hello from QTvoice!",
"from": "+12155555678" // optional
}Contacts API
/api/v1/contactsList contacts
Parameters
| search | string | Search by name, company, or email |
| phone | string | Search by phone number |
/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"
}
]
}/api/v1/contactsCreate a new contact
Request Body
{
"first_name": "John",
"last_name": "Doe",
"company": "Acme Inc",
"email": "john@acme.com",
"phone": "+12155551234",
"notes": "VIP customer"
}/api/v1/contacts/{id}Update a contact
/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 callcall.answered- Call was answeredcall.completed- Call endedcall.missed- Call was not answeredcall.voicemail- Voicemail was leftsms.received- SMS receivedsms.sent- SMS sentsms.delivered- SMS deliveredvoicemail.new- New voicemailvoicemail.transcribed- Voicemail transcribedcontact.created- Contact createdcontact.updated- Contact updatedWebhook 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 signatureX-QTvoice-Timestamp- Unix timestampX-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
/api/v1/voicemailsList voicemails
Parameters
| is_read | boolean | Filter by read status |
| from | string | Filter by caller |
/api/v1/extensionsList all extensions
Error Handling
Errors are returned with appropriate HTTP status codes and JSON body:
{
"error": "Invalid API key",
"code": "UNAUTHORIZED"
}Common Error Codes
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid request parameters |
| 401 | UNAUTHORIZED | Invalid or missing API key |
| 403 | FORBIDDEN | Missing required permission |
| 404 | NOT_FOUND | Resource not found |
| 429 | RATE_LIMITED | Rate limit exceeded |
| 500 | SERVER_ERROR | Internal server error |
Ready to Integrate?
Get started with the QTvoice API today. Create your API key and start building.
Get Your API Key