Read API Reference
The REST API gives your product access to the same data that Voicetta sends through webhooks.
Use it when you need:
- conversation history
- backfills
- recovery after downtime
- individual records
- reports
- an integration without webhooks
Base URL
https://api.voicetta.com/v1Collections
| Collection | Contains | Webhook event |
|---|---|---|
/v1/calls | Voice calls | call.completed |
/v1/messages | SMS and WhatsApp messages | message.received, message.sent |
/v1/threads | Completed SMS and WhatsApp conversations | thread.completed |
The same underlying objects are available through the API and webhooks.
Authentication
Every request requires an API key.
Create one in Settings → Developers.
Send it as a bearer token:
Authorization: Bearer vk_live_xxxxxxxxxxxxxxxxxxxxxxxxKeys are shown once.
If you lose a key, revoke it and create another one.
Each key belongs to one workspace.
Choosing what you can read
API keys have their own field permissions.
| Block | Contains | Default | Collections |
|---|---|---|---|
call | Record id, workspace, assistant, timestamps | Always | All |
customer | Name, phone, email, language, country | On | All |
costs | Cost breakdown | Off | All |
transcript | Turn-by-turn transcript | On | Calls, threads |
analysis | Summary, intent, outcome, sentiment | On | Calls, threads |
evaluations | Evaluation results | On | Calls, threads |
follow_ups | Follow-up state | Off | Calls, threads |
recording | Recording status and link | On | Calls |
performance_metrics | Speech, model, and voice latency | Off | Calls |
config_snapshot | Assistant configuration | Off | Calls |
You can further narrow a request with fields.
For example:
?fields=transcriptRequesting a field your key is not allowed to read returns 403.
GET /v1/calls
Returns voice calls, newest first.
Parameters
| Parameter | Type | Meaning |
|---|---|---|
cursor | string | Cursor from the previous page |
limit | integer | 1–100, default 25 |
from | ISO 8601 | Calls ending after this time |
to | ISO 8601 | Calls ending before this time |
assistant_id | UUID | Filter by assistant |
include_test | boolean | Include test calls |
fields | string | Requested field blocks |
Example:
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/calls?limit=50&from=2026-08-01T00:00:00Z&fields=transcript"Response:
{
"calls": [
{
"call_id": "9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11"
}
],
"has_more": true,
"next_cursor": "MjAyNi0wOC0yMFQxMDowMDowMCswMDowMHw5ZjhiMWM0ZQ"
}Pagination
Use cursor pagination.
Do not use offsets.
cursor=""
while :; do
page=$(curl -sH "Authorization: Bearer $KEY" \
"https://api.voicetta.com/v1/calls?limit=100&cursor=$cursor")
echo "$page" | jq -c '.calls[]'
[ "$(echo "$page" | jq -r '.has_more')" = "true" ] || break
cursor=$(echo "$page" | jq -r '.next_cursor')
doneThree rules:
- Stop when
has_moreis false. - Treat cursors as opaque strings.
- Do not construct or modify cursors.
GET /v1/calls/{call_id}
Returns one call.
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/calls/9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11"Response:
{
"call": {
"call_id": "9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11"
}
}You can use fields here too.
GET /v1/calls/{call_id}/recording
Returns a redirect to the audio file.
curl -L -o call.mp3 \
-H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/calls/9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11/recording"The redirect URL is temporary.
Do not store the redirected URL.
The recording.download_url in an archived Voicetta payload remains useful because it points to this stable Voicetta endpoint.
GET /v1/messages
Returns SMS and WhatsApp messages, newest first.
Parameters
| Parameter | Type | Meaning |
|---|---|---|
cursor | string | Cursor from the previous page |
limit | integer | 1–100, default 25 |
from | ISO 8601 | Messages after this time |
to | ISO 8601 | Messages before this time |
assistant_id | UUID | Filter by assistant |
channel | string | sms or whatsapp |
direction | string | inbound or outbound |
thread_id | UUID | Filter by conversation |
fields | string | Requested field blocks |
Example:
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/messages?channel=whatsapp&limit=50"GET /v1/messages/{message_id}
Returns one message.
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/messages/b71e9d02-4a6c-4f18-9d3e-7c2b5a4e8f31"GET /v1/threads
Returns completed SMS and WhatsApp conversations.
Parameters
| Parameter | Type | Meaning |
|---|---|---|
cursor | string | Cursor from previous page |
limit | integer | 1–100, default 25 |
from | ISO 8601 | Threads completed after this time |
to | ISO 8601 | Threads completed before this time |
assistant_id | UUID | Filter by assistant |
channel | string | sms or whatsapp |
close_reason | string | Filter by close reason |
fields | string | Requested field blocks |
Example:
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/threads?close_reason=graded&limit=50"GET /v1/threads/{thread_id}
Returns one completed conversation.
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/threads/c82fa013-5b7d-4029-8e4f-8d3c6b5f9a42"Errors
The API uses standard HTTP status codes.
| Status | Meaning |
|---|---|
400 | Invalid request |
401 | Missing or invalid API key |
403 | Your key does not have access to the requested data |
404 | Record does not exist |
429 | Rate limit exceeded |
500 | Server error |
Error responses include a JSON body explaining the problem.
Rate limits
| Limit | Scope |
|---|---|
| 1,000 requests per hour | Per endpoint, per caller |
| 100 requests per second | Burst protection |
If you are regularly hitting the hourly limit, use webhooks instead of polling.
Backfilling history
The REST API is also how you load data from before your webhook was enabled.
For example:
curl -H "Authorization: Bearer $KEY" \
"https://api.voicetta.com/v1/calls?limit=100&from=2026-08-01T00:00:00Z"Feed the results through the same processing logic as your webhook.
The objects are the same.
Make your handler idempotent so running a backfill more than once is safe.
For a specific recovery window, use both from and to.
Versioning
All API paths use /v1.
Within version 1, existing fields are stable.
We add fields without breaking existing integrations.
Breaking changes get a new version.
The OpenAPI specification is available at:
/open-api