Skip to main content

Outbound Calls

Make your AI agents proactively reach out to customers by scheduling outbound voice calls. Whether you’re conducting surveys, sending appointment reminders, qualifying leads, or running customer outreach campaigns, Dasha BlackBox provides both dashboard and API-based tools for scheduling and managing outbound calls at scale.

What are Outbound Calls?

Outbound calls are voice calls initiated by your AI agent to call recipients you specify. Unlike inbound calls where customers call your agent, outbound calls have your agent proactively dial phone numbers on your behalf.

Common Use Cases

Sales and Lead Qualification
  • Call leads from CRM to qualify interest
  • Schedule product demos automatically
  • Follow up on abandoned carts
  • Re-engage dormant customers
Customer Service
  • Send appointment reminders (medical, service, consultations)
  • Notify customers of delivery status
  • Conduct satisfaction surveys after interactions
  • Provide proactive support for known issues
Emergency and Notifications
  • Mass notifications for critical alerts
  • School closure announcements
  • Service outage notifications
  • Event reminders and confirmations
Data Collection
  • Market research surveys
  • Customer feedback collection
  • Political polling
  • Verification calls
Best Practice: Always obtain consent before making outbound calls and comply with local regulations like TCPA (US), GDPR (EU), and do-not-call registries.

Prerequisites

Before scheduling outbound calls, ensure you have:

1. Configured Agent

Your agent must be:
  • Created and enabled (isEnabled: true)
  • Tested and working via dashboard or widget testing
  • Configured with appropriate prompts for outbound context
Use the Test & Deploy section in the agent creation wizard to verify your agent works correctly before scheduling real calls.

2. Caller ID Phone Number

You need a verified phone number for caller ID display: Why Caller ID Matters:
  • Recipients see this number when you call
  • Improves answer rates (recognized numbers)
  • Required by most carriers
  • Compliance with telephony regulations
Setting Up Caller ID:
  1. Navigate to your agent’s Phone tab in the dashboard
  2. Add and verify a phone number via Twilio integration
  3. Number appears as from number on outbound calls
See Phone Numbers for detailed setup instructions.

3. Valid Recipient Phone Numbers

Outbound calls require properly formatted phone numbers: Supported Formats:
  • E.164 format (recommended): +1-555-123-4567
  • SIP URIs: sip:user@domain.com
Phone Number Validation:
  • Must include country code
  • Must be dialable from your carrier
  • Should be active and in service
Invalid Numbers: Calls to invalid, disconnected, or blocked numbers will fail. Always validate phone numbers before scheduling bulk calls.

Scheduling Single Calls via Dashboard

Schedule individual outbound calls through the Dasha BlackBox dashboard.

Step 1: Navigate to Agent Details

  1. Go to Agents page
  2. Click on the agent you want to use for outbound calls
  3. Navigate to the Calls tab
  4. Click “Schedule Outbound Call” button
Agent calls tab with schedule button Schedule outbound calls from the agent detail page

Step 2: Configure Call Parameters

Fill in the call scheduling form: Recipient Phone Number (required)
  • Enter phone number in E.164 format
  • Example: +1-555-123-4567
  • Validates format on input
Priority Level (optional)
  • Range: 0-10 (default: 5)
  • Higher priority = earlier in queue
  • Use for urgent calls or VIP customers
Schedule Time (optional)
  • Immediate: Call as soon as possible (default)
  • Scheduled: Pick specific date and time
  • Timezone: Uses agent’s configured timezone
Call Deadline (optional)
  • Maximum time to attempt the call
  • Call canceled if not started by deadline
  • Useful for time-sensitive offers or appointments
Additional Data (optional)
  • JSON object with custom metadata
  • Available in webhooks and transcripts
  • Example: Customer ID, order number, campaign name

Step 3: Confirm and Schedule

  1. Review call parameters
  2. Click “Schedule Call”
  3. Call appears in Scheduled Calls list
  4. View status updates in real-time
Scheduled calls table showing queue status Monitor scheduled calls in the calls queue
Queue Processing: Calls are processed by the DWRR (Dynamic Weighted Round Robin) scheduler based on priority, deadline, and agent availability.

Scheduling Single Calls via API

Schedule outbound calls programmatically using the REST API.

