Skip to main content
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:
from smallestai.atoms import AtomsClient
from smallestai.atoms.campaign import Campaign

client = AtomsClient()
campaign = Campaign()

phones = client.get_phone_numbers()
phone_id = phones["data"][0]["_id"]
Each phone includes provider details:
{
  "status": true,
  "data": [
    {
      "_id": "6963d3a8862e1cb702da7244",
      "attributes": {
        "provider": "plivo",
        "phoneNumber": "+912268093560"
      },
      "isActive": true
    }
  ]
}

Creating a Campaign

create() creates a campaign linking your agent, audience, and phone number:
response = campaign.create(
    name="January Outreach",
    agent_id=agent_id,
    audience_id=audience_id,
    phone_ids=[phone_id],
    max_retries=2,
    retry_delay=30
)

campaign_id = response["data"]["_id"]
The response includes all campaign details:
{
  "status": true,
  "data": {
    "name": "January Outreach",
    "agentId": "696ddd281ea16a73cb8aafbe",
    "audienceId": "696ddd287f45bf7b27344e7c",
    "participantsCount": 2,
    "maxRetries": 2,
    "retryDelay": 30,
    "status": "draft",
    "_id": "696ddd2a04ff172dbd8eddad"
    // ...
  }
}

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)

Starting a Campaign

start() begins dialing contacts in the audience:
result = campaign.start(campaign_id)
The response confirms the campaign is processing:
{
  "status": true,
  "data": {
    "message": "Campaign is being processed",
    "taskId": "081a5402-3f1f-4447-a257-6dd7bc6bad60",
    "campaignId": "696ddd2a04ff172dbd8eddad"
  }
}

Monitoring Progress

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

data = status["data"]["campaign"]
metrics = status["data"]["metrics"]

print(f"Status: {data['status']}")
print(f"Called: {metrics['contacts_called']}/{metrics['total_participants']}")
print(f"Connected: {metrics['contacts_connected']}")
Full status response:
{
  "status": true,
  "data": {
    "campaign": {
      "status": "running",
      "executions": [
        {
          "executionNumber": 1,
          "status": "completed",
          "totalMembers": 2,
          "processedMembers": 2
        }
      ]
    },
    // ...
    "metrics": {
      "total_participants": 2,
      "contacts_called": 2,
      "contacts_connected": 1
    }
  }
}

Cleaning Up

delete() removes the campaign and its execution history:
campaign.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

contacts_called counts dial attempts. contacts_connected counts answered calls. The difference represents voicemail, busy signals, and no-answers.
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.
Yes. Each campaign operates independently. Just ensure you have sufficient phone capacity for parallel dialing.
Campaigns cannot change agents after creation. Create a new campaign with the desired agent and audience.