How to Connect an AI Calling Agent to Your CRM (API + Webhooks)
Use two pieces: an API call from your CRM or website that starts the AI call the moment a lead arrives, and a webhook that sends the result back. On TaskVox that is POST /api/campaigns with "autoStart": true to call, and a call.completed webhook — signed with HMAC-SHA256 — that delivers the transcript and outcome to your server.
The most valuable minute in sales is the first one after a lead fills in a form. This guide shows how to wire that up end to end. Everything below matches the live API at taskvox.in/api/docs.
The flow
- A lead is created in your CRM or website form.
- Your backend calls the TaskVox API to start a call to that number.
- The AI agent calls, asks your questions and ends the call.
- TaskVox POSTs a signed
call.completedwebhook to your server. - Your server verifies the signature and updates the lead.
Step 1: get an API key
In the dashboard, open API Keys and create a key. It is shown once — keep it in your server’s secrets, never in browser or mobile code, because anyone holding it can place calls on your credits. Every request sends it in the X-API-Key header. Find the agent you will call with:
curl https://taskvox.in/api/agents \
-H "X-API-Key: tvx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Step 2: start a call when a lead arrives
Create a campaign with the lead’s number and "autoStart": true. A number can be a plain string, or an object with variables your agent’s script can use, such as the lead’s name. Send an Idempotency-Key (for example your lead ID) so a network retry never calls the same person twice.
curl -X POST https://taskvox.in/api/campaigns \
-H "X-API-Key: tvx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: lead-48213" \
-d '{
"name": "Website lead 48213",
"agentId": "sales-agent-01",
"numbers": [{ "number": "9198XXXXXXXX", "variables": { "name": "Rahul" } }],
"autoStart": true
}'
Two things trip up new integrations. Without autoStart (or a separate POST /api/campaigns/{id}/start), no call goes out. And campaign calls follow Indian calling rules: they only go out between 8 am and 8 pm IST, and numbers on your do-not-call list are skipped. Outside those hours the campaign is created but not started — the response has "started": false with a startError — and it does not start by itself later, so keep night-time leads in a queue and call POST /api/campaigns/{id}/start after 8 am.
Step 3: register a webhook
curl -X POST https://taskvox.in/api/webhooks \
-H "X-API-Key: tvx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "name": "CRM sync", "url": "https://yourcrm.example.com/taskvox/webhook",
"events": ["call.completed", "call.failed"] }'
The response includes the webhook’s secret, shown only once. Store it; you need it to verify every delivery. The four events are call.completed, call.failed, campaign.started and campaign.completed.
Step 4: verify and handle the webhook
Every delivery is a POST with an X-TaskVox-Signature header: an HMAC-SHA256 of the raw request body, hex-encoded, keyed with your secret. Verify it against the raw bytes, not the parsed JSON, and compare in constant time:
// Node.js + Express
const crypto = require('crypto');
app.post('/taskvox/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const expected = crypto.createHmac('sha256', process.env.TASKVOX_WEBHOOK_SECRET)
.update(req.body).digest('hex');
const got = req.get('X-TaskVox-Signature') || '';
if (got.length !== expected.length ||
!crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
return res.status(401).send('bad signature');
}
res.sendStatus(200); // acknowledge first
const evt = JSON.parse(req.body); // then process
if (evt.event === 'call.completed') updateLead(evt.data);
});
The data object of a call event carries call_id, agent_id, campaign_id, from, to, duration_seconds, turns, status, the full transcript as an array of { role, text } turns, a lead object (label hot / warm / cold / not_a_lead, score, summary and collected answers) and a recording_url.
Step 5: make it reliable
- Acknowledge fast. Reply 2xx within 10 seconds and do the CRM update afterwards. A failed delivery is retried after about 1, 5 and 15 minutes.
- Reconcile. If you must never miss a result, also pull
GET /api/callson a schedule and fill any gaps. - De-duplicate on the
X-TaskVox-Deliveryheader ordata.call_id— a retry carries the same values. - Mind the limits. Each API key may make 200 requests per minute; a
402means the credit balance needs a recharge. - Keep keys server-side and rotate any key that may have leaked.
What to store in the CRM
- The call ID and status, so you can link back to the recording in TaskVox.
- The transcript, or the answers to your qualifying questions extracted from it.
- The lead label (
data.lead.label) and summary — the same Hot / Warm / Cold / Not a lead you see on the TaskVox Leads page. - A follow-up task for Hot leads — the faster a person calls back, the better.
Frequently asked questions
Is there an API to make AI voice calls?
Yes. With TaskVox you create a campaign through the API with one or more phone numbers and "autoStart": true, and an AI agent calls them. Requests are authenticated with an X-API-Key header, and results come back by webhook.
How do I send AI call results to my CRM?
Register a webhook URL for the call.completed event. After every call TaskVox POSTs a JSON payload with the call ID, numbers, duration, status and full transcript, signed with an HMAC-SHA256 signature you verify before updating the CRM.
Can I personalise each API call with the lead’s name?
Yes. Each entry in the numbers array can be an object such as {"number": "98XXXXXXXX", "variables": {"name": "Rahul"}}, and the agent’s script can use those variables.
Are webhooks retried if my server is down?
Yes. If your endpoint does not answer with a 2xx within 10 seconds, TaskVox sends the same event again after about 1, 5 and 15 minutes — 4 attempts in total. Every attempt carries the same X-TaskVox-Delivery ID, so you can ignore repeats. For a longer outage, reconcile with GET /api/calls.
Do API calls follow TRAI calling hours?
Yes. Campaigns created through the API follow the same rules as the dashboard: calls only go out between 8 am and 8 pm IST, and numbers on your do-not-call list are skipped. A campaign created outside those hours is not started, so queue it and start it after 8 am.
Get an API key in two minutes
100 free credits to test · ₹2–₹4/min · telecom included