Create a campaign
Creates an outbound campaign in draft status. Nothing dials until you add contacts and call POST /campaigns/{id}/start.
Supply caller IDs with phone_number_ids (preferred — the campaign rotates through them in order) or a single legacy provider. Sending both fails unless they agree.
curl --request POST \
--url https://api.vocobase.com/api/v2/campaigns \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "March renewals",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"phone_number_ids": [
"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f"
],
"concurrency_limit": 10,
"retry_count": 2,
"retry_delays_minutes": [
30,
240
]
}
'import requests
url = "https://api.vocobase.com/api/v2/campaigns"
payload = {
"name": "March renewals",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"phone_number_ids": ["pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f"],
"concurrency_limit": 10,
"retry_count": 2,
"retry_delays_minutes": [30, 240]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'March renewals',
agent_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
phone_number_ids: ['pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f'],
concurrency_limit: 10,
retry_count: 2,
retry_delays_minutes: [30, 240]
})
};
fetch('https://api.vocobase.com/api/v2/campaigns', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vocobase.com/api/v2/campaigns",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'March renewals',
'agent_id' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'phone_number_ids' => [
'pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f'
],
'concurrency_limit' => 10,
'retry_count' => 2,
'retry_delays_minutes' => [
30,
240
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vocobase.com/api/v2/campaigns"
payload := strings.NewReader("{\n \"name\": \"March renewals\",\n \"agent_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"phone_number_ids\": [\n \"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f\"\n ],\n \"concurrency_limit\": 10,\n \"retry_count\": 2,\n \"retry_delays_minutes\": [\n 30,\n 240\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vocobase.com/api/v2/campaigns")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"March renewals\",\n \"agent_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"phone_number_ids\": [\n \"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f\"\n ],\n \"concurrency_limit\": 10,\n \"retry_count\": 2,\n \"retry_delays_minutes\": [\n 30,\n 240\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vocobase.com/api/v2/campaigns")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"March renewals\",\n \"agent_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"phone_number_ids\": [\n \"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f\"\n ],\n \"concurrency_limit\": 10,\n \"retry_count\": 2,\n \"retry_delays_minutes\": [\n 30,\n 240\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"campaign_id": "cmp_7f3a1b02-4d5e-4c11-9a88-2e6f0c4d1a90",
"name": "March renewals",
"description": "Outbound renewal reminders",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"agent_name": "Renewals Agent",
"provider": null,
"type": "outbound",
"phone_numbers": [
{
"phone_number_id": "pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"phone_number": "+918065480085"
}
],
"concurrency_limit": 10,
"retry_concurrency": 3,
"retry_count": 2,
"cooldown_minutes": 60,
"retry_delays_minutes": [
30,
240
],
"callback_enabled": true,
"status": "draft",
"total_contacts": 0,
"completed_count": 0,
"failed_count": 0,
"skipped_count": 0,
"started_at": null,
"paused_at": null,
"completed_at": null,
"created_at": "2026-08-19T16:41:00.000Z"
}
}{
"success": false,
"error": {
"code": "PROVIDER_NOT_CONFIGURED",
"message": "Twilio telephony is not configured for this partner. Contact support."
}
}{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Resource not found"
}
}{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 60 seconds."
}
}{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred"
}
}Authorizations
API key in format: rg_live_xxxx. Pass as a Bearer token in the Authorization header.
Body
Required. Non-empty.
Required. Must be an active agent on your account.
INBOUND campaigns are not available on the API yet.
OUTBOUND Imported numbers to dial from. Each must be active, owned by you, and voice-capable.
Legacy alternative to phone_number_ids. Required when phone_number_ids is omitted. tata_smartflo is rejected — Smartflo does not support streaming voice bots on campaigns.
twilio, exotel, mcube, tata_smartflo Simultaneous first-attempt calls.
Simultaneous retry calls.
Retries per contact after the first call.
Fixed wait between retries.
Per-attempt waits. Overrides cooldown_minutes.
Set false to stop calls asking for a callback time.
curl --request POST \
--url https://api.vocobase.com/api/v2/campaigns \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "March renewals",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"phone_number_ids": [
"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f"
],
"concurrency_limit": 10,
"retry_count": 2,
"retry_delays_minutes": [
30,
240
]
}
'import requests
url = "https://api.vocobase.com/api/v2/campaigns"
payload = {
"name": "March renewals",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"phone_number_ids": ["pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f"],
"concurrency_limit": 10,
"retry_count": 2,
"retry_delays_minutes": [30, 240]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'March renewals',
agent_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
phone_number_ids: ['pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f'],
concurrency_limit: 10,
retry_count: 2,
retry_delays_minutes: [30, 240]
})
};
fetch('https://api.vocobase.com/api/v2/campaigns', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vocobase.com/api/v2/campaigns",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'March renewals',
'agent_id' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'phone_number_ids' => [
'pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f'
],
'concurrency_limit' => 10,
'retry_count' => 2,
'retry_delays_minutes' => [
30,
240
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vocobase.com/api/v2/campaigns"
payload := strings.NewReader("{\n \"name\": \"March renewals\",\n \"agent_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"phone_number_ids\": [\n \"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f\"\n ],\n \"concurrency_limit\": 10,\n \"retry_count\": 2,\n \"retry_delays_minutes\": [\n 30,\n 240\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vocobase.com/api/v2/campaigns")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"March renewals\",\n \"agent_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"phone_number_ids\": [\n \"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f\"\n ],\n \"concurrency_limit\": 10,\n \"retry_count\": 2,\n \"retry_delays_minutes\": [\n 30,\n 240\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vocobase.com/api/v2/campaigns")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"March renewals\",\n \"agent_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"phone_number_ids\": [\n \"pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f\"\n ],\n \"concurrency_limit\": 10,\n \"retry_count\": 2,\n \"retry_delays_minutes\": [\n 30,\n 240\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"campaign_id": "cmp_7f3a1b02-4d5e-4c11-9a88-2e6f0c4d1a90",
"name": "March renewals",
"description": "Outbound renewal reminders",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"agent_name": "Renewals Agent",
"provider": null,
"type": "outbound",
"phone_numbers": [
{
"phone_number_id": "pn_1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"phone_number": "+918065480085"
}
],
"concurrency_limit": 10,
"retry_concurrency": 3,
"retry_count": 2,
"cooldown_minutes": 60,
"retry_delays_minutes": [
30,
240
],
"callback_enabled": true,
"status": "draft",
"total_contacts": 0,
"completed_count": 0,
"failed_count": 0,
"skipped_count": 0,
"started_at": null,
"paused_at": null,
"completed_at": null,
"created_at": "2026-08-19T16:41:00.000Z"
}
}{
"success": false,
"error": {
"code": "PROVIDER_NOT_CONFIGURED",
"message": "Twilio telephony is not configured for this partner. Contact support."
}
}{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Resource not found"
}
}{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 60 seconds."
}
}{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred"
}
}