Basic Call Scheduling

Schedule an immediate call to a single recipient:
const response = await fetch('https://blackbox.dasha.ai/api/v1/calls', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    agentId: "550e8400-e29b-41d4-a716-446655440000",
    endpoint: "+1-555-123-4567",
    priority: 5
  })
});

const call = await response.json();
console.log('Call scheduled:', call.callId);
console.log('Status:', call.status); // "Queued"
console.log('Next schedule time:', call.nextScheduleTime);
Response:
{
  "callId": "660e8400-e29b-41d4-a716-446655440001",
  "agentId": "550e8400-e29b-41d4-a716-446655440000",
  "endpoint": "+1-555-123-4567",
  "status": "Queued",
  "priority": 5,
  "createdTime": "2025-10-20T10:35:00Z",
  "nextScheduleTime": "2025-10-20T10:36:00Z"
}

Scheduled Call with Deadline

Schedule a call for a specific time with a maximum deadline:
const response = await fetch('https://blackbox.dasha.ai/api/v1/calls', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    agentId: "550e8400-e29b-41d4-a716-446655440000",
    endpoint: "+1-555-123-4567",
    priority: 8,
    deadline: "2025-10-20T17:00:00-05:00", // 5 PM Central Time
    additionalData: {
      customerId: "cust_789",
      appointmentType: "dental_checkup",
      appointmentTime: "2025-10-21T09:00:00"
    }
  })
});

const call = await response.json();
console.log('Appointment reminder scheduled:', call.callId);
Use Case: Appointment reminder call scheduled to go out before 5 PM, with customer and appointment details included.

Call with Custom Metadata

Include custom data for use in webhooks, transcripts, and analytics:
const response = await fetch('https://blackbox.dasha.ai/api/v1/calls', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    agentId: "550e8400-e29b-41d4-a716-446655440000",
    endpoint: "+1-555-555-0100",
    priority: 7,
    additionalData: {
      // Custom metadata accessible in webhooks
      leadId: "lead_12345",
      leadSource: "website_form",
      productInterest: "enterprise_plan",
      lastInteraction: "2025-10-15",
      campaignId: "fall_2025_outreach",
      salesRepId: "rep_456"
    }
  })
});
Accessing Custom Data:
  • Available in all webhook payloads (call.additionalData)
  • Visible in call transcripts and inspector
  • Searchable in call results API
  • Useful for CRM integration and tracking
Pro Tip: Use additionalData to pass context that helps your agent personalize the conversation or helps your systems track the call’s purpose.

Bulk Call Scheduling

Schedule hundreds or thousands of calls in a single API request.

Bulk Scheduling Endpoint

Use POST /api/v1/calls/bulk to schedule multiple calls at once:
const response = await fetch('https://blackbox.dasha.ai/api/v1/calls/bulk', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    agentId: "550e8400-e29b-41d4-a716-446655440000",
    calls: [
      {
        endpoint: "+1-555-123-0001",
        priority: 5,
        additionalData: { customerId: "cust_001", segment: "high_value" }
      },
      {
        endpoint: "+1-555-123-0002",
        priority: 6,
        additionalData: { customerId: "cust_002", segment: "medium_value" }
      },
      {
        endpoint: "+1-555-123-0003",
        priority: 5,
        additionalData: { customerId: "cust_003", segment: "high_value" }
      }
      // ... up to 1000 calls per request
    ]
  })
});

const result = await response.json();
console.log('Scheduled calls:', result.scheduled.length);
console.log('Failed calls:', result.failed.length);
console.log('Total:', result.total);
Response:
{
  "total": 3,
  "scheduled": [
    {
      "callId": "660e8400-e29b-41d4-a716-446655440001",
      "endpoint": "+1-555-123-0001",
      "status": "Queued"
    },
    {
      "callId": "660e8400-e29b-41d4-a716-446655440002",
      "endpoint": "+1-555-123-0002",
      "status": "Queued"
    },
    {
      "callId": "660e8400-e29b-41d4-a716-446655440003",
      "endpoint": "+1-555-123-0003",
      "status": "Queued"
    }
  ],
  "failed": []
}

Campaign Scheduling Example

Schedule a survey campaign to 500 customers:
// Load customer list from database or CSV
const customers = await loadCustomersFromDatabase({
  segment: "recent_purchasers",
  limit: 500
});

