By area
AI agents
Read from the API’s own reference file every hour.
Your AI agents, and one outgoing call through one of them.
List AI agents
GET/v1/
Your AI agents, with what you need to pick one for POST /v1/agents/{id}/calls. Agents are set up in the portal. An agent can place calls only when active and outgoing_calls are both true.
Keys with the agents scope can call this route.
Request
curl https://api.vocatech.com/v1/agents \
-H "Authorization: Bearer YOUR_API_KEY"const res = await fetch("https://api.vocatech.com/v1/agents", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
console.log(res.status, await res.json());import requests
r = requests.get(
"https://api.vocatech.com/v1/agents",
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=30,
)
print(r.status_code, r.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client([
'base_uri' => 'https://api.vocatech.com',
'headers' => ['Authorization' => 'Bearer YOUR_API_KEY'],
'http_errors' => false,
]);
$res = $client->get('/v1/agents');
echo $res->getStatusCode(), PHP_EOL, $res->getBody(), PHP_EOL;Answers
| Field | Type | Description |
|---|---|---|
agents required | array of objects | |
agents[]. required | integer | Use it with POST /v1/agents/{id}/calls. |
agents[]. required | string | |
agents[]. required | string | The agent's extension. |
agents[]. required | boolean | The agent is switched on. |
agents[]. required | boolean | The agent's Outgoing calls switch is on. It must be on to place calls. |
agents[]. required | boolean | The agent is set up on the phone system. |
meta required | object | |
meta. required | integer |
{
"agents": [
{
"id": 12,
"name": "Front Desk",
"extension": "150",
"active": true,
"outgoing_calls": true,
"provisioned": true
}
],
"meta": {
"total": 1
}
}Retry-After seconds. The body names the counter, the window and the limit.| Header | Type | Description |
|---|---|---|
Retry-After | integer | Seconds to wait before you try again. |
Retry-After: 5), or a service this route needs could not be reached.| Header | Type | Description |
|---|---|---|
Retry-After | integer | Seconds to wait before you try again. |
Place an outgoing AI agent call
POST/v1/
Your AI agent places one outgoing call: a reminder, a confirmation, a callback, a notice. The agent opens with its outgoing greeting, says the purpose, and handles the answer with the jobs it has. A job that changes an appointment files the change.
The outcome reaches you the way every message from the agent does: through the agent's message delivery and message action, opening with a tag that names your reference.
Rules.
- One call per request. This is not a bulk dialer.
tois a 10-digit US or Canadian number, or an extension of 2 to 6 digits. Never an emergency or service number (911 and the other N11 codes, 933, 988), a premium number (900, 976), or an area code that is another country.- The agent must be on, and its Outgoing calls switch must be on (in the portal, under Persona, Outgoing calls).
- A call outside the agent's own calling hours (8 AM to 9 PM in the agent's time zone unless its Persona tab says otherwise) is refused unless
allow_quiet_hoursis true. - Send
purposeorinstructions, or both. - An agent places at most 50 calls a day; past that the request is refused (
422) until the next day.
The answer is 202 once the call is placed. state is the first state the phone system reported.
A retry is safe with an Idempotency-Key. Send the header, your own id for the request (up to 80 characters): a repeat within a day answers the same call (202, the same call_sid) instead of placing a second one. Without it, the same agent, to and reference within two minutes is treated as the same request. A 502 means the platform did not answer and the call may have been placed: check for the placed-call tag before you retry, or retry with the same key.
Keys with the agents scope can call this route.
Request
curl -X POST https://api.vocatech.com/v1/agents/12/calls \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "7185550142",
"purpose": "Confirm the Friday 10 AM appointment",
"person_name": "Jordan Reyes",
"reference": "appt-2291",
"kind": "notice"
}'const res = await fetch("https://api.vocatech.com/v1/agents/12/calls", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "7185550142",
purpose: "Confirm the Friday 10 AM appointment",
person_name: "Jordan Reyes",
reference: "appt-2291",
kind: "notice",
}),
});
console.log(res.status, await res.json());import requests
r = requests.post(
"https://api.vocatech.com/v1/agents/12/calls",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"to": "7185550142",
"purpose": "Confirm the Friday 10 AM appointment",
"person_name": "Jordan Reyes",
"reference": "appt-2291",
"kind": "notice",
},
timeout=30,
)
print(r.status_code, r.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client([
'base_uri' => 'https://api.vocatech.com',
'headers' => ['Authorization' => 'Bearer YOUR_API_KEY'],
'http_errors' => false,
]);
$res = $client->post('/v1/agents/12/calls', [
'json' => [
'to' => '7185550142',
'purpose' => 'Confirm the Friday 10 AM appointment',
'person_name' => 'Jordan Reyes',
'reference' => 'appt-2291',
'kind' => 'notice',
],
]);
echo $res->getStatusCode(), PHP_EOL, $res->getBody(), PHP_EOL;Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | integer | The agent's id, from GET /v1/agents. For example 12. |
Idempotency-Key | header | string | Your own id for this request, up to 80 characters. A repeat within a day answers the same call instead of placing a second one. Up to 80 characters. For example visit-20260925-0900. |
Body
| Field | Type | Description |
|---|---|---|
to required | string | Who to call: a 10-digit US or Canadian number, or an extension of 2 to 6 digits. Punctuation and a leading 1 are ignored. For example 7185550142. |
purpose | string | Why the agent is calling, in one line. It says this after its greeting. Longer text is cut to 200 characters. Up to 200 characters. |
subject | string | Another name for purpose. |
instructions | string | More for the agent to know or do on this call. Longer text is cut to 2,000 characters. Up to 2,000 characters. |
person_name | string | The name of the person being called. Cut to 80 characters. Up to 80 characters. |
reference | string | Your own id for this call, echoed in the agent's message about it. Letters, digits, dots, dashes, colons and underscores. Matches ^[A-Za-z0-9._:-]{1,80}$. |
job | string | The name of the agent job the call starts with. Cut to 80 characters. Up to 80 characters. |
kind | string | notice tells the person something. callback answers something they asked for. Any other value reads as notice. One of notice or callback. Default notice. |
allow_quiet_hours | boolean | Allow a call outside the agent's own calling hours (8 AM to 9 PM in its time zone unless its Persona tab says otherwise). Default false. |
{
"to": "7185550142",
"purpose": "Confirm the Friday 10 AM appointment",
"person_name": "Jordan Reyes",
"reference": "appt-2291",
"kind": "notice"
}Answers
| Field | Type | Description |
|---|---|---|
call required | object | |
call. required | string | The id of the placed call. |
call. required | integer | |
call. required | string | The number the call comes from. |
call. required | string | |
call. required | string | The first state the phone system reported, for example trying. |
call. required | string | One of notice or callback. |
call. required | string | |
call. required | string |
{
"call": {
"call_sid": "c7d2e9a4-1f3b-4c8e-9a6d-0b5e2f7c1a93",
"agent_id": 12,
"from": "7185550100",
"to": "7185550142",
"state": "trying",
"kind": "notice",
"purpose": "Confirm the Friday 10 AM appointment",
"reference": "appt-2291"
}
}Example body
{
"error": {
"code": 400,
"type": "BAD_REQUEST",
"message": "The agent id must be a number."
}
}Example body
{
"error": {
"code": 404,
"type": "NOT_FOUND",
"message": "No agent with that id on this account."
}
}Example bodies
{
"error": {
"code": 422,
"type": "UNPROCESSABLE_ENTITY",
"message": "Outgoing calls are switched off on this agent. Turn them on under Persona, Outgoing calls."
}
}{
"error": {
"code": 422,
"type": "UNPROCESSABLE_ENTITY",
"message": "to is required: the number to call, or an extension."
}
}{
"error": {
"code": 422,
"type": "UNPROCESSABLE_ENTITY",
"message": "to may not be an emergency or service number."
}
}{
"error": {
"code": 422,
"type": "UNPROCESSABLE_ENTITY",
"message": "purpose or instructions is required: the agent has to know why it is calling."
}
}{
"error": {
"code": 422,
"type": "UNPROCESSABLE_ENTITY",
"message": "This agent is switched off."
}
}dial counter is full (10 a minute, 500 a day per key), or another request limit was reached. Wait Retry-After seconds.| Header | Type | Description |
|---|---|---|
Retry-After | integer | Seconds to wait before you try again. |
Example body
{
"error": "Rate limit exceeded",
"period": "minute",
"limit": 10,
"counter": "dial",
"retry_after": 42
}Idempotency-Key.Example body
{
"error": {
"code": 502,
"type": "ERROR",
"message": "The agent platform did not answer. The call may have been placed; check for the placed-call tag before you retry."
}
}| Header | Type | Description |
|---|---|---|
Retry-After | integer | Seconds to wait before you try again. |
Example body
{
"error": {
"code": 503,
"type": "ERROR",
"message": "Outgoing calls are not available right now."
}
}