Campaigns
Add contacts to a campaign
Adds contacts by phone number. Numbers are canonicalised to E.164 before storage, so the same number written two ways resolves to one contact.
Contacts already in your library are reused rather than duplicated, and contacts already on this campaign are counted as duplicates and skipped. Adding contacts to a completed campaign re-opens it to paused, not running — the response says so via campaign_reopened. Dialling does not resume on its own: call POST /campaigns/{id}/resume, which re-validates caller IDs and provider access first.
Maximum 10,000 contacts per request.
POST
/
campaigns
/
{id}
/
contacts
Add contacts to a campaign
curl --request POST \
--url https://api.vocobase.com/api/v2/campaigns/{id}/contacts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contacts": [
{
"phone": "+919876543210",
"name": "Asha Menon",
"metadata": {
"plan": "pro",
"renews_on": "2026-09-01"
}
},
{
"phone": "+919812345678",
"name": "Ravi Kumar"
}
]
}
'import requests
url = "https://api.vocobase.com/api/v2/campaigns/{id}/contacts"
payload = { "contacts": [
{
"phone": "+919876543210",
"name": "Asha Menon",
"metadata": {
"plan": "pro",
"renews_on": "2026-09-01"
}
},
{
"phone": "+919812345678",
"name": "Ravi Kumar"
}
] }
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({
contacts: [
{
phone: '+919876543210',
name: 'Asha Menon',
metadata: {plan: 'pro', renews_on: '2026-09-01'}
},
{phone: '+919812345678', name: 'Ravi Kumar'}
]
})
};
fetch('https://api.vocobase.com/api/v2/campaigns/{id}/contacts', 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/{id}/contacts",
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([
'contacts' => [
[
'phone' => '+919876543210',
'name' => 'Asha Menon',
'metadata' => [
'plan' => 'pro',
'renews_on' => '2026-09-01'
]
],
[
'phone' => '+919812345678',
'name' => 'Ravi Kumar'
]
]
]),
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/{id}/contacts"
payload := strings.NewReader("{\n \"contacts\": [\n {\n \"phone\": \"+919876543210\",\n \"name\": \"Asha Menon\",\n \"metadata\": {\n \"plan\": \"pro\",\n \"renews_on\": \"2026-09-01\"\n }\n },\n {\n \"phone\": \"+919812345678\",\n \"name\": \"Ravi Kumar\"\n }\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/{id}/contacts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contacts\": [\n {\n \"phone\": \"+919876543210\",\n \"name\": \"Asha Menon\",\n \"metadata\": {\n \"plan\": \"pro\",\n \"renews_on\": \"2026-09-01\"\n }\n },\n {\n \"phone\": \"+919812345678\",\n \"name\": \"Ravi Kumar\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vocobase.com/api/v2/campaigns/{id}/contacts")
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 \"contacts\": [\n {\n \"phone\": \"+919876543210\",\n \"name\": \"Asha Menon\",\n \"metadata\": {\n \"plan\": \"pro\",\n \"renews_on\": \"2026-09-01\"\n }\n },\n {\n \"phone\": \"+919812345678\",\n \"name\": \"Ravi Kumar\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"added": 2,
"duplicates": 0,
"contacts_created": 1,
"contacts_existing": 1,
"campaign_reopened": false
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid E.164 phone numbers: 9876543210, 044-1234"
}
}{
"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.
Path Parameters
Campaign ID.
Body
application/json
Required array length:
1 - 10000 elementsShow child attributes
Show child attributes
⌘I
Add contacts to a campaign
curl --request POST \
--url https://api.vocobase.com/api/v2/campaigns/{id}/contacts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contacts": [
{
"phone": "+919876543210",
"name": "Asha Menon",
"metadata": {
"plan": "pro",
"renews_on": "2026-09-01"
}
},
{
"phone": "+919812345678",
"name": "Ravi Kumar"
}
]
}
'import requests
url = "https://api.vocobase.com/api/v2/campaigns/{id}/contacts"
payload = { "contacts": [
{
"phone": "+919876543210",
"name": "Asha Menon",
"metadata": {
"plan": "pro",
"renews_on": "2026-09-01"
}
},
{
"phone": "+919812345678",
"name": "Ravi Kumar"
}
] }
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({
contacts: [
{
phone: '+919876543210',
name: 'Asha Menon',
metadata: {plan: 'pro', renews_on: '2026-09-01'}
},
{phone: '+919812345678', name: 'Ravi Kumar'}
]
})
};
fetch('https://api.vocobase.com/api/v2/campaigns/{id}/contacts', 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/{id}/contacts",
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([
'contacts' => [
[
'phone' => '+919876543210',
'name' => 'Asha Menon',
'metadata' => [
'plan' => 'pro',
'renews_on' => '2026-09-01'
]
],
[
'phone' => '+919812345678',
'name' => 'Ravi Kumar'
]
]
]),
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/{id}/contacts"
payload := strings.NewReader("{\n \"contacts\": [\n {\n \"phone\": \"+919876543210\",\n \"name\": \"Asha Menon\",\n \"metadata\": {\n \"plan\": \"pro\",\n \"renews_on\": \"2026-09-01\"\n }\n },\n {\n \"phone\": \"+919812345678\",\n \"name\": \"Ravi Kumar\"\n }\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/{id}/contacts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contacts\": [\n {\n \"phone\": \"+919876543210\",\n \"name\": \"Asha Menon\",\n \"metadata\": {\n \"plan\": \"pro\",\n \"renews_on\": \"2026-09-01\"\n }\n },\n {\n \"phone\": \"+919812345678\",\n \"name\": \"Ravi Kumar\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vocobase.com/api/v2/campaigns/{id}/contacts")
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 \"contacts\": [\n {\n \"phone\": \"+919876543210\",\n \"name\": \"Asha Menon\",\n \"metadata\": {\n \"plan\": \"pro\",\n \"renews_on\": \"2026-09-01\"\n }\n },\n {\n \"phone\": \"+919812345678\",\n \"name\": \"Ravi Kumar\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"added": 2,
"duplicates": 0,
"contacts_created": 1,
"contacts_existing": 1,
"campaign_reopened": false
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid E.164 phone numbers: 9876543210, 044-1234"
}
}{
"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"
}
}