// Convert to call objects
const calls = customers.map(customer => ({
  endpoint: customer.phoneNumber,
  priority: customer.isPremium ? 7 : 5,
  additionalData: {
    customerId: customer.id,
    customerName: customer.name,
    purchaseDate: customer.lastPurchaseDate,
    productCategory: customer.lastProductCategory,
    campaignId: "satisfaction_survey_oct_2025"
  }
}));

// Schedule all calls in batches of 500
const batchSize = 500;
for (let i = 0; i < calls.length; i += batchSize) {
  const batch = calls.slice(i, i + batchSize);

  const response = await fetch('https://blackbox.dasha.ai/api/v1/calls/bulk', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      agentId: "550e8400-e29b-41d4-a716-446655440000",
      calls: batch
    })
  });

  const result = await response.json();
  console.log(`Batch ${i / batchSize + 1}: ${result.scheduled.length} scheduled, ${result.failed.length} failed`);
}
Rate Limits: Maximum 1000 calls per bulk request. For larger campaigns, batch requests as shown above with appropriate delays between batches.

Handling Bulk Scheduling Errors

Check for failed calls in the response:
const result = await response.json();

if (result.failed.length > 0) {
  console.error('Some calls failed to schedule:');

  result.failed.forEach(failure => {
    console.error(`Endpoint: ${failure.endpoint}`);
    console.error(`Reason: ${failure.error}`);
    console.error(`Details: ${failure.details}`);
  });

  // Retry failed calls or log for manual review
  const retryList = result.failed.map(f => f.endpoint);
  await handleFailedNumbers(retryList);
}
Common Failure Reasons:
  • Invalid phone number format
  • Duplicate call to same endpoint within short timeframe
  • Agent disabled or deleted
  • Concurrency limit reached
  • Insufficient balance (if applicable)

Call Parameters Reference

Required Parameters

agentId (string)
  • UUID of the agent making the call
  • Must be enabled and configured
  • Example: "550e8400-e29b-41d4-a716-446655440000"
endpoint (string)
  • Recipient phone number in E.164 format
  • Or SIP URI for VoIP calls
  • Examples: "+1-555-123-4567", "sip:user@domain.com"

Optional Parameters

priority (integer, 0-10, default: 5)
  • Queue priority for this call
  • Higher number = processed sooner
  • Use for urgent calls or VIP customers
  • Example: 8 for high-priority appointment reminder
deadline (string, ISO 8601)
  • Maximum time to start the call
  • Call canceled if not started by this time
  • Include timezone offset for accuracy
  • Example: "2025-10-20T17:00:00-05:00"
additionalData (object)
  • Custom JSON metadata for this call
  • Accessible in webhooks and transcripts
  • No schema restrictions
  • Example: { "customerId": "123", "campaignId": "fall_2025" }
timezone (string, IANA timezone identifier)
  • Timezone for deadline interpretation
  • Uses agent timezone if not specified
  • Example: "America/New_York"

Call Queue Management

Monitor and manage scheduled calls in the queue.

Viewing Scheduled Calls

Dashboard:
  1. Navigate to Calls page
  2. Select Scheduled Calls tab
  3. Filter by status: “Queued”, “Pending”, “Created”
  4. Search by call ID or endpoint
