Create Campaign
curl --request POST \
--url https://app.bananaflow.ai/api/v1/campaign/create \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"source_type": "<string>",
"source_id": "<string>",
"workflow_id": 1,
"traffic_split": {
"variants": [
{
"workflow_id": 123,
"weight": 50,
"workflow_definition_id": 1
}
]
},
"telephony_configuration_id": 123,
"retry_config": {
"enabled": true,
"max_retries": 2,
"retry_delay_seconds": 120,
"retry_on_busy": true,
"retry_on_no_answer": true,
"retry_on_voicemail": true
},
"max_concurrency": 2,
"rate_limit_per_second": 1,
"schedule_config": {
"slots": [
{
"day_of_week": 3,
"start_time": "<string>",
"end_time": "<string>"
}
],
"enabled": true,
"timezone": "UTC"
},
"circuit_breaker": {
"enabled": true,
"failure_threshold": 0.5,
"window_seconds": 120,
"min_calls_in_window": 5
}
}
'import requests
url = "https://app.bananaflow.ai/api/v1/campaign/create"
payload = {
"name": "<string>",
"source_type": "<string>",
"source_id": "<string>",
"workflow_id": 1,
"traffic_split": { "variants": [
{
"workflow_id": 123,
"weight": 50,
"workflow_definition_id": 1
}
] },
"telephony_configuration_id": 123,
"retry_config": {
"enabled": True,
"max_retries": 2,
"retry_delay_seconds": 120,
"retry_on_busy": True,
"retry_on_no_answer": True,
"retry_on_voicemail": True
},
"max_concurrency": 2,
"rate_limit_per_second": 1,
"schedule_config": {
"slots": [
{
"day_of_week": 3,
"start_time": "<string>",
"end_time": "<string>"
}
],
"enabled": True,
"timezone": "UTC"
},
"circuit_breaker": {
"enabled": True,
"failure_threshold": 0.5,
"window_seconds": 120,
"min_calls_in_window": 5
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
source_type: '<string>',
source_id: '<string>',
workflow_id: 1,
traffic_split: {variants: [{workflow_id: 123, weight: 50, workflow_definition_id: 1}]},
telephony_configuration_id: 123,
retry_config: {
enabled: true,
max_retries: 2,
retry_delay_seconds: 120,
retry_on_busy: true,
retry_on_no_answer: true,
retry_on_voicemail: true
},
max_concurrency: 2,
rate_limit_per_second: 1,
schedule_config: {
slots: [{day_of_week: 3, start_time: '<string>', end_time: '<string>'}],
enabled: true,
timezone: 'UTC'
},
circuit_breaker: {
enabled: true,
failure_threshold: 0.5,
window_seconds: 120,
min_calls_in_window: 5
}
})
};
fetch('https://app.bananaflow.ai/api/v1/campaign/create', 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://app.bananaflow.ai/api/v1/campaign/create",
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' => '<string>',
'source_type' => '<string>',
'source_id' => '<string>',
'workflow_id' => 1,
'traffic_split' => [
'variants' => [
[
'workflow_id' => 123,
'weight' => 50,
'workflow_definition_id' => 1
]
]
],
'telephony_configuration_id' => 123,
'retry_config' => [
'enabled' => true,
'max_retries' => 2,
'retry_delay_seconds' => 120,
'retry_on_busy' => true,
'retry_on_no_answer' => true,
'retry_on_voicemail' => true
],
'max_concurrency' => 2,
'rate_limit_per_second' => 1,
'schedule_config' => [
'slots' => [
[
'day_of_week' => 3,
'start_time' => '<string>',
'end_time' => '<string>'
]
],
'enabled' => true,
'timezone' => 'UTC'
],
'circuit_breaker' => [
'enabled' => true,
'failure_threshold' => 0.5,
'window_seconds' => 120,
'min_calls_in_window' => 5
]
]),
CURLOPT_HTTPHEADER => [
"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://app.bananaflow.ai/api/v1/campaign/create"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"source_type\": \"<string>\",\n \"source_id\": \"<string>\",\n \"workflow_id\": 1,\n \"traffic_split\": {\n \"variants\": [\n {\n \"workflow_id\": 123,\n \"weight\": 50,\n \"workflow_definition_id\": 1\n }\n ]\n },\n \"telephony_configuration_id\": 123,\n \"retry_config\": {\n \"enabled\": true,\n \"max_retries\": 2,\n \"retry_delay_seconds\": 120,\n \"retry_on_busy\": true,\n \"retry_on_no_answer\": true,\n \"retry_on_voicemail\": true\n },\n \"max_concurrency\": 2,\n \"rate_limit_per_second\": 1,\n \"schedule_config\": {\n \"slots\": [\n {\n \"day_of_week\": 3,\n \"start_time\": \"<string>\",\n \"end_time\": \"<string>\"\n }\n ],\n \"enabled\": true,\n \"timezone\": \"UTC\"\n },\n \"circuit_breaker\": {\n \"enabled\": true,\n \"failure_threshold\": 0.5,\n \"window_seconds\": 120,\n \"min_calls_in_window\": 5\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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://app.bananaflow.ai/api/v1/campaign/create")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"source_type\": \"<string>\",\n \"source_id\": \"<string>\",\n \"workflow_id\": 1,\n \"traffic_split\": {\n \"variants\": [\n {\n \"workflow_id\": 123,\n \"weight\": 50,\n \"workflow_definition_id\": 1\n }\n ]\n },\n \"telephony_configuration_id\": 123,\n \"retry_config\": {\n \"enabled\": true,\n \"max_retries\": 2,\n \"retry_delay_seconds\": 120,\n \"retry_on_busy\": true,\n \"retry_on_no_answer\": true,\n \"retry_on_voicemail\": true\n },\n \"max_concurrency\": 2,\n \"rate_limit_per_second\": 1,\n \"schedule_config\": {\n \"slots\": [\n {\n \"day_of_week\": 3,\n \"start_time\": \"<string>\",\n \"end_time\": \"<string>\"\n }\n ],\n \"enabled\": true,\n \"timezone\": \"UTC\"\n },\n \"circuit_breaker\": {\n \"enabled\": true,\n \"failure_threshold\": 0.5,\n \"window_seconds\": 120,\n \"min_calls_in_window\": 5\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.bananaflow.ai/api/v1/campaign/create")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"source_type\": \"<string>\",\n \"source_id\": \"<string>\",\n \"workflow_id\": 1,\n \"traffic_split\": {\n \"variants\": [\n {\n \"workflow_id\": 123,\n \"weight\": 50,\n \"workflow_definition_id\": 1\n }\n ]\n },\n \"telephony_configuration_id\": 123,\n \"retry_config\": {\n \"enabled\": true,\n \"max_retries\": 2,\n \"retry_delay_seconds\": 120,\n \"retry_on_busy\": true,\n \"retry_on_no_answer\": true,\n \"retry_on_voicemail\": true\n },\n \"max_concurrency\": 2,\n \"rate_limit_per_second\": 1,\n \"schedule_config\": {\n \"slots\": [\n {\n \"day_of_week\": 3,\n \"start_time\": \"<string>\",\n \"end_time\": \"<string>\"\n }\n ],\n \"enabled\": true,\n \"timezone\": \"UTC\"\n },\n \"circuit_breaker\": {\n \"enabled\": true,\n \"failure_threshold\": 0.5,\n \"window_seconds\": 120,\n \"min_calls_in_window\": 5\n }\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"name": "<string>",
"workflow_id": 123,
"workflow_name": "<string>",
"state": "<string>",
"source_type": "<string>",
"source_id": "<string>",
"total_rows": 123,
"processed_rows": 123,
"failed_rows": 123,
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"retry_config": {
"enabled": true,
"max_retries": 123,
"retry_delay_seconds": 123,
"retry_on_busy": true,
"retry_on_no_answer": true,
"retry_on_voicemail": true
},
"traffic_split": {
"revision": 123,
"variants": [
{
"workflow_id": 123,
"weight": 50,
"id": "<string>",
"workflow_name": "<string>",
"workflow_definition_id": 1,
"version_number": 123
}
]
},
"max_concurrency": 123,
"rate_limit_per_second": 1,
"schedule_config": {
"enabled": true,
"timezone": "<string>",
"slots": [
{
"day_of_week": 123,
"start_time": "<string>",
"end_time": "<string>"
}
]
},
"circuit_breaker": {
"enabled": false,
"failure_threshold": 0.5,
"window_seconds": 120,
"min_calls_in_window": 5
},
"executed_count": 0,
"total_queued_count": 0,
"parent_campaign_id": 123,
"redialed_campaign_id": 123,
"telephony_configuration_id": 123,
"telephony_configuration_name": "<string>",
"logs": [
{
"ts": "<string>",
"level": "<string>",
"event": "<string>",
"message": "<string>",
"details": {}
}
],
"warnings": [
"<string>"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Campaigns
Create Campaign
Create a new outbound calling campaign
POST
/
api
/
v1
/
campaign
/
create
Create Campaign
curl --request POST \
--url https://app.bananaflow.ai/api/v1/campaign/create \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"source_type": "<string>",
"source_id": "<string>",
"workflow_id": 1,
"traffic_split": {
"variants": [
{
"workflow_id": 123,
"weight": 50,
"workflow_definition_id": 1
}
]
},
"telephony_configuration_id": 123,
"retry_config": {
"enabled": true,
"max_retries": 2,
"retry_delay_seconds": 120,
"retry_on_busy": true,
"retry_on_no_answer": true,
"retry_on_voicemail": true
},
"max_concurrency": 2,
"rate_limit_per_second": 1,
"schedule_config": {
"slots": [
{
"day_of_week": 3,
"start_time": "<string>",
"end_time": "<string>"
}
],
"enabled": true,
"timezone": "UTC"
},
"circuit_breaker": {
"enabled": true,
"failure_threshold": 0.5,
"window_seconds": 120,
"min_calls_in_window": 5
}
}
'import requests
url = "https://app.bananaflow.ai/api/v1/campaign/create"
payload = {
"name": "<string>",
"source_type": "<string>",
"source_id": "<string>",
"workflow_id": 1,
"traffic_split": { "variants": [
{
"workflow_id": 123,
"weight": 50,
"workflow_definition_id": 1
}
] },
"telephony_configuration_id": 123,
"retry_config": {
"enabled": True,
"max_retries": 2,
"retry_delay_seconds": 120,
"retry_on_busy": True,
"retry_on_no_answer": True,
"retry_on_voicemail": True
},
"max_concurrency": 2,
"rate_limit_per_second": 1,
"schedule_config": {
"slots": [
{
"day_of_week": 3,
"start_time": "<string>",
"end_time": "<string>"
}
],
"enabled": True,
"timezone": "UTC"
},
"circuit_breaker": {
"enabled": True,
"failure_threshold": 0.5,
"window_seconds": 120,
"min_calls_in_window": 5
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
source_type: '<string>',
source_id: '<string>',
workflow_id: 1,
traffic_split: {variants: [{workflow_id: 123, weight: 50, workflow_definition_id: 1}]},
telephony_configuration_id: 123,
retry_config: {
enabled: true,
max_retries: 2,
retry_delay_seconds: 120,
retry_on_busy: true,
retry_on_no_answer: true,
retry_on_voicemail: true
},
max_concurrency: 2,
rate_limit_per_second: 1,
schedule_config: {
slots: [{day_of_week: 3, start_time: '<string>', end_time: '<string>'}],
enabled: true,
timezone: 'UTC'
},
circuit_breaker: {
enabled: true,
failure_threshold: 0.5,
window_seconds: 120,
min_calls_in_window: 5
}
})
};
fetch('https://app.bananaflow.ai/api/v1/campaign/create', 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://app.bananaflow.ai/api/v1/campaign/create",
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' => '<string>',
'source_type' => '<string>',
'source_id' => '<string>',
'workflow_id' => 1,
'traffic_split' => [
'variants' => [
[
'workflow_id' => 123,
'weight' => 50,
'workflow_definition_id' => 1
]
]
],
'telephony_configuration_id' => 123,
'retry_config' => [
'enabled' => true,
'max_retries' => 2,
'retry_delay_seconds' => 120,
'retry_on_busy' => true,
'retry_on_no_answer' => true,
'retry_on_voicemail' => true
],
'max_concurrency' => 2,
'rate_limit_per_second' => 1,
'schedule_config' => [
'slots' => [
[
'day_of_week' => 3,
'start_time' => '<string>',
'end_time' => '<string>'
]
],
'enabled' => true,
'timezone' => 'UTC'
],
'circuit_breaker' => [
'enabled' => true,
'failure_threshold' => 0.5,
'window_seconds' => 120,
'min_calls_in_window' => 5
]
]),
CURLOPT_HTTPHEADER => [
"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://app.bananaflow.ai/api/v1/campaign/create"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"source_type\": \"<string>\",\n \"source_id\": \"<string>\",\n \"workflow_id\": 1,\n \"traffic_split\": {\n \"variants\": [\n {\n \"workflow_id\": 123,\n \"weight\": 50,\n \"workflow_definition_id\": 1\n }\n ]\n },\n \"telephony_configuration_id\": 123,\n \"retry_config\": {\n \"enabled\": true,\n \"max_retries\": 2,\n \"retry_delay_seconds\": 120,\n \"retry_on_busy\": true,\n \"retry_on_no_answer\": true,\n \"retry_on_voicemail\": true\n },\n \"max_concurrency\": 2,\n \"rate_limit_per_second\": 1,\n \"schedule_config\": {\n \"slots\": [\n {\n \"day_of_week\": 3,\n \"start_time\": \"<string>\",\n \"end_time\": \"<string>\"\n }\n ],\n \"enabled\": true,\n \"timezone\": \"UTC\"\n },\n \"circuit_breaker\": {\n \"enabled\": true,\n \"failure_threshold\": 0.5,\n \"window_seconds\": 120,\n \"min_calls_in_window\": 5\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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://app.bananaflow.ai/api/v1/campaign/create")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"source_type\": \"<string>\",\n \"source_id\": \"<string>\",\n \"workflow_id\": 1,\n \"traffic_split\": {\n \"variants\": [\n {\n \"workflow_id\": 123,\n \"weight\": 50,\n \"workflow_definition_id\": 1\n }\n ]\n },\n \"telephony_configuration_id\": 123,\n \"retry_config\": {\n \"enabled\": true,\n \"max_retries\": 2,\n \"retry_delay_seconds\": 120,\n \"retry_on_busy\": true,\n \"retry_on_no_answer\": true,\n \"retry_on_voicemail\": true\n },\n \"max_concurrency\": 2,\n \"rate_limit_per_second\": 1,\n \"schedule_config\": {\n \"slots\": [\n {\n \"day_of_week\": 3,\n \"start_time\": \"<string>\",\n \"end_time\": \"<string>\"\n }\n ],\n \"enabled\": true,\n \"timezone\": \"UTC\"\n },\n \"circuit_breaker\": {\n \"enabled\": true,\n \"failure_threshold\": 0.5,\n \"window_seconds\": 120,\n \"min_calls_in_window\": 5\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.bananaflow.ai/api/v1/campaign/create")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"source_type\": \"<string>\",\n \"source_id\": \"<string>\",\n \"workflow_id\": 1,\n \"traffic_split\": {\n \"variants\": [\n {\n \"workflow_id\": 123,\n \"weight\": 50,\n \"workflow_definition_id\": 1\n }\n ]\n },\n \"telephony_configuration_id\": 123,\n \"retry_config\": {\n \"enabled\": true,\n \"max_retries\": 2,\n \"retry_delay_seconds\": 120,\n \"retry_on_busy\": true,\n \"retry_on_no_answer\": true,\n \"retry_on_voicemail\": true\n },\n \"max_concurrency\": 2,\n \"rate_limit_per_second\": 1,\n \"schedule_config\": {\n \"slots\": [\n {\n \"day_of_week\": 3,\n \"start_time\": \"<string>\",\n \"end_time\": \"<string>\"\n }\n ],\n \"enabled\": true,\n \"timezone\": \"UTC\"\n },\n \"circuit_breaker\": {\n \"enabled\": true,\n \"failure_threshold\": 0.5,\n \"window_seconds\": 120,\n \"min_calls_in_window\": 5\n }\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"name": "<string>",
"workflow_id": 123,
"workflow_name": "<string>",
"state": "<string>",
"source_type": "<string>",
"source_id": "<string>",
"total_rows": 123,
"processed_rows": 123,
"failed_rows": 123,
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"retry_config": {
"enabled": true,
"max_retries": 123,
"retry_delay_seconds": 123,
"retry_on_busy": true,
"retry_on_no_answer": true,
"retry_on_voicemail": true
},
"traffic_split": {
"revision": 123,
"variants": [
{
"workflow_id": 123,
"weight": 50,
"id": "<string>",
"workflow_name": "<string>",
"workflow_definition_id": 1,
"version_number": 123
}
]
},
"max_concurrency": 123,
"rate_limit_per_second": 1,
"schedule_config": {
"enabled": true,
"timezone": "<string>",
"slots": [
{
"day_of_week": 123,
"start_time": "<string>",
"end_time": "<string>"
}
]
},
"circuit_breaker": {
"enabled": false,
"failure_threshold": 0.5,
"window_seconds": 120,
"min_calls_in_window": 5
},
"executed_count": 0,
"total_queued_count": 0,
"parent_campaign_id": 123,
"redialed_campaign_id": 123,
"telephony_configuration_id": 123,
"telephony_configuration_name": "<string>",
"logs": [
{
"ts": "<string>",
"level": "<string>",
"event": "<string>",
"message": "<string>",
"details": {}
}
],
"warnings": [
"<string>"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Before creating a campaign, upload your contacts CSV to get a
Once created, the campaign is in
You can specify one to five unique agent/version pairs. Weights must be whole percentages from 1 to 100 and total 100. All agents must belong to your organization, and your CSV must supply the template variables required by every selected version.
Omit
source_url.
Set telephony_configuration_id to pin the campaign to a specific telephony configuration. If omitted, Bananaflow falls back to the organization’s default outbound configuration – supplying an id that doesn’t exist in your organization returns 400 telephony_configuration_not_found.
The time_slots field controls when Bananaflow is allowed to place calls. If omitted, calls can be placed at any time. The timezone field applies to all time slot windows.
{
"time_slots": [
{ "day": "monday", "start": "09:00", "end": "17:00" },
{ "day": "tuesday", "start": "09:00", "end": "17:00" }
]
}
draft status. Call Start to begin dialing.
To split calls between agents or versions, send traffic_split instead of workflow_id:
{
"name": "Version comparison",
"source_type": "csv",
"source_id": "your-uploaded-csv-key",
"traffic_split": {
"variants": [
{ "workflow_id": 12, "workflow_definition_id": null, "weight": 50 },
{ "workflow_id": 12, "workflow_definition_id": 341, "weight": 50 }
]
}
}
workflow_definition_id or set it to null to use the latest published version at dial time. A definition ID pins a published or archived version; drafts cannot be selected. Calls already in progress keep their version.
You can change the split with PATCH /api/v1/campaign/{campaign_id} while a campaign is running or paused. Changes apply to the next batch, including retries. A contact stays on the same variant while the split is unchanged; changing weights or removing variants can move contacts. Reordering existing variants alone does not change allocation. Redial campaigns inherit the current split and its allocation seed.
The campaign detail page shows current target percentages and actual shares across all attempts, including retries and earlier splits. Shares are approximate, especially with small contact lists. GET /api/v1/campaign/{campaign_id}/traffic-stats returns the same counts, outcomes, and versions used, including variants removed from the current split.Body
application/json
Required string length:
1 - 255Pattern:
^csv$Required range:
x > 0Show child attributes
Show child attributes
Show child attributes
Show child attributes
Required range:
x >= 1Required range:
x >= 1Show child attributes
Show child attributes
Show child attributes
Show child attributes
Response
Successful Response
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Was this page helpful?