--- title: "Read API Reference" description: "Read Voicetta calls, messages, and completed conversations through the REST API. Includes authentication, pagination, filters, errors, rate limits, and backfills." publishedAt: "2026-08-22" modifiedAt: "2026-08-22" category: "Reference" tags: "Voicetta, REST API, OpenAPI, pagination, authentication, rate limits, messages, threads" navOrder: "40" canonical: "https://voicetta.com/developers/api-reference" --- # 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 ```text https://api.voicetta.com/v1 ``` ## Collections | 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: ```text Authorization: Bearer vk_live_xxxxxxxxxxxxxxxxxxxxxxxx ``` Keys 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: ```text ?fields=transcript ``` Requesting 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: ```bash 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: ```json { "calls": [ { "call_id": "9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11" } ], "has_more": true, "next_cursor": "MjAyNi0wOC0yMFQxMDowMDowMCswMDowMHw5ZjhiMWM0ZQ" } ``` ## Pagination Use cursor pagination. Do not use offsets. ```bash 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') done ``` Three rules: 1. Stop when `has_more` is false. 2. Treat cursors as opaque strings. 3. Do not construct or modify cursors. ## `GET /v1/calls/{call_id}` Returns one call. ```bash curl -H "Authorization: Bearer vk_live_your_key_here" \ "https://api.voicetta.com/v1/calls/9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11" ``` Response: ```json { "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. ```bash 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: ```bash 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. ```bash 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: ```bash 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. ```bash 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: ```bash 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: ```text /open-api ``` ## Related pages * [Overview](/developers/overview) * [Quickstart](/developers/quickstart) * [Webhook Reference](/developers/webhooks) * [Message Events](/developers/message-events) * [Thread Events](/developers/thread-events) * [n8n and No-code](/developers/n8n)