Scheduled calls queue with filters Filter and search scheduled calls API:
const response = await fetch('https://blackbox.dasha.ai/api/v1/calls/queue/list?agentId=550e8400-e29b-41d4-a716-446655440000&skip=0&take=50', {
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

const { calls, total } = await response.json();
console.log(`${calls.length} scheduled calls, ${total} total in queue`);

DWRR Scheduling Algorithm

Dasha BlackBox uses Dynamic Weighted Round Robin (DWRR) scheduling: How It Works:
  1. Priority-based weighting: Higher priority = more queue weight
  2. Deadline awareness: Calls approaching deadline get priority boost
  3. Agent availability: Only schedules when agent has capacity
  4. Fair distribution: Prevents starvation of lower-priority calls
Priority Behavior:
  • Priority 10: Immediate processing (emergency)
  • Priority 7-9: High priority (appointments, VIP)
  • Priority 5-6: Normal priority (standard outreach)
  • Priority 0-4: Low priority (bulk campaigns, surveys)
Deadline Impact:
  • Calls within 1 hour of deadline: +3 priority boost
  • Calls within 15 minutes of deadline: +5 priority boost
  • Missed deadline: Call automatically canceled
Queue Processing: Calls are processed continuously based on agent availability, concurrency limits, and priority weighting. Most calls start within 1-5 minutes of being queued.

Caller ID Configuration

Configure the phone number that appears as caller ID for outbound calls.

Setting Outbound Number

Dashboard Configuration:
  1. Go to agent Edit page
  2. Navigate to Phone tab
  3. Add phone number via Twilio Integration
  4. Verify ownership through Twilio
  5. Set as Outbound Caller ID
API Configuration:
await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
  method: 'PUT',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    // ... other agent config
    outboundSipConfig: {
      server: "sip.provider.com:5060",
      authUser: "your_username",
      password: "your_password",
      fromUser: "+1-555-100-0000",  // This is your outbound caller ID
      domain: "sip.provider.com",
      transport: "udp"
    }
  })
});

Caller ID Best Practices

Do:
  • ✅ Use local numbers (same area code as recipients)
  • ✅ Verify number ownership with carrier
  • ✅ Use consistent caller ID for brand recognition
  • ✅ Include company name in CNAM (Caller Name) if possible
  • ✅ Add number to Google Business listings
Don’t:
  • ❌ Use spoofed or fake caller IDs
  • ❌ Change caller ID frequently (confuses recipients)
  • ❌ Use blocked/private caller ID
  • ❌ Use invalid or unverified numbers
Spoofing Regulations: Using fake or misleading caller IDs is illegal in most jurisdictions. Always use verified numbers you own or lease.

Call Timing and Scheduling

Control when outbound calls are made to maximize answer rates and compliance.

Immediate vs Scheduled Calls

Immediate Calls (no deadline specified)
  • Queued immediately
  • Processed as soon as agent available
  • Subject to agent business hours (if configured)
  • Typical start time: 1-5 minutes
Scheduled Calls (with deadline)
  • Processed before deadline
  • Respects agent availability schedule
  • Automatically canceled if deadline passed
  • Typical start time: Within 1 hour of deadline

Timezone Considerations

Agent Timezone (from agent schedule)
  • Used for interpreting business hours
  • Default for call scheduling
  • Example: Agent in America/New_York won’t call during local night hours
Call Timezone (from call timezone parameter)
  • Overrides agent timezone for this call
  • Useful for multi-timezone campaigns
  • Example: Call West Coast customer at 9 AM Pacific, even if agent is in Eastern
Example: Multi-Timezone Campaign
const westCoastCalls = westCoastCustomers.map(customer => ({
  endpoint: customer.phone,
  deadline: "2025-10-20T09:00:00-08:00", // 9 AM Pacific
  timezone: "America/Los_Angeles",
  additionalData: { customerId: customer.id }
}));

const eastCoastCalls = eastCoastCustomers.map(customer => ({
  endpoint: customer.phone,
  deadline: "2025-10-20T09:00:00-05:00", // 9 AM Eastern
  timezone: "America/New_York",
  additionalData: { customerId: customer.id }
}));

Best Calling Times

Optimal Call Windows (based on industry data): Business Calls (B2B):
  • Best: 10 AM - 11 AM, 2 PM - 4 PM (recipient’s local time)
  • Good: 9 AM - 10 AM, 4 PM - 5 PM
  • Avoid: Before 9 AM, after 5 PM, lunch (12 PM - 1 PM)
Consumer Calls (B2C):
  • Best: 5 PM - 8 PM weekdays (after work)
  • Good: 10 AM - 12 PM weekends
  • Avoid: Early mornings (before 9 AM), late nights (after 9 PM)
Appointment Reminders:
  • 24 hours before appointment
  • 2 hours before appointment (if 24hr reminder missed)
Compliance: Always respect local regulations regarding calling hours. In the US, TCPA restricts calls before 8 AM and after 9 PM recipient local time.

Priority Levels Explained

Use priority to control queue processing order.

Priority Scale (0-10)

