For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Atoms PlatformProduct OverviewDeveloper GuideAPI ReferenceMCPIntegrationsDeveloper ToolsChangelog
Atoms PlatformProduct OverviewDeveloper GuideAPI ReferenceMCPIntegrationsDeveloper ToolsChangelog
  • Get Started
    • Quickstart Crew CLI
    • Overview
    • Error Handling
  • Build
      • Overview
      • Managing Audiences
      • Creating Campaigns
  • Operate
  • Examples
    • Examples
  • Migrate
    • From ElevenLabs
LogoLogo
Voice AgentsModels
Voice AgentsModels
On this page
  • Prerequisites
  • Getting Your Phone Number
  • Creating a Campaign
  • Campaign Parameters
  • Scheduling a campaign (REST)
  • Starting a Campaign
  • Monitoring Progress
  • Cleaning Up
  • SDK Reference
  • Tips
BuildCampaigns

Running Campaigns

||View as Markdown|
Was this page helpful?
Previous

Audiences

Next

Testing & Debugging

Built with

This guide walks through the complete campaign lifecycle—from setup to cleanup.

Prerequisites

Before creating a campaign, you need:

  • Agent ID — Create one with new_agent() or use an existing agent
  • Audience ID — Create one with create_audience() (see Audiences)
  • Phone Number ID — Retrieve available numbers with get_phone_numbers()

Getting Your Phone Number

get_phone_numbers() returns all outbound phone numbers available for campaigns:

1from smallestai.atoms import AtomsClient
2from smallestai.atoms.campaign import Campaign
3
4client = AtomsClient()
5campaign = Campaign()
6
7phones = client.get_phone_numbers()
8phone_id = phones["data"][0]["_id"]

Each phone includes provider details:

1{
2 "status": true,
3 "data": [
4 {
5 "_id": "6963d3a8862e1cb702da7244",
6 "attributes": {
7 "provider": "plivo",
8 "phoneNumber": "+912268093560"
9 },
10 "isActive": true
11 }
12 ]
13}

Creating a Campaign

create() creates a campaign linking your agent, audience, and phone number:

1response = campaign.create(
2 name="January Outreach",
3 agent_id=agent_id,
4 audience_id=audience_id,
5 phone_ids=[phone_id],
6 max_retries=2,
7 retry_delay=30
8)
9
10campaign_id = response["data"]["_id"]

The response includes all campaign details:

1{
2 "status": true,
3 "data": {
4 "name": "January Outreach",
5 "agentId": "696ddd281ea16a73cb8aafbe",
6 "audienceId": "696ddd287f45bf7b27344e7c",
7 "participantsCount": 2,
8 "maxRetries": 2,
9 "retryDelay": 30,
10 "status": "draft",
11 "_id": "696ddd2a04ff172dbd8eddad"
12 // ...
13 }
14}

Campaign Parameters

ParameterTypeDescription
namestringCampaign name (required)
agent_idstringAgent to handle calls (required)
audience_idstringContacts to dial (required)
phone_idslistOutbound phone number IDs (required)
max_retriesintRetry attempts for failed calls (0–10, default: 3)
retry_delayintMinutes between retries (1–1440, default: 15)

Scheduling a campaign (REST)

POST /campaign also accepts an optional scheduledAt (ISO-8601, must be in the future) to defer the first dial-out. If provided, the campaign is created in scheduled status and begins automatically at the specified time.

$curl -X POST "https://api.smallest.ai/atoms/v1/campaign" \
> -H "Authorization: Bearer $SMALLEST_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "name": "January Outreach",
> "agentId": "696ddd281ea16a73cb8aafbe",
> "audienceId": "696ddd287f45bf7b27344e7c",
> "phoneNumberIds": ["6963d3a8862e1cb702da7244"],
> "scheduledAt": "2026-04-24T10:00:00.000Z",
> "maxRetries": 3,
> "retryDelay": 15
> }'

Full request/response shape: see POST /campaign in the API reference.


Starting a Campaign

start() begins dialing contacts in the audience:

1result = campaign.start(campaign_id)

The response confirms the campaign is processing:

1{
2 "status": true,
3 "data": {
4 "message": "Campaign is being processed",
5 "taskId": "081a5402-3f1f-4447-a257-6dd7bc6bad60",
6 "campaignId": "696ddd2a04ff172dbd8eddad"
7 }
8}

Monitoring Progress

get() returns the campaign status, execution history, and metrics:

1status = campaign.get(campaign_id)
2
3data = status["data"]["campaign"]
4metrics = status["data"]["metrics"]
5
6print(f"Status: {data['status']}")
7print(f"Called: {metrics['contacts_called']}/{metrics['total_participants']}")
8print(f"Connected: {metrics['contacts_connected']}")

Full status response:

1{
2 "status": true,
3 "data": {
4 "campaign": {
5 "status": "running",
6 "executions": [
7 {
8 "executionNumber": 1,
9 "status": "completed",
10 "totalMembers": 2,
11 "processedMembers": 2
12 }
13 ]
14 },
15 // ...
16 "metrics": {
17 "total_participants": 2,
18 "contacts_called": 2,
19 "contacts_connected": 1
20 }
21 }
22}

Cleaning Up

delete() removes the campaign and its execution history:

1campaign.delete(campaign_id)

Running campaigns should be paused before deletion. Use pause(id) first if needed.


SDK Reference

MethodDescription
get_phone_numbers()List available outbound numbers (via generic client)
create(...)Create a campaign
start(id)Begin dialing
get(id)Get status and metrics
pause(id)Pause a running campaign
delete(id)Remove a campaign

Tips

Why are contacts_called and contacts_connected different?

contacts_called counts dial attempts. contacts_connected counts answered calls. The difference represents voicemail, busy signals, and no-answers.

What happens when a call fails?

Failed calls enter the retry queue based on your max_retries and retry_delay settings. After all retries are exhausted, the contact is marked as failed.

Can I run multiple campaigns simultaneously?

Yes. Each campaign operates independently. Just ensure you have sufficient phone capacity for parallel dialing.

How do I change an agent mid-campaign?

Campaigns cannot change agents after creation. Create a new campaign with the desired agent and audience.