The Voizematic REST API lives at https://voizematic.ai/api/v1, authenticates with a bearer key issued in the panel, and lets your own systems place calls, manage agents and contacts, read transcripts and receive webhook events. It is the same engine the panel uses; anything you can do here is billed per connected minute from the wallet, exactly as a panel call is.
Docs: Getting started · Configuration · Integrations · API reference · MCP connector · Tutorials · FAQ
Open the gear icon → Global Settings → API Keys and create a key. It starts with vz_live_. Send it on every request:
Authorization: Bearer vz_live_…
Content-Type: application/json
Keys act under your account. Rate limit: 1,000 requests per minute per key; a 429 response carries a Retry-After header. Regenerating the key invalidates the old one immediately.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/v1/agents | List your agents: id, name, type, greeting, system_prompt, voice, phone_number, knowledge_base_ids. |
| POST | /api/v1/agents | Create an agent: name and system_prompt required; optional greeting, type (outbound/inbound) and voice (professional_male, professional_female, hindi_male). Returns the agent with its numeric id. |
| PUT | /api/v1/agents/:agentId | Update an agent's name, system_prompt, greeting, voice or booking_url (see below; null removes it). |
| POST | /api/v1/calls | Place an outbound call now: to_number (E.164), agent_id, optional knowledge_base_id, optional context (≤ 2,000 characters of details for this one call, e.g. cart contents or an order number). |
| GET | /api/v1/calls | Your calls, newest first; limit (1–500, default 100) and offset query parameters. |
| GET | /api/v1/calls/:callId | One call (by the call_id from POST /calls or a call_sid): status, duration, summary, transcript, recording URL. |
| GET | /api/v1/calls/:callId/transcript | The transcript as text and as speaker turns, with the summary and recording URL. |
| GET | /api/v1/contacts | List your contacts. |
| POST | /api/v1/contacts | Add one contact: name and phone (E.164) required; optional email, tags and custom_fields. |
| POST | /api/v1/contacts/bulk | Add up to 1,000 contacts in one request; invalid rows are reported in errors. |
| GET | /api/v1/phone-numbers/available | Search numbers you can buy: country (ISO code, e.g. IN, US) required; optional type (fixed/mobile for India; local/mobile/toll-free elsewhere), capabilities (e.g. voice,sms), area_code (US) and limit (≤ 50). Each result has its setup_fee_usd and monthly_fee_usd; Indian (+91) numbers also carry setup_fee_inr (₹299) and monthly_fee_inr (₹199), the amounts actually charged. |
| POST | /api/v1/phone-numbers | Buy a number from your wallet: phone_number (E.164, from the search) and optional agent_id to assign it straight away. Same price and rules as the dashboard — Indian numbers need approved KYC first (403 compliance_required), and a low wallet returns 400. |
| GET | /api/v1/phone-numbers | Every number on your account: id, phone_number, country, capabilities, status, monthly_fee_usd, next_renewal_at and the agents using it. |
| GET | /api/v1/phone-numbers/:id | One number, by its id or the E.164 number. |
| PUT / DELETE | /api/v1/phone-numbers/:id/agent | Assign ({"agent_id": 42}) or unassign an agent. A number takes one outbound and one inbound agent; a second agent of the same type returns 409. DELETE removes every agent from the number, or only ?agent_id=42. |
| GET / POST | /api/v1/webhooks | List or register webhook endpoints (also available under Global Settings → API Keys → Webhooks); DELETE /api/v1/webhooks/:id removes one and POST /api/v1/webhooks/:id/test sends a signed test event. |
curl -X POST https://voizematic.ai/api/v1/calls \
-H "Authorization: Bearer vz_live_…" \
-H "Content-Type: application/json" \
-d '{
"to_number": "+919876543210",
"agent_id": 42,
"context": "Abandoned cart: 2 × running shoes size 8, ₹4,998. Coupon SAVE10 valid till Friday."
}'
The call is queued and dialled by the platform's call worker within seconds — except Indian numbers outside 9 AM–9 PM IST, which are held until the window opens (the response then includes deferred_until); the response carries its call_id, which every later webhook event and GET /api/v1/calls/:callId use. The wallet must hold at least $1.00; numbers on your block, opt-out or Do-Not-Call lists, or on a national do-not-call registry, are refused with 403 before anything is queued. The agent receives the context as background for that one call — it is never read out verbatim and is not treated as instructions.
Yes. Set booking_url (HTTPS) on the agent with POST /api/v1/agents or PUT /api/v1/agents/:agentId. The response returns booking_secret once. During a call the agent then POSTs to your URL — signed with X-Voizematic-Signature, an HMAC-SHA256 of the raw body using that secret — and you reply within 8 seconds:
booking.check_availability with slots: [{start, end}] → reply {"slots": [{"start", "available"}], "suggestions": [{"start", "end"}]}.booking.create with action (create, reschedule or cancel), start, end, appointment_type and caller (name, email, phone) → reply {"success": true, "confirmation_id", "message"}.Every request carries agent_id and, when known, call_id, so one URL can serve many businesses. An error, a timeout or a reply without success: true makes the agent tell the caller it could not confirm — it never claims a booking.
Events: call.created, call.ended, call.failed, call.transcribed and email.requested. email.requested fires when an agent wants to email a caller and your account has no Gmail connected: data has channel (call, whatsapp or telegram), agent_id, call_id, to, subject, body and is_html (plus cc, bcc, attachments), and you send it from your own email system — Voizematic never sends API accounts' email from its own mailbox. With no subscriber the agent gives the caller the details by voice instead. call.failed also fires when a queued call is refused before dialling, with data.reason. Failed deliveries (network error, timeout, 5xx, 408, 429) are retried after 30 s, 2 min and 10 min with the same payload. Each POST carries a JSON body with the event name, timestamp and call data, plus two headers: X-Voizematic-Event (the event name) and X-Voizematic-Signature (an HMAC-SHA256 of the raw body using your webhook secret, so you can verify origin). call.transcribed includes the transcript, summary and recording URL, and every call event carries the call_id returned by POST /api/v1/calls. Endpoints must use HTTPS. Respond with a 2xx status promptly.
| Status | Meaning |
|---|---|
| 401 | Missing or invalid key. |
| 402 | Insufficient wallet balance to place the call (the body reports the current balance). |
| 404 | Agent, call or contact not found under this account. |
| 400 | Validation failed — to_number (E.164) and numeric agent_id are required; context must be a string (it is truncated to 2,000 characters). |
| 403 | Call refused before dialling: ACCOUNT_LIMIT (outbound calls off or monthly cap reached), NUMBER_BLOCKED, NUMBER_OPTED_OUT or NUMBER_ON_DNC. |
| 409 | NO_PHONE_NUMBER — the account has no phone number to call from; get one under Phone Numbers (the free trial line only rings your own phone from the dashboard). |
| 429 | Rate limit exceeded; wait for the Retry-After seconds. |
| 503 | The call could not be queued; safe to retry. |
Prefer an assistant-driven integration instead of code? See the MCP connector. Code samples in JavaScript and Python are in the panel's API Reference page after sign-in.