PriorityUse CaseProcessing Time
10Critical/EmergencyImmediate (highest)
8-9High (VIP, Appointments)under 5 minutes
6-7Above Normal (Follow-ups)under 15 minutes
5Normal (Default)under 30 minutes
3-4Low (Surveys, Bulk)under 1 hour
0-2Lowest (Mass campaigns)under 2 hours

Priority Examples

Emergency Notification (Priority: 10)
{
  endpoint: "+1-555-123-4567",
  priority: 10,
  additionalData: { alertType: "critical_outage", serviceId: "web_hosting" }
}
Appointment Reminder (Priority: 8)
{
  endpoint: "+1-555-123-4567",
  priority: 8,
  deadline: "2025-10-21T08:00:00-05:00", // Before appointment
  additionalData: { appointmentTime: "2025-10-21T10:00:00", doctorName: "Dr. Smith" }
}
Lead Qualification (Priority: 5)
{
  endpoint: "+1-555-123-4567",
  priority: 5,
  additionalData: { leadSource: "website_form", productInterest: "enterprise" }
}
Survey Call (Priority: 3)
{
  endpoint: "+1-555-123-4567",
  priority: 3,
  additionalData: { surveyType: "satisfaction", lastPurchase: "2025-09-15" }
}

Canceling Scheduled Calls

Remove calls from the queue before they’re processed.

Cancel via Dashboard

  1. Navigate to Calls page
  2. Select Scheduled Calls tab
  3. Find the call to cancel
  4. Click Remove button (trash icon)
  5. Confirm cancellation in dialog
Cancel call confirmation dialog Confirm call cancellation

Cancel via API

Single Call Cancellation:
const callId = "660e8400-e29b-41d4-a716-446655440001";

