Quickstart
Connect Voicetta to your product in a few minutes.
The basic flow is:
Customer → Voicetta → your backend → your product
Voicetta handles the conversation.
Your backend receives the event and decides what to do with it.
Step 1: See a real event
Before writing code, send a test event to a temporary endpoint.
- Open webhook.site, RequestBin, or use an
ngroktunnel. - Copy the URL.
- In Voicetta, open Settings → Developers.
- Create a webhook endpoint using that URL.
- Choose the events you want.
- Click Send test event.
You will see the exact HTTP request, headers, and JSON payload.
A Voicetta event is one JSON object.
The basic shape is:
{
"event": "call.completed",
"event_id": "9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11",
"version": 1,
"occurred_at": "2026-08-20T10:03:00+00:00",
"call": {}
}The event tells you what happened.
The object underneath it contains the data.
Step 2: Read data through the API
Create an API key in Settings → Developers.
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/calls?limit=1"You get a page of calls:
{
"calls": [
{
"call_id": "9f8b1c4e-6d2a-4b7f-8e21-3c5a7d9e0f11",
"workspace_id": "2a1f8e7d-4c3b-4a29-9f18-6d5e4c3b2a19",
"call_type": "inbound",
"direction": "inbound",
"status": "ended",
"duration_seconds": 180,
"analysis": {
"summary": "Caller booked a double room for Friday."
}
}
],
"has_more": true,
"next_cursor": "MjAyNi0wOC0yMFQxMDowMDowMCswMDowMHw5ZjhiMWM0ZQ"
}You can request only the fields your application needs:
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/calls?limit=1&fields=transcript"Requesting a field group your key does not have returns 403.
A missing field is not an error. Fields with no value are omitted.
The other collections work the same way:
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/messages?limit=1"
curl -H "Authorization: Bearer vk_live_your_key_here" \
"https://api.voicetta.com/v1/threads?limit=1"One API key can read all three collections.
Step 3: Handle webhook events
Replace the temporary URL with your own endpoint.
A minimal Express handler:
const HANDLERS = {
'call.completed': (body) => store('call', body.call),
'message.received': (body) => store('message', body.message),
'message.sent': (body) => store('message', body.message),
'thread.completed': (body) => store('thread', body.thread),
};
app.post('/voicetta/events', express.json(), (req, res) => {
res.sendStatus(200);
const deliveryId = req.get('X-Voicetta-Delivery-Id');
if (alreadyProcessed(deliveryId)) {
return;
}
const handler = HANDLERS[req.body.event];
if (!handler) {
return;
}
enqueue(deliveryId, () => handler(req.body));
});The important part is the shape:
- receive the event
- acknowledge it
- deduplicate it
- dispatch based on
event - process it in the background
Add signature verification before going to production.
See Webhook Reference.
The two rules that matter
Acknowledge first
Return 200 quickly.
Do not wait for database writes, API calls, or other processing before responding.
Put the event into a queue or store it, return 200, and process it afterward.
If the response takes too long, Voicetta will retry the delivery.
Expect duplicates
Webhook delivery is at-least-once.
A network problem can cause the same event to arrive more than once.
Make your handler idempotent.
Use X-Voicetta-Delivery-Id to identify delivery attempts, or use event_id when you want to treat repeated deliveries as the same conversation event.
Step 4: Go live
- Make sure your endpoint is publicly reachable over HTTPS.
- Test the endpoint with Send test event.
- Confirm that your server returns
200. - Add signature verification.
- Watch the delivery log.
- Start receiving real traffic.
Enabling a webhook event is not retroactive.
If you need older conversations, use the REST API.