Home / API Reference VeytrixAI API Documentation & REST API Reference Use the VeytrixAI voice calling API to place calls, read what was said, and act on the outcome — from your own code. Everything the dashboard does to a call, an agent or a list, you can do over HTTP with an API key.
Your first call in one request Create a key in the dashboard under Settings → Developer , then dial your own phone. Nothing else needs to be set up first, as long as the workspace owns a number and has a wallet balance.
curl -X POST https://veytrix-api.fly.dev/api/agents/YOUR_AGENT_ID/test-call \
-H "Authorization: Bearer acai_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "phoneNumber": "+919876543210" }'Authentication Every request carries an API key as a bearer token. Keys begin acai_, belong to one workspace, and act with admin rights inside it — treat one as a password for the whole workspace and keep it server-side.
-H "Authorization: Bearer acai_YOUR_KEY"Creating and revoking Keys are created in Settings → Developer . The full key is shown once, at creation — only a SHA-256 hash is stored, so a lost key cannot be recovered and has to be replaced. Revoking takes effect on the next request.
What a key can reach A key is restricted to the twelve mounts below. Any other path answers 403 with “This endpoint is not available via API key” — including endpoints your own user can open in the dashboard. Billing changes, workspace settings, team management and the platform console are all deliberately outside the key's reach.
/agents/campaigns/batches/calls/alert/ratings/dashboard/analytics/wallet/balances/numbers/recordings
Rate limits Each key gets 5,000 requests a day and 100,000 a month by default. Both can be raised per key. The daily window resets at midnight IST; the monthly one on the 1st.
Every response carries your current position:
{
"message": "Daily API limit reached (5,000 requests). Resets at midnight IST.",
"scope": "daily",
"limit": 5000,
"used": 5000
}Errors Every error is JSON with a human-readable message. Show it to your operators — the text is written to be actionable rather than generic.
{ "message": "Agent not found." }Alert dial One request, many phones ringing at once. The fastest path from an event in your system to a live call — no batch to create, no start step, no lifecycle to manage.
POST /alert
Dial every number in the list immediately
Creates one call per phone number and enqueues all of them in the same request, then returns. Announcement agents bypass the per-organization concurrency counter, so the phones ring near-simultaneously rather than one after another. This is the endpoint to use for security alerts, outage notifications, and anything else where the delay of a batch would defeat the purpose.
https://veytrix-api.fly.dev/api /alert
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Malformed numbers are skipped, not rejected — an alert still reaches the valid numbers, and `skipped` tells you how many were dropped. A request where every number is malformed returns 400. Duplicate numbers in one request are dialed once. Returns 403 when the monthly minute quota is exhausted, and 400 when the workspace owns no phone number. The response returns before the calls connect. Subscribe to `call.completed` to learn how each one went. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/alert`, {
method: "POST",
headers,
body: JSON.stringify({
"agentId": "6f1c2f4a-1c7e-4c9a-9d21-2b6f5f0a1c33",
"phones": ["+919876543210", "+919812345678"],
"variables": { "site": "Gate 3", "severity": "high" }
})
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Alert dialing 2 number(s) via plivo.",
"calls": [
{ "callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77", "phone": "+919876543210" },
{ "callId": "c9a7d1b2-33f8-42aa-8e10-7c5b9e2f4a18", "phone": "+919812345678" }
],
"dialed": 2,
"skipped": 0
}Agents The AI persona that runs a conversation: its prompt, voice, language, model and call behaviour. Create one here or in the dashboard — same object either way.
GET /agents
List every agent in the workspace
https://veytrix-api.fly.dev/api /agents
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
[
{
"id": "6f1c2f4a-1c7e-4c9a-9d21-2b6f5f0a1c33",
"name": "Screening — Backend Engineer",
"status": "active",
"conversationEngine": "pipeline",
"language": "English",
"llmProvider": "Gemini",
"llmModel": "gemini-2.5-flash"
}
]POST /agents
Create an agent
https://veytrix-api.fly.dev/api /agents
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents`, {
method: "POST",
headers,
body: JSON.stringify({
"name": "Screening — Backend Engineer",
"conversationEngine": "pipeline",
"welcomeMessage": "Hi, this is Maya from Acme. Do you have two minutes?",
"prompt": "Ask about years of experience, primary stack, notice period. Keep replies under two sentences."
})
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "6f1c2f4a-1c7e-4c9a-9d21-2b6f5f0a1c33",
"name": "Screening — Backend Engineer",
"status": "active",
"conversationEngine": "pipeline",
"language": "English",
"llmProvider": "Gemini",
"llmModel": "gemini-2.5-flash"
}GET /agents/{agentId}
Fetch a single agent
https://veytrix-api.fly.dev/api /agents/{agentId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "6f1c2f4a-1c7e-4c9a-9d21-2b6f5f0a1c33",
"name": "Screening — Backend Engineer",
"status": "active",
"conversationEngine": "pipeline",
"language": "English",
"llmProvider": "Gemini",
"llmModel": "gemini-2.5-flash"
}PATCH /agents/{agentId}
Update any subset of an agent's fields
https://veytrix-api.fly.dev/api /agents/{agentId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}`, {
method: "PATCH",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "6f1c2f4a-1c7e-4c9a-9d21-2b6f5f0a1c33",
"name": "Screening — Backend Engineer",
"status": "active",
"conversationEngine": "pipeline",
"language": "English",
"llmProvider": "Gemini",
"llmModel": "gemini-2.5-flash"
}DELETE /agents/{agentId}
Soft-delete an agent
https://veytrix-api.fly.dev/api /agents/{agentId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}`, {
method: "DELETE",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
No response body This request does not return any response body.
POST /agents/{agentId}/restore
Undo a soft-delete
https://veytrix-api.fly.dev/api /agents/{agentId}/restore
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}/restore`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Undo a soft-delete."
}POST /agents/{agentId}/activate
Reactivate a dormant agent
An agent idle past the platform inactivity window stops having its welcome audio kept warm. Activating re-warms it so the next dial is as fast as any other.
https://veytrix-api.fly.dev/api /agents/{agentId}/activate
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}/activate`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Reactivate a dormant agent."
}POST /agents/{agentId}/deactivate
Stop an agent from being dialed
https://veytrix-api.fly.dev/api /agents/{agentId}/deactivate
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}/deactivate`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Stop an agent from being dialed."
}POST /agents/{agentId}/test-call
Place a single call to one number
The one-off dial. For more than a handful of numbers use batches, or /alert when they must ring at once.
https://veytrix-api.fly.dev/api /agents/{agentId}/test-call
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
409 with the in-flight `callId` when that number already has a call running — dial again once it settles. 403 when the monthly minute quota is spent. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}/test-call`, {
method: "POST",
headers,
body: JSON.stringify({ "phoneNumber": "+919876543210", "variables": { "name": "Priya" } })
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "6f1c2f4a-1c7e-4c9a-9d21-2b6f5f0a1c33",
"name": "Screening — Backend Engineer",
"status": "active",
"conversationEngine": "pipeline",
"language": "English",
"llmProvider": "Gemini",
"llmModel": "gemini-2.5-flash"
}POST /agents/{agentId}/chat
Exchange text turns with the agent, no phone call
https://veytrix-api.fly.dev/api /agents/{agentId}/chat
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/{agentId}/chat`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Exchange text turns with the agent, no phone call."
}POST /agents/generate
Draft a whole agent from a plain-language brief
https://veytrix-api.fly.dev/api /agents/generate
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/generate`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Draft a whole agent from a plain-language brief."
}POST /agents/prompt-assist
Improve an existing prompt
https://veytrix-api.fly.dev/api /agents/prompt-assist
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/agents/prompt-assist`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Improve an existing prompt."
}Calls Everything that happened on the phone: status, duration, transcript, summary and recording. This is the group most integrations spend their time in.
GET /calls
List calls, newest first
https://veytrix-api.fly.dev/api /calls
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
`status` in the response is the display form ("Completed", "No Answer"), while the `status` query parameter takes the raw form (`completed`, `no-answer`). They are deliberately different — filter with the raw values. `duration` and `startedAt` are pre-formatted for display, not machine values. Use the webhook payload's `durationSeconds` when you need arithmetic. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"studentName": "Priya Sharma",
"phone": "+919876543210",
"email": null,
"campaignName": "--",
"agentName": "Screening — Backend Engineer",
"duration": "4m 12s",
"status": "Completed",
"provider": "plivo",
"startedAt": "12 minutes ago",
"summary": "5 years on Node and React. 30-day notice. Open to Hyderabad.",
"calendarStatus": null,
"calendarEventUrl": null,
"calendarError": null,
"transcript": []
}
],
"total": 1284,
"page": 1,
"limit": 25,
"stats": { "total": 1284, "completedCount": 1102, "failedCount": 182 }
}GET /calls/{callId}
One call, with its full transcript
Same shape as a list row, except `transcript` is populated with every turn in order.
https://veytrix-api.fly.dev/api /calls/{callId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/{callId}`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"studentName": "Priya Sharma",
"status": "Completed",
"summary": "5 years on Node and React. 30-day notice.",
"transcript": [
{ "speaker": "Bot", "text": "Hi, this is Maya from Acme. Do you have two minutes?" },
{ "speaker": "Candidate", "text": "Yes, go ahead." }
]
}GET /calls/{callId}/transcript
Transcript only
https://veytrix-api.fly.dev/api /calls/{callId}/transcript
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Turn-level rows are pruned after 90 days. `transcriptText` is denormalised onto the call and is not pruned, so use it for anything you keep. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/{callId}/transcript`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"transcriptText": "Bot: Hi, this is Maya…\nCandidate: Yes, go ahead.",
"turns": [
{ "speaker": "assistant", "text": "Hi, this is Maya…", "createdAt": "2026-08-15T09:12:04.881Z" }
]
}GET /calls/{callId}/turns
Raw turn rows, unformatted
https://veytrix-api.fly.dev/api /calls/{callId}/turns
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/{callId}/turns`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"studentName": "Priya Sharma",
"phone": "+919876543210",
"agentName": "Screening — Backend Engineer",
"duration": "4m 12s",
"status": "Completed",
"provider": "plivo",
"startedAt": "12 minutes ago",
"summary": "5 years on Node and React. 30-day notice.",
"transcript": []
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /calls/{callId}/recording-url
Short-lived signed URL for the recording audio
The stored URL points at a private bucket. This returns a pre-signed link your client can fetch directly.
https://veytrix-api.fly.dev/api /calls/{callId}/recording-url
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
`url` is null when the call was not recorded, or when its retention window has passed. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/{callId}/recording-url`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{ "url": "https://s3.ap-south-1.amazonaws.com/…?X-Amz-Signature=…", "callId": "b21e0e4c" }GET /calls/{callId}/recording
Stream the recording audio through the API
https://veytrix-api.fly.dev/api /calls/{callId}/recording
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/{callId}/recording`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"studentName": "Priya Sharma",
"phone": "+919876543210",
"agentName": "Screening — Backend Engineer",
"duration": "4m 12s",
"status": "Completed",
"provider": "plivo",
"startedAt": "12 minutes ago",
"summary": "5 years on Node and React. 30-day notice.",
"transcript": []
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /calls/export.csv
Download the filtered call list as CSV
https://veytrix-api.fly.dev/api /calls/export.csv
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/export.csv`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Download the filtered call list as CSV."
}POST /calls/{callId}/cancel
Cancel a queued call, or hang up a live one
https://veytrix-api.fly.dev/api /calls/{callId}/cancel
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/{callId}/cancel`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Cancel a queued call, or hang up a live one."
}POST /calls/{callId}/redeliver-webhook
Re-send this call's webhook events
For when your endpoint was down. Replays to every active subscription that covers the event.
https://veytrix-api.fly.dev/api /calls/{callId}/redeliver-webhook
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/calls/{callId}/redeliver-webhook`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Re-send this call's webhook events."
}Batches Call a list of people with one agent. Three steps by design — create, add items, start — so a half-uploaded list can never start dialing on its own.
POST /batches
Create an empty batch
https://veytrix-api.fly.dev/api /batches
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches`, {
method: "POST",
headers,
body: JSON.stringify({ "name": "Backend shortlist — week 33", "agentId": "6f1c2f4a" })
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "9d3a71c8-5f22-4b0e-9a7d-1c8e4b2f6a90",
"name": "Backend shortlist — week 33",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 240,
"completed": 118,
"failed": 17,
"pending": 105
}POST /batches/{batchId}/items
Add people to the batch
Call as many times as you need before starting. Each item carries its own variables, so every call is personalised.
https://veytrix-api.fly.dev/api /batches/{batchId}/items
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}/items`, {
method: "POST",
headers,
body: JSON.stringify({
"items": [
{ "name": "Priya Sharma", "phone": "+919876543210", "variables": { "role": "Backend Engineer" } },
{ "name": "Arun Nair", "phone": "+919812345678", "variables": { "role": "Backend Engineer" } }
]
})
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Add people to the batch."
}POST /batches/{batchId}/start
Begin dialing
Calls are paced by the workspace's concurrency limit, so a 2,000-item batch runs for as long as that limit dictates rather than all at once.
https://veytrix-api.fly.dev/api /batches/{batchId}/start
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}/start`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Begin dialing."
}POST /batches/{batchId}/pause
Stop dialing; keep the remaining items queued
https://veytrix-api.fly.dev/api /batches/{batchId}/pause
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}/pause`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Stop dialing; keep the remaining items queued."
}POST /batches/{batchId}/resume
Continue a paused batch
https://veytrix-api.fly.dev/api /batches/{batchId}/resume
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}/resume`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Continue a paused batch."
}POST /batches/{batchId}/stop
End the batch and drop its pending items
https://veytrix-api.fly.dev/api /batches/{batchId}/stop
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}/stop`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "End the batch and drop its pending items."
}POST /batches/{batchId}/retry
Re-dial the items that failed or went unanswered
https://veytrix-api.fly.dev/api /batches/{batchId}/retry
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}/retry`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Re-dial the items that failed or went unanswered."
}GET /batches
List batches with their progress counts
https://veytrix-api.fly.dev/api /batches
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "9d3a71c8-5f22-4b0e-9a7d-1c8e4b2f6a90",
"name": "Backend shortlist — week 33",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 240,
"completed": 118,
"failed": 17,
"pending": 105
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /batches/{batchId}
One batch
https://veytrix-api.fly.dev/api /batches/{batchId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "9d3a71c8-5f22-4b0e-9a7d-1c8e4b2f6a90",
"name": "Backend shortlist — week 33",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 240,
"completed": 118,
"failed": 17,
"pending": 105
}GET /batches/{batchId}/items
The people in a batch and each one's latest status
https://veytrix-api.fly.dev/api /batches/{batchId}/items
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}/items`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "The people in a batch and each one's latest status."
}PATCH /batches/{batchId}
Rename or reschedule
https://veytrix-api.fly.dev/api /batches/{batchId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}`, {
method: "PATCH",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "9d3a71c8-5f22-4b0e-9a7d-1c8e4b2f6a90",
"name": "Backend shortlist — week 33",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 240,
"completed": 118,
"failed": 17,
"pending": 105
}DELETE /batches/{batchId}
Delete a batch
https://veytrix-api.fly.dev/api /batches/{batchId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/batches/{batchId}`, {
method: "DELETE",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
No response body This request does not return any response body.
Campaigns Batches built around a CSV upload, with a students list and per-campaign export. Use these when the list arrives as a file; use batches when it arrives from your own system.
GET /campaigns
List campaigns
https://veytrix-api.fly.dev/api /campaigns
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "3c1f9a76-84be-4f21-b0d5-7ea2c6415d88",
"name": "March intake",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 500,
"completed": 322,
"failed": 41,
"pending": 137
}
],
"total": 1284,
"page": 1,
"limit": 25
}POST /campaigns
Create a campaign
https://veytrix-api.fly.dev/api /campaigns
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "3c1f9a76-84be-4f21-b0d5-7ea2c6415d88",
"name": "March intake",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 500,
"completed": 322,
"failed": 41,
"pending": 137
}GET /campaigns/{campaignId}
One campaign with its progress
https://veytrix-api.fly.dev/api /campaigns/{campaignId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "3c1f9a76-84be-4f21-b0d5-7ea2c6415d88",
"name": "March intake",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 500,
"completed": 322,
"failed": 41,
"pending": 137
}PATCH /campaigns/{campaignId}
Update a campaign
https://veytrix-api.fly.dev/api /campaigns/{campaignId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}`, {
method: "PATCH",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "3c1f9a76-84be-4f21-b0d5-7ea2c6415d88",
"name": "March intake",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 500,
"completed": 322,
"failed": 41,
"pending": 137
}DELETE /campaigns/{campaignId}
Delete a campaign
https://veytrix-api.fly.dev/api /campaigns/{campaignId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}`, {
method: "DELETE",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
No response body This request does not return any response body.
POST /campaigns/{campaignId}/students/upload
Upload the call list as CSV
multipart/form-data. Columns beyond name and phone become variables available to the prompt.
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/students/upload
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/students/upload`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Upload the call list as CSV."
}POST /campaigns/{campaignId}/start
Begin dialing
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/start
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/start`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Begin dialing."
}POST /campaigns/{campaignId}/pause
Pause dialing
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/pause
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/pause`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Pause dialing."
}POST /campaigns/{campaignId}/resume
Resume dialing
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/resume
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/resume`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Resume dialing."
}POST /campaigns/{campaignId}/stop
Stop and drop pending calls
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/stop
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/stop`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Stop and drop pending calls."
}POST /campaigns/{campaignId}/retry
Re-dial failures
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/retry
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/retry`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Re-dial failures."
}GET /campaigns/{campaignId}/calls
Calls placed by this campaign
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/calls
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/calls`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "3c1f9a76-84be-4f21-b0d5-7ea2c6415d88",
"name": "March intake",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 500,
"completed": 322,
"failed": 41,
"pending": 137
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /campaigns/{campaignId}/students
The uploaded list and each row's status
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/students
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/students`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "3c1f9a76-84be-4f21-b0d5-7ea2c6415d88",
"name": "March intake",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 500,
"completed": 322,
"failed": 41,
"pending": 137
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /campaigns/{campaignId}/export
Results as a downloadable file
https://veytrix-api.fly.dev/api /campaigns/{campaignId}/export
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/campaigns/{campaignId}/export`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "3c1f9a76-84be-4f21-b0d5-7ea2c6415d88",
"name": "March intake",
"agentName": "Screening — Backend Engineer",
"status": "running",
"total": 500,
"completed": 322,
"failed": 41,
"pending": 137
}
],
"total": 1284,
"page": 1,
"limit": 25
}Ratings The scorecard produced after each call, using the rating template attached to the agent. Rating runs in the background, so a call reaches `completed` before its rating exists.
GET /ratings
List rated calls
https://veytrix-api.fly.dev/api /ratings
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"candidateName": "Priya Sharma",
"overallRating": 4.2,
"agentName": "Screening — Backend Engineer",
"columns": [
{ "name": "Communication", "score": 4, "reason": "Clear, gave concrete examples." },
{ "name": "Relevant experience", "score": 5, "reason": "5 years, matching stack." }
]
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /ratings/{callId}
The scorecard for one call
https://veytrix-api.fly.dev/api /ratings/{callId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/{callId}`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"candidateName": "Priya Sharma",
"overallRating": 4.2,
"agentName": "Screening — Backend Engineer",
"columns": [
{ "name": "Communication", "score": 4, "reason": "Clear, gave concrete examples." },
{ "name": "Relevant experience", "score": 5, "reason": "5 years, matching stack." }
]
}GET /ratings/by-phone/{phone}
Every rating for a phone number
Useful when the same person has been called more than once and you want the history in one request.
https://veytrix-api.fly.dev/api /ratings/by-phone/{phone}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/by-phone/{phone}`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"candidateName": "Priya Sharma",
"overallRating": 4.2,
"agentName": "Screening — Backend Engineer",
"columns": [
{ "name": "Communication", "score": 4, "reason": "Clear, gave concrete examples." },
{ "name": "Relevant experience", "score": 5, "reason": "5 years, matching stack." }
]
}GET /ratings/stats
Counts and averages across the workspace
https://veytrix-api.fly.dev/api /ratings/stats
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/stats`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"candidateName": "Priya Sharma",
"overallRating": 4.2,
"agentName": "Screening — Backend Engineer",
"columns": [
{ "name": "Communication", "score": 4, "reason": "Clear, gave concrete examples." },
{ "name": "Relevant experience", "score": 5, "reason": "5 years, matching stack." }
]
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /ratings/analytics
Score distribution, broken down by column
https://veytrix-api.fly.dev/api /ratings/analytics
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/analytics`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"candidateName": "Priya Sharma",
"overallRating": 4.2,
"agentName": "Screening — Backend Engineer",
"columns": [
{ "name": "Communication", "score": 4, "reason": "Clear, gave concrete examples." },
{ "name": "Relevant experience", "score": 5, "reason": "5 years, matching stack." }
]
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /ratings/export-all
Every rating as a downloadable file
https://veytrix-api.fly.dev/api /ratings/export-all
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/export-all`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"candidateName": "Priya Sharma",
"overallRating": 4.2,
"agentName": "Screening — Backend Engineer",
"columns": [
{ "name": "Communication", "score": 4, "reason": "Clear, gave concrete examples." },
{ "name": "Relevant experience", "score": 5, "reason": "5 years, matching stack." }
]
}
],
"total": 1284,
"page": 1,
"limit": 25
}POST /ratings/export-sheet
Push ratings into a Google Sheet
https://veytrix-api.fly.dev/api /ratings/export-sheet
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/export-sheet`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Push ratings into a Google Sheet."
}POST /ratings/{callId}/rate-now
Rate a call immediately instead of waiting for the queue
https://veytrix-api.fly.dev/api /ratings/{callId}/rate-now
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/{callId}/rate-now`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Rate a call immediately instead of waiting for the queue."
}POST /ratings/{callId}/regenerate
Score the call again
Use after editing the template — the existing scorecard is replaced.
https://veytrix-api.fly.dev/api /ratings/{callId}/regenerate
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/{callId}/regenerate`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Score the call again."
}POST /ratings/bulk-regenerate
Re-score many calls at once
https://veytrix-api.fly.dev/api /ratings/bulk-regenerate
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/bulk-regenerate`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Re-score many calls at once."
}POST /ratings/reload
Re-read templates and refresh pending ratings
https://veytrix-api.fly.dev/api /ratings/reload
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/ratings/reload`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Re-read templates and refresh pending ratings."
}Phone numbers The caller IDs your workspace owns. A number is rented monthly; the first month is paid online and every renewal is taken from the wallet.
GET /numbers
List the numbers this workspace owns
https://veytrix-api.fly.dev/api /numbers
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "7b2e5c19-40aa-4d63-8f11-2c9d7e0a5b34",
"phoneNumber": "+918047182290",
"label": "Main line",
"provider": "plivo",
"isActive": true,
"isDefaultOutbound": true,
"assignedAgentId": null,
"nextRenewalAt": "2026-09-15T00:00:00.000Z"
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /numbers/available-pool
Numbers available to rent
https://veytrix-api.fly.dev/api /numbers/available-pool
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers/available-pool`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "7b2e5c19-40aa-4d63-8f11-2c9d7e0a5b34",
"phoneNumber": "+918047182290",
"label": "Main line",
"provider": "plivo",
"isActive": true,
"isDefaultOutbound": true,
"assignedAgentId": null,
"nextRenewalAt": "2026-09-15T00:00:00.000Z"
}
],
"total": 1284,
"page": 1,
"limit": 25
}GET /numbers/renewals-due
Numbers renewing soon, with their dates
https://veytrix-api.fly.dev/api /numbers/renewals-due
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers/renewals-due`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"rows": [
{
"id": "7b2e5c19-40aa-4d63-8f11-2c9d7e0a5b34",
"phoneNumber": "+918047182290",
"label": "Main line",
"provider": "plivo",
"isActive": true,
"isDefaultOutbound": true,
"assignedAgentId": null,
"nextRenewalAt": "2026-09-15T00:00:00.000Z"
}
],
"total": 1284,
"page": 1,
"limit": 25
}POST /numbers
Register a number against the workspace
https://veytrix-api.fly.dev/api /numbers
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "7b2e5c19-40aa-4d63-8f11-2c9d7e0a5b34",
"phoneNumber": "+918047182290",
"label": "Main line",
"provider": "plivo",
"isActive": true,
"isDefaultOutbound": true,
"assignedAgentId": null,
"nextRenewalAt": "2026-09-15T00:00:00.000Z"
}PATCH /numbers/{numberId}
Set the label, the inbound agent, or the default caller ID
https://veytrix-api.fly.dev/api /numbers/{numberId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
An inbound number rings exactly one agent. Assigning it to a second agent moves it. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers/{numberId}`, {
method: "PATCH",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"id": "7b2e5c19-40aa-4d63-8f11-2c9d7e0a5b34",
"phoneNumber": "+918047182290",
"label": "Main line",
"provider": "plivo",
"isActive": true,
"isDefaultOutbound": true,
"assignedAgentId": null,
"nextRenewalAt": "2026-09-15T00:00:00.000Z"
}POST /numbers/{numberId}/renew
Renew now, charged to the wallet
https://veytrix-api.fly.dev/api /numbers/{numberId}/renew
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers/{numberId}/renew`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Renew now, charged to the wallet."
}POST /numbers/{numberId}/release
Return the number to the shared pool
https://veytrix-api.fly.dev/api /numbers/{numberId}/release
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Irreversible. The number becomes available to other workspaces and cannot be reclaimed. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers/{numberId}/release`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Return the number to the shared pool."
}DELETE /numbers/{numberId}
Remove a number record
https://veytrix-api.fly.dev/api /numbers/{numberId}
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/numbers/{numberId}`, {
method: "DELETE",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
No response body This request does not return any response body.
Wallet & usage Prepaid balance, what has been spent, and what is left. Poll this if you want to stop your own dialing before the wallet runs dry.
GET /wallet
Balance, spend and usage for the current month
https://veytrix-api.fly.dev/api /wallet
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
`lowBalance` turns true when the balance buys fewer than about 30 two-way minutes. It is the field to alert on. `ratePerMin` follows the plan the balance unlocks, so it changes as the wallet is topped up. Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/wallet`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"currency": "INR",
"ratePerMin": 4.5,
"walletCredits": 20000,
"amountPaid": 20000,
"spent": 8420.5,
"balance": 11579.5,
"minutesUsed": 1871,
"minutesLimit": 4444,
"projectedDaysRemaining": 19,
"lowBalance": false,
"monthStart": "2026-08-01T00:00:00.000Z"
}GET /wallet/transactions
Ledger entries, newest first
https://veytrix-api.fly.dev/api /wallet/transactions
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/wallet/transactions`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"currency": "INR",
"ratePerMin": 4.5,
"walletCredits": 20000,
"balance": 11579.5,
"minutesUsed": 1871,
"lowBalance": false
}GET /wallet/transactions/export.csv
The ledger as CSV
https://veytrix-api.fly.dev/api /wallet/transactions/export.csv
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/wallet/transactions/export.csv`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "The ledger as CSV."
}GET /wallet/usage
Usage broken down by agent and campaign
https://veytrix-api.fly.dev/api /wallet/usage
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/wallet/usage`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"currency": "INR",
"ratePerMin": 4.5,
"walletCredits": 20000,
"balance": 11579.5,
"minutesUsed": 1871,
"lowBalance": false
}GET /wallet/auto-recharge
Current auto-recharge settings
https://veytrix-api.fly.dev/api /wallet/auto-recharge
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/wallet/auto-recharge`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"currency": "INR",
"ratePerMin": 4.5,
"walletCredits": 20000,
"balance": 11579.5,
"minutesUsed": 1871,
"lowBalance": false
}PATCH /wallet/auto-recharge
Change the threshold, amount or daily cap
https://veytrix-api.fly.dev/api /wallet/auto-recharge
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/wallet/auto-recharge`, {
method: "PATCH",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"currency": "INR",
"ratePerMin": 4.5,
"walletCredits": 20000,
"balance": 11579.5,
"minutesUsed": 1871,
"lowBalance": false
}POST /wallet/fund-request
Request a manual top-up
https://veytrix-api.fly.dev/api /wallet/fund-request
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEYContent-Type application/json
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/wallet/fund-request`, {
method: "POST",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"message": "Request a manual top-up."
}GET /balances
Upstream provider credit, when the workspace uses its own keys
https://veytrix-api.fly.dev/api /balances
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/balances`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"currency": "INR",
"ratePerMin": 4.5,
"walletCredits": 20000,
"balance": 11579.5,
"minutesUsed": 1871,
"lowBalance": false
}Dashboard & analytics The same aggregates the dashboard renders, for when you want them in your own reporting.
GET /dashboard/overview
Headline counters
https://veytrix-api.fly.dev/api /dashboard/overview
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/dashboard/overview`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"totalCalls": 1284,
"completedCalls": 1102,
"failedCalls": 182,
"totalMinutes": 5136,
"averageDurationSeconds": 240
}GET /dashboard/analytics
Per-agent performance
https://veytrix-api.fly.dev/api /dashboard/analytics
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/dashboard/analytics`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"totalCalls": 1284,
"completedCalls": 1102,
"failedCalls": 182,
"totalMinutes": 5136,
"averageDurationSeconds": 240
}GET /dashboard/call-volume
Calls over time, for charting
https://veytrix-api.fly.dev/api /dashboard/call-volume
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/dashboard/call-volume`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"totalCalls": 1284,
"completedCalls": 1102,
"failedCalls": 182,
"totalMinutes": 5136,
"averageDurationSeconds": 240
}GET /dashboard/status-breakdown
How calls ended, grouped by status
https://veytrix-api.fly.dev/api /dashboard/status-breakdown
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/dashboard/status-breakdown`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"totalCalls": 1284,
"completedCalls": 1102,
"failedCalls": 182,
"totalMinutes": 5136,
"averageDurationSeconds": 240
}GET /dashboard/recent-calls
The latest calls, pre-trimmed for a feed
https://veytrix-api.fly.dev/api /dashboard/recent-calls
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/dashboard/recent-calls`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"totalCalls": 1284,
"completedCalls": 1102,
"failedCalls": 182,
"totalMinutes": 5136,
"averageDurationSeconds": 240
}GET /analytics/overview
Funnel, engagement buckets and cost in one payload
https://veytrix-api.fly.dev/api /analytics/overview
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/analytics/overview`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"totalCalls": 1284,
"completedCalls": 1102,
"failedCalls": 182,
"totalMinutes": 5136,
"averageDurationSeconds": 240
}GET /recordings
Recordings across the workspace, with playback URLs
https://veytrix-api.fly.dev/api /recordings
Authorization Type Bearer token Token acai_YOUR_KEY
Headers Authorization Bearer acai_YOUR_KEY
Example request
cURL Python Node.js PHP Go
Copy // Node 18+ — fetch is built in
const BASE = "https://veytrix-api.fly.dev/api";
const headers = {
Authorization: "Bearer acai_YOUR_KEY",
"Content-Type": "application/json"
};
const res = await fetch(`${BASE}/recordings`, {
method: "GET",
headers
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Example response
{
"totalCalls": 1284,
"completedCalls": 1102,
"failedCalls": 182,
"totalMinutes": 5136,
"averageDurationSeconds": 240
}Webhooks Rather than polling /calls, let Veytrix tell you. Register an HTTPS endpoint in Settings → Developer , choose the events, and every matching call POSTs a signed JSON body to you.
The envelope Every delivery has the same outer shape; only data differs by event.
POST https://your-app.example.com/veytrix
Content-Type: application/json
X-Veytrix-Event: call.completed
X-Veytrix-Signature: sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b…
{
"event": "call.completed",
"organizationId": "a17f…",
"data": { },
"sentAt": "2026-08-15T09:16:31.204Z"
}Verifying the signature The signature is HMAC-SHA256 over the exact raw body , keyed by the subscription secret (it begins whsec_). Compare with a timing-safe equality check, and verify before you parse — re-serialising the JSON first changes the bytes and the signature will never match.
import crypto from "node:crypto";
import express from "express";
const app = express();
// express.raw, NOT express.json — the signature covers the exact bytes.
app.post("/veytrix", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.header("X-Veytrix-Signature") ?? "";
const expected =
"sha256=" +
crypto.createHmac("sha256", process.env.VEYTRIX_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok) return res.status(401).send("bad signature");
const { event, data } = JSON.parse(req.body.toString("utf8"));
// Acknowledge fast, then do the work out of band — deliveries time out at 10s.
res.sendStatus(200);
void handle(event, data);
});import hmac, hashlib, os
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["VEYTRIX_WEBHOOK_SECRET"].encode()
@app.post("/veytrix")
def veytrix():
raw = request.get_data() # bytes, before any parsing
expected = "sha256=" + hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(request.headers.get("X-Veytrix-Signature", ""), expected):
abort(401)
payload = request.get_json()
handle(payload["event"], payload["data"])
return "", 200Events Three events are delivered to subscriptions. Each fires once per call; rating.created always trails its call's own event, sometimes by a minute or more, because scoring runs in the background.
call.completed
A call ended with a real conversation. Fires once the transcript and summary are written.
{
"event": "call.completed",
"organizationId": "a17f…",
"data": {
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"status": "completed",
"durationSeconds": 252,
"targetName": "Priya Sharma",
"targetPhone": "+919876543210",
"summaryText": "5 years on Node and React. 30-day notice."
},
"sentAt": "2026-08-15T09:16:31.204Z"
}call.failed
The call did not connect, or nobody answered. Same payload shape, with status `failed` or `no-answer`.
{
"event": "call.failed",
"organizationId": "a17f…",
"data": {
"callId": "c9a7d1b2-33f8-42aa-8e10-7c5b9e2f4a18",
"status": "no-answer",
"durationSeconds": 0,
"targetName": "Arun Nair",
"targetPhone": "+919812345678",
"summaryText": null
},
"sentAt": "2026-08-15T09:17:02.771Z"
}rating.created
The scorecard for a call is ready. Always arrives after that call's own event, sometimes by a minute or more.
{
"event": "rating.created",
"organizationId": "a17f…",
"data": {
"callId": "b21e0e4c-70f2-4f5f-9a1e-4d2f1a6c9b77",
"candidateName": "Priya Sharma",
"overallRating": 4.2,
"agentName": "Screening — Backend Engineer"
},
"sentAt": "2026-08-15T09:18:44.019Z"
}Delivery behaviour Each delivery times out after 10 seconds . Return 200 immediately and do your work afterwards. A non-2xx response is logged but not automatically retried . To replay a specific call, use POST /calls/{callId}/redeliver-webhook. The target must be a public HTTPS address. URLs that resolve to private or internal ranges are refused at delivery time, not just at registration — so a DNS change cannot turn your endpoint into an internal one. Deliveries are not ordered. Key your handler on callId and make it idempotent. Common integrations Four things people build first, end to end.
Call a lead the moment it arrives Speed to first contact is the whole game in inbound sales. Call your form handler's webhook straight into a dial — the lead's phone rings while they are still on the thank-you page.
await fetch("https://veytrix-api.fly.dev/api/agents/AGENT_ID/test-call", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.VEYTRIX_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
phoneNumber: lead.phone, // +919876543210
variables: { name: lead.firstName, product: lead.interestedIn }
})
});Then listen for rating.created and write overallRating back onto the lead — your reps work the list in score order instead of arrival order.
Screen a shortlist overnight Create the batch, push everyone in, start it. Each person gets their own variables, so the agent opens with their name and the role they applied for.
const auth = { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" };
// 1 · create
const batch = await (await fetch("https://veytrix-api.fly.dev/api/batches", {
method: "POST", headers: auth,
body: JSON.stringify({ name: "Backend shortlist", agentId: AGENT_ID })
})).json();
// 2 · fill
await fetch(`https://veytrix-api.fly.dev/api/batches/${batch.id}/items`, {
method: "POST", headers: auth,
body: JSON.stringify({
items: candidates.map(c => ({
name: c.name, phone: c.phone, variables: { role: c.role }
}))
})
});
// 3 · dial
await fetch(`https://veytrix-api.fly.dev/api/batches/${batch.id}/start`, { method: "POST", headers: auth });Pass scheduledStartAt at step 1 instead of calling start, and the batch begins on its own at that time.
Ring every on-call engineer at once When something is on fire, a batch is the wrong shape — it paces calls. /alert rings all of them in parallel from a single request, and returns before they connect.
From your monitoring hook Copy await fetch("https://veytrix-api.fly.dev/api/alert", {
method: "POST",
headers: { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
agentId: ANNOUNCEMENT_AGENT_ID,
phones: onCall.map(p => p.phone),
variables: { service: incident.service, severity: incident.severity }
})
});Use an announcement agent here: it plays one message and hangs up, costs no LLM time, and its audio is cached — so the message starts almost the instant the call connects.
Sync every outcome into your CRM Subscribe to call.completed and rating.created, verify the signature, and upsert on callId. Two events per call arrive separately, so write them independently rather than waiting for both.
async function handle(event, data) {
if (event === "call.completed") {
await crm.upsertActivity({
externalId: data.callId,
phone: data.targetPhone,
durationSeconds: data.durationSeconds,
notes: data.summaryText
});
}
if (event === "rating.created") {
await crm.updateActivity(data.callId, { score: data.overallRating });
}
// call.failed carries status "failed" or "no-answer" — worth a retry task.
}Need the audio too? Call GET /calls/{callId}/recording-url when the event arrives and store the file yourself — the signed URL is short-lived by design.