const response = await fetch(`https://blackbox.dasha.ai/api/v1/calls/${callId}`, {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

if (response.ok) {
  console.log('Call canceled successfully');
} else {
  const error = await response.json();
  console.error('Failed to cancel call:', error.message);
}
Bulk Cancellation:
// Cancel all calls for a campaign
const response = await fetch('https://blackbox.dasha.ai/api/v1/calls/queue/list?agentId=550e8400-e29b-41d4-a716-446655440000&skip=0&take=1000', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});

const { calls } = await response.json();

// Filter calls by campaign ID in additionalData
const campaignCalls = calls.filter(call =>
  call.additionalData?.campaignId === "fall_2025_survey"
);

// Cancel each call
const cancellations = campaignCalls.map(call =>
  fetch(`https://blackbox.dasha.ai/api/v1/calls/${call.callId}`, {
    method: 'DELETE',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  })
);

const results = await Promise.all(cancellations);
console.log(`Canceled ${results.filter(r => r.ok).length} calls`);
Cancellation Limitations: You can only cancel calls in “Queued”, “Pending”, or “Created” status. Calls already “InProgress” cannot be canceled via API.

Monitoring Outbound Calls

Track call status and results in real-time.

Call Status Lifecycle

  1. Created: Call record created, not yet queued
  2. Queued: In scheduler queue, awaiting processing
  3. Pending: Being prepared for dialing
  4. InProgress: Currently calling/connected
  5. Completed: Call finished successfully
  6. Failed: Call failed (busy, no answer, error)
  7. Canceled: Removed from queue before starting

Dashboard Monitoring

Real-Time View:
  • Navigate to Dashboard for org-wide metrics
  • Navigate to Calls page for detailed list
  • Use Scheduled Calls tab for queue monitoring
  • Use Past Calls tab for completed call results
Available Metrics:
  • Total calls scheduled
  • Calls currently in progress
  • Completed calls count
  • Failed calls count
  • Average call duration
  • Answer rate percentage

API Monitoring

Get Call Status:
const callId = "660e8400-e29b-41d4-a716-446655440001";

const response = await fetch(`https://blackbox.dasha.ai/api/v1/calls/${callId}`, {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});

const call = await response.json();
console.log('Status:', call.status);
console.log('Priority:', call.priority);
console.log('Next schedule time:', call.nextScheduleTime);
console.log('Deadline:', call.callDeadline);
Call Statistics by Status:
const fromDate = "2025-10-20T00:00:00Z";
const toDate = "2025-10-20T23:59:59Z";

const response = await fetch(`https://blackbox.dasha.ai/api/v1/calls/statistics/statuses?agentId=550e8400-e29b-41d4-a716-446655440000&fromDate=${fromDate}&toDate=${toDate}`, {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});

const stats = await response.json();
console.log('Queued:', stats.queued);
console.log('Completed:', stats.completed);
console.log('Failed:', stats.failed);
console.log('InProgress:', stats.inProgress);

Webhook Notifications

Get real-time updates on call events via webhooks: Configure Webhooks in Agent:
{
  config: {
    webhooks: {
      completedWebHook: {
        url: "https://your-server.com/webhooks/call-completed",
        headers: { "X-API-Key": "your_secret" }
      },
      failedWebHook: {
        url: "https://your-server.com/webhooks/call-failed",
        headers: { "X-API-Key": "your_secret" }
      }
    }
  }
}
Webhook Payload (Completed):
{
  "callId": "660e8400-e29b-41d4-a716-446655440001",
  "agentId": "550e8400-e29b-41d4-a716-446655440000",
  "endpoint": "+1-555-123-4567",
  "status": "Completed",
  "duration": 180,
  "transcript": [...],
  "additionalData": { "customerId": "cust_123" }
}
See Webhooks Overview for complete webhook documentation.

Best Practices

Compliance and Regulations

Do-Not-Call (DNC) Lists
  • Maintain internal DNC list
  • Honor national DNC registries (US: donotcall.gov)
  • Remove numbers upon request immediately
  • Check numbers against DNC before scheduling
Consent Requirements
  • Obtain express written consent for marketing calls
  • Keep consent records with timestamps
  • Provide opt-out mechanism in every call
  • Honor opt-outs within 30 days
Calling Hours
  • US (TCPA): 8 AM - 9 PM recipient local time
  • EU (GDPR): Business hours only, no weekends
  • Check local regulations for your jurisdiction
Call Recording Disclosure
  • Disclose recording at start of call
  • Obtain consent where required (two-party consent states)
  • Secure storage of recordings
  • Honor deletion requests
Legal Compliance: Violating telemarketing regulations can result in fines up to $43,792 per call (US TCPA). Always consult legal counsel for compliance requirements in your jurisdiction.

Optimizing Answer Rates

Call Timing:
  • Call during optimal hours for your audience
  • Avoid meal times and very early/late hours
  • Test different times and track answer rates
  • Use local caller ID when possible
Caller ID Optimization:
  • Use local area code matching recipient
  • Register business name with CNAM providers
  • Maintain good reputation (low spam reports)
  • Avoid frequent number changes
Retry Logic:
  • Don’t retry immediately after busy/no-answer
  • Wait at least 4 hours between retry attempts
  • Maximum 3 attempts per number
  • Track retry history in additionalData
Personalization:
  • Use recipient’s name in greeting (via additionalData)
  • Reference recent interactions or purchases
  • Tailor message to recipient’s interests
  • Provide immediate value in introduction

Campaign Management

Segmentation:
// Segment by customer value
const vipCalls = customers
  .filter(c => c.lifetimeValue > 10000)
  .map(c => ({ endpoint: c.phone, priority: 8, additionalData: { segment: "vip" } }));

const standardCalls = customers
  .filter(c => c.lifetimeValue <= 10000)
  .map(c => ({ endpoint: c.phone, priority: 5, additionalData: { segment: "standard" } }));
Throttling:
// Prevent overwhelming recipients or systems
const callsPerHour = 100;
const batchSize = callsPerHour / 4; // 4 batches per hour

for (let i = 0; i < calls.length; i += batchSize) {
  const batch = calls.slice(i, i + batchSize);
  await scheduleBulkCalls(batch);

  // Wait 15 minutes before next batch
  if (i + batchSize < calls.length) {
    await sleep(15 * 60 * 1000);
  }
}
A/B Testing:
// Test different agents or prompts
const agentA = "550e8400-e29b-41d4-a716-446655440000";
const agentB = "550e8400-e29b-41d4-a716-446655440001";

const calls = customers.map((c, i) => ({
  agentId: i % 2 === 0 ? agentA : agentB, // Alternate between agents
  endpoint: c.phone,
  additionalData: {
    testGroup: i % 2 === 0 ? "A" : "B",
    customerId: c.id
  }
}));

Error Handling and Retry Logic

Handling Failed Calls:
// Monitor failed calls via webhook
app.post('/webhooks/call-failed', async (req, res) => {
  const { callId, endpoint, failureReason, additionalData } = req.body;

  // Categorize failure
  if (failureReason === 'busy') {
    // Retry later (recipient was busy)
    await scheduleRetry(endpoint, additionalData, delay: 4 * 60 * 60);
  } else if (failureReason === 'no-answer') {
    // Retry at different time
    await scheduleRetry(endpoint, additionalData, delay: 24 * 60 * 60);
  } else if (failureReason === 'invalid-number') {
    // Don't retry, update database
    await markNumberInvalid(endpoint);
  } else {
    // Log for manual review
    await logFailureForReview(callId, failureReason);
  }

  res.sendStatus(200);
});
Retry Strategy:
  • Busy: Retry after 4 hours
  • No Answer: Retry after 24 hours, different time
  • Invalid Number: Don’t retry, mark as invalid
  • Network Error: Retry after 1 hour (transient)
  • Max Retries: 3 attempts maximum

Troubleshooting

Common Outbound Call Issues

Calls Not Being Scheduled Symptoms:
  • API returns error on schedule attempt
  • Calls don’t appear in queue
Possible Causes:
  • Agent is disabled (isEnabled: false)
  • Invalid phone number format
  • Missing required parameters
  • Exceeded rate limits
  • Insufficient balance (if applicable)
Solution:
// Check agent status
const agent = await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());

console.log('Agent enabled:', agent.isEnabled);
console.log('Agent status:', agent.status);

// Validate phone number
const phoneRegex = /^\+[1-9]\d{1,14}$/;
console.log('Valid E.164:', phoneRegex.test(endpoint));
Calls Stuck in Queue Symptoms:
  • Calls remain “Queued” for extended time
  • Never progress to “InProgress”
Possible Causes:
  • Agent outside business hours (schedule configured)
  • Concurrency limit reached
  • Deadline passed (calls auto-canceled)
  • Agent has connectivity issues
Solution:
// Check agent schedule
console.log('Agent timezone:', agent.schedule?.timezone);
console.log('Current day schedule:', agent.schedule?.[getCurrentDay()]);

// Check concurrency
const concurrency = await fetch('https://blackbox.dasha.ai/api/v1/misc/concurrency', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());

console.log('Active calls:', concurrency.active);
console.log('Max concurrent:', concurrency.concurrency);
console.log('At capacity:', concurrency.active >= concurrency.concurrency);
Low Answer Rates Symptoms:
  • Many calls marked “Failed: no-answer”
  • Calls connect but recipient doesn’t stay on line
Possible Causes:
  • Calling at wrong times
  • Unrecognized caller ID (spam)
  • Poor call quality
  • Weak opening message
Solution:
  • Call during optimal hours (see Best Calling Times)
  • Use local caller ID
  • Register with CNAM providers
  • Test agent voice quality via dashboard
  • Refine opening message for clarity and value
Calls Failing Immediately Symptoms:
  • Status changes from “Queued” to “Failed” instantly
  • No call attempt made
Possible Causes:
  • Invalid destination number
  • Blocked number (carrier or recipient)
  • Telephony provider issue
  • Missing caller ID configuration
Solution:
// Validate number with carrier lookup API (optional)
const validation = await validatePhoneNumber(endpoint);
console.log('Number valid:', validation.isValid);
console.log('Number type:', validation.type); // mobile, landline, voip
console.log('Carrier:', validation.carrier);

// Check caller ID config (fromUser is your outbound caller ID)
console.log('Outbound caller ID:', agent.outboundSipConfig?.fromUser);

Getting Support

If issues persist after troubleshooting:
  1. Gather Information:
    • Call ID(s) experiencing issues
    • Agent ID
    • Timestamps of failures
    • Error messages or API responses
  2. Check Status Page:
  3. Contact Support:
See Getting Support for more details.

Next Steps

Now that you understand outbound calling:
  1. Configure caller ID in Phone Numbers
  2. Monitor call results with Call Management
  3. Set up webhooks for Call Events
  4. Analyze call data with Post-Call Analysis
  5. Review compliance with Production Checklist

API Cross-Refs