Make your first Callaro call in one controlled sandbox cycle.
This flow validates the full lifecycle: key auth, campaign creation, contact ingestion, campaign launch, webhook receipt, and call-log verification.
Prerequisites
- Sandbox tenant with at least one published agent.
- One active outbound-capable phone number in sandbox.
- Tenant API key with
bulk_call_campaigns:write, contacts:write, voice_sessions:read.
- A webhook endpoint or request bin for payload validation.
- 2-3 safe test contacts with consented test numbers.
Success criteria
Campaign enters launched state without validation errors
API returns 200/201 on create and launch endpoints.
At least one call reaches terminal state
A voice_session record appears and includes outcome metadata.
Webhook arrives and is processable
Receiver stores one call.completed payload with dedupe key handling.
Logs and recordings are retrievable
You can fetch session detail and recording endpoint without auth or routing failures.
Step 1: Create a draft campaign
curl -X POST "https://api.callaro.ai/api/v1/bulk_call_campaigns" \
-H "X-Api-Key: $CALLARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sandbox Quickstart Campaign",
"agent_id": 42,
"timezone": "Asia/Kolkata",
"campaign_phone_number_ids": [101],
"concurrency_limit": 2
}'
const createCampaign = await fetch('https://api.callaro.ai/api/v1/bulk_call_campaigns', {
method: 'POST',
headers: {
'X-Api-Key': process.env.CALLARO_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Sandbox Quickstart Campaign',
agent_id: 42,
timezone: 'Asia/Kolkata',
campaign_phone_number_ids: [101],
concurrency_limit: 2
})
});
const campaignPayload = await createCampaign.json();
const campaignId = campaignPayload.data.id;
Expected result: 201 and a campaign ID.
curl -X POST "https://api.callaro.ai/api/v1/contacts/import" \
-H "X-Api-Key: $CALLARO_API_KEY" \
-F "file=@contacts.csv" \
-F 'column_mapping={"Phone":"phone_e164","First Name":"first_name","Last Name":"last_name"}'
const formData = new FormData();
const csvBody = 'Phone,First Name,Last Name\n+919900000001,Test,Lead1\n+919900000002,Test,Lead2';
formData.append('file', new Blob([csvBody], { type: 'text/csv' }), 'contacts.csv');
formData.append('column_mapping', JSON.stringify({
Phone: 'phone_e164',
'First Name': 'first_name',
'Last Name': 'last_name'
}));
await fetch('https://api.callaro.ai/api/v1/contacts/import', {
method: 'POST',
headers: { 'X-Api-Key': process.env.CALLARO_API_KEY },
body: formData
});
Expected result: 202 or 201 and import job accepted.
Step 3: Launch the campaign
curl -X POST "https://api.callaro.ai/api/v1/bulk_call_campaigns/123/launch" \
-H "X-Api-Key: $CALLARO_API_KEY"
await fetch('https://api.callaro.ai/api/v1/bulk_call_campaigns/123/launch', {
method: 'POST',
headers: { 'X-Api-Key': process.env.CALLARO_API_KEY }
});
Expected result: 200 with launched campaign state.
Step 4: Verify call execution
curl "https://api.callaro.ai/api/v1/voice_sessions?page_size=25" \
-H "X-Api-Key: $CALLARO_API_KEY"
curl "https://api.callaro.ai/api/v1/voice_sessions/9001" \
-H "X-Api-Key: $CALLARO_API_KEY"
const sessions = await fetch('https://api.callaro.ai/api/v1/voice_sessions?page_size=25', {
headers: { 'X-Api-Key': process.env.CALLARO_API_KEY }
});
const sessionsPayload = await sessions.json();
console.log(sessionsPayload.data?.items?.[0], sessionsPayload.data?.next_cursor);
Verify:
voice_session exists for your campaign contacts.
duration_seconds, outcome, and transcript fields are populated.
- webhook receiver got
call.completed.
Common failure modes
| Symptom | Likely cause | Fix |
|---|
401 on create/launch | Wrong key or environment | Validate key source and base URL. |
422 on launch | Missing contact list, number, or invalid campaign state | Check campaign payload and contact import status. |
| No calls created | Number health or schedule window blocks dispatch | Check campaign timezone window and number assignment. |
| Webhook not received | Wrong endpoint URL or receiver error | Use request bin first, then move to production webhook worker. |
Cleanup
- Pause/cancel test campaign after validation.
- Remove or archive test contacts.
- Revoke temporary keys used for quickstart if shared during testing.
Do not promote to production until this flow succeeds twice with independent test contacts and your webhook consumer proves idempotent behavior.