Heppu AI

Timezone-Aware Scheduling

Schedule calls across multiple timezones while respecting local business hours and customer preferences

Overview

Heppu AI's timezone-aware scheduling ensures your calls reach customers at the right time in their local timezone. Schedule calls using local time references, configure business hours, exclude weekends, and set minimum intervals between calls to maximize contact rates while respecting customer preferences.

Local Time Scheduling

Using targetLocalTime

Schedule calls to execute at a specific time in the recipient's local timezone:

{
  "agentId": "agent_abc123",
  "phoneNumber": "+12125551234",
  "targetLocalTime": "09:00",
  "timezone": "America/New_York"
}

This call will execute at 9:00 AM Eastern Time, regardless of your server's timezone.

Multiple Timezone Example

Schedule the same time across different timezones:

JavaScript

const contacts = [
  { phone: '+12125551234', timezone: 'America/New_York' },    // 9 AM EST
  { phone: '+13125551234', timezone: 'America/Chicago' },     // 9 AM CST
  { phone: '+14155551234', timezone: 'America/Los_Angeles' }, // 9 AM PST
  { phone: '+14425551234', timezone: 'Europe/London' },       // 9 AM GMT
  { phone: '+4989551234', timezone: 'Europe/Berlin' }         // 9 AM CET
];

const calls = contacts.map(contact => ({
  agentId: 'agent_abc123',
  phoneNumber: contact.phone,
  targetLocalTime: '09:00',
  timezone: contact.timezone,
  metadata: {
    scheduledFor: '9:00 AM local time'
  }
}));

// Schedule all calls
const response = await fetch('https://v2.heppu.ai/api/v1/calls/batch', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ agentId: 'agent_abc123', calls })
});

Python

contacts = [
    {'phone': '+12125551234', 'timezone': 'America/New_York'},
    {'phone': '+13125551234', 'timezone': 'America/Chicago'},
    {'phone': '+14155551234', 'timezone': 'America/Los_Angeles'},
    {'phone': '+14425551234', 'timezone': 'Europe/London'},
    {'phone': '+4989551234', 'timezone': 'Europe/Berlin'}
]

calls = [
    {
        'agentId': 'agent_abc123',
        'phoneNumber': contact['phone'],
        'targetLocalTime': '09:00',
        'timezone': contact['timezone'],
        'metadata': {
            'scheduledFor': '9:00 AM local time'
        }
    }
    for contact in contacts
]

response = requests.post(
    'https://v2.heppu.ai/api/v1/calls/batch',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
    },
    json={'agentId': 'agent_abc123', 'calls': calls}
)

cURL

curl -X POST https://v2.heppu.ai/api/v1/calls/batch \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agent_abc123",
    "calls": [
      {
        "phoneNumber": "+12125551234",
        "targetLocalTime": "09:00",
        "timezone": "America/New_York"
      },
      {
        "phoneNumber": "+13125551234",
        "targetLocalTime": "09:00",
        "timezone": "America/Chicago"
      },
      {
        "phoneNumber": "+14155551234",
        "targetLocalTime": "09:00",
        "timezone": "America/Los_Angeles"
      }
    ]
  }'

Business Hours Configuration

Basic Business Hours

Restrict calls to specific hours of the day:

{
  "agentId": "agent_abc123",
  "phoneNumber": "+12125551234",
  "timezone": "America/New_York",
  "businessHours": {
    "start": "09:00",
    "end": "17:00"
  }
}

This ensures calls only execute between 9 AM and 5 PM in the recipient's timezone.

Advanced Business Hours with Days

Configure different hours for different days:

{
  "agentId": "agent_abc123",
  "phoneNumber": "+12125551234",
  "timezone": "America/New_York",
  "businessHours": {
    "monday": { "start": "09:00", "end": "17:00" },
    "tuesday": { "start": "09:00", "end": "17:00" },
    "wednesday": { "start": "09:00", "end": "17:00" },
    "thursday": { "start": "09:00", "end": "17:00" },
    "friday": { "start": "09:00", "end": "17:00" },
    "saturday": { "start": "10:00", "end": "14:00" },
    "sunday": null
  }
}

Business Hours Best Practices

IndustryRecommended HoursTimezone Considerations
B2B9 AM - 5 PMUse recipient's business timezone
Retail10 AM - 8 PMConsider store hours
Healthcare8 AM - 6 PMRespect patient privacy times
Financial9 AM - 4 PMAlign with market hours

Weekend Exclusion

Exclude Weekends

Automatically skip Saturday and Sunday:

{
  "agentId": "agent_abc123",
  "phoneNumber": "+12125551234",
  "excludeWeekends": true,
  "businessHours": {
    "start": "09:00",
    "end": "17:00"
  }
}

If a call is scheduled for Saturday, it will automatically move to the next Monday.

Holiday Exclusion

Combine with custom date exclusions:

async function scheduleWithHolidayExclusion(phoneNumber, agentId, timezone) {
  const holidays = [
    '2024-12-25', // Christmas
    '2024-01-01', // New Year's Day
    '2024-07-04'  // Independence Day (US)
  ];

  const scheduledDate = new Date();

  // Check if scheduled date is a holiday
  const dateString = scheduledDate.toISOString().split('T')[0];
  if (holidays.includes(dateString)) {
    // Move to next business day
    scheduledDate.setDate(scheduledDate.getDate() + 1);
  }

  return fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      agentId,
      phoneNumber,
      scheduleAt: scheduledDate.toISOString(),
      timezone,
      excludeWeekends: true
    })
  });
}

Minimum Interval Between Calls

Setting Minimum Intervals

Prevent calling the same number too frequently:

{
  "agentId": "agent_abc123",
  "phoneNumber": "+12125551234",
  "minIntervalHours": 24
}

If this number was called within the last 24 hours, the call will be automatically rescheduled.

Interval Strategies

IntervalUse CaseRecommended For
1 hourUrgent follow-upsSupport callbacks
4 hoursSame-day retriesAppointment reminders
24 hoursDaily check-insLead nurturing
72 hoursGentle persistenceCold outreach
168 hours (1 week)Respectful spacingFollow-up campaigns

Combined with Retry Logic

{
  "agentId": "agent_abc123",
  "phoneNumber": "+12125551234",
  "minIntervalHours": 24,
  "maxRetries": 3,
  "retryOnNoAnswer": true,
  "businessHours": {
    "start": "09:00",
    "end": "17:00"
  }
}

This configuration will:

  1. Try calling during business hours
  2. Retry up to 3 times if no answer
  3. Wait at least 24 hours between attempts

IANA Timezone Database

Common Timezones

Heppu AI uses the IANA timezone database. Here are commonly used timezones:

United States

America/New_York        (EST/EDT)
America/Chicago         (CST/CDT)
America/Denver          (MST/MDT)
America/Los_Angeles     (PST/PDT)
America/Phoenix         (MST, no DST)
America/Anchorage       (AKST/AKDT)
America/Honolulu        (HST, no DST)

Europe

Europe/London           (GMT/BST)
Europe/Paris            (CET/CEST)
Europe/Berlin           (CET/CEST)
Europe/Rome             (CET/CEST)
Europe/Madrid           (CET/CEST)
Europe/Amsterdam        (CET/CEST)

Asia-Pacific

Asia/Tokyo              (JST)
Asia/Shanghai           (CST)
Asia/Singapore          (SGT)
Asia/Dubai              (GST)
Australia/Sydney        (AEDT/AEST)
Pacific/Auckland        (NZDT/NZST)

Finding the Right Timezone

Use this helper function to determine timezone from phone number:

function getTimezoneFromPhone(phoneNumber) {
  const countryCode = phoneNumber.substring(0, 2);

  const timezoneMap = {
    '+1': 'America/New_York',  // Default US
    '+44': 'Europe/London',     // UK
    '+49': 'Europe/Berlin',     // Germany
    '+33': 'Europe/Paris',      // France
    '+81': 'Asia/Tokyo',        // Japan
    '+86': 'Asia/Shanghai',     // China
    '+61': 'Australia/Sydney',  // Australia
  };

  return timezoneMap[countryCode] || 'America/New_York';
}

For more accurate timezone detection, use a phone number validation service or maintain a CRM database with timezone preferences.

Full IANA List

For the complete list of timezones, visit: IANA Timezone Database

Complete Example: Multi-Timezone Campaign

Schedule 100 calls across US timezones, respecting local business hours:

JavaScript

async function scheduleUSCampaign(contacts) {
  // Group contacts by timezone
  const timezoneGroups = {
    'America/New_York': [],
    'America/Chicago': [],
    'America/Denver': [],
    'America/Los_Angeles': []
  };

  contacts.forEach(contact => {
    const timezone = contact.timezone || getTimezoneFromPhone(contact.phone);
    if (timezoneGroups[timezone]) {
      timezoneGroups[timezone].push(contact);
    }
  });

  const allCalls = [];

  // Schedule each timezone group
  for (const [timezone, groupContacts] of Object.entries(timezoneGroups)) {
    const calls = groupContacts.map(contact => ({
      agentId: 'agent_abc123',
      phoneNumber: contact.phone,
      targetLocalTime: '10:00', // 10 AM local time
      timezone: timezone,
      businessHours: {
        start: '09:00',
        end: '18:00'
      },
      excludeWeekends: true,
      minIntervalHours: 48,
      maxRetries: 3,
      retryOnNoAnswer: true,
      retryOnBusy: true,
      metadata: {
        campaignId: 'us_rollout_2024',
        timezone: timezone,
        contactName: contact.name
      }
    }));

    allCalls.push(...calls);
  }

  // Submit in batches of 1000
  const BATCH_SIZE = 1000;
  const results = [];

  for (let i = 0; i < allCalls.length; i += BATCH_SIZE) {
    const batch = allCalls.slice(i, i + BATCH_SIZE);

    const response = await fetch('https://v2.heppu.ai/api/v1/calls/batch', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        agentId: 'agent_abc123',
        calls: batch
      })
    });

    results.push(await response.json());

    // Rate limiting
    await new Promise(resolve => setTimeout(resolve, 2000));
  }

  return results;
}

// Usage
const contacts = [
  { phone: '+12125551001', name: 'John Doe', timezone: 'America/New_York' },
  { phone: '+13125551002', name: 'Jane Smith', timezone: 'America/Chicago' },
  // ... 98 more contacts
];

scheduleUSCampaign(contacts).then(results => {
  console.log('Campaign scheduled:', results);
});

Python

import requests
from typing import List, Dict
from collections import defaultdict
import time

def schedule_us_campaign(contacts: List[Dict]) -> List[Dict]:
    """Schedule calls across US timezones respecting business hours"""

    # Group contacts by timezone
    timezone_groups = defaultdict(list)

    for contact in contacts:
        timezone = contact.get('timezone') or get_timezone_from_phone(contact['phone'])
        timezone_groups[timezone].append(contact)

    all_calls = []

    # Schedule each timezone group
    for timezone, group_contacts in timezone_groups.items():
        calls = [
            {
                'agentId': 'agent_abc123',
                'phoneNumber': contact['phone'],
                'targetLocalTime': '10:00',  # 10 AM local time
                'timezone': timezone,
                'businessHours': {
                    'start': '09:00',
                    'end': '18:00'
                },
                'excludeWeekends': True,
                'minIntervalHours': 48,
                'maxRetries': 3,
                'retryOnNoAnswer': True,
                'retryOnBusy': True,
                'metadata': {
                    'campaignId': 'us_rollout_2024',
                    'timezone': timezone,
                    'contactName': contact.get('name')
                }
            }
            for contact in group_contacts
        ]

        all_calls.extend(calls)

    # Submit in batches of 1000
    BATCH_SIZE = 1000
    results = []

    for i in range(0, len(all_calls), BATCH_SIZE):
        batch = all_calls[i:i + BATCH_SIZE]

        response = requests.post(
            'https://v2.heppu.ai/api/v1/calls/batch',
            headers={
                'Authorization': 'Bearer YOUR_API_KEY',
                'Content-Type': 'application/json'
            },
            json={
                'agentId': 'agent_abc123',
                'calls': batch
            }
        )

        results.append(response.json())

        # Rate limiting
        time.sleep(2)

    return results

def get_timezone_from_phone(phone: str) -> str:
    """Determine timezone from phone number"""
    timezone_map = {
        '+1212': 'America/New_York',
        '+1312': 'America/Chicago',
        '+1415': 'America/Los_Angeles',
        # Add more mappings
    }

    for prefix, timezone in timezone_map.items():
        if phone.startswith(prefix):
            return timezone

    return 'America/New_York'  # Default

# Usage
contacts = [
    {'phone': '+12125551001', 'name': 'John Doe', 'timezone': 'America/New_York'},
    {'phone': '+13125551002', 'name': 'Jane Smith', 'timezone': 'America/Chicago'},
    # ... 98 more contacts
]

results = schedule_us_campaign(contacts)
print('Campaign scheduled:', results)

Common Pitfalls and Solutions

Pitfall 1: Ignoring Daylight Saving Time

Problem: Hardcoding UTC offsets instead of using IANA timezones

Wrong:

{
  "timezone": "UTC-5"  // Breaks during DST
}

Correct:

{
  "timezone": "America/New_York"  // Automatically handles DST
}

Pitfall 2: Not Accounting for Business Hours

Problem: Scheduling calls at inappropriate times

Solution: Always set business hours constraints

{
  "businessHours": {
    "start": "09:00",
    "end": "17:00"
  },
  "excludeWeekends": true
}

Pitfall 3: Over-Calling Contacts

Problem: Multiple calls to the same number in short succession

Solution: Use minimum intervals

{
  "minIntervalHours": 24
}

Pitfall 4: Wrong Timezone Format

Problem: Using abbreviations instead of IANA names

Wrong:

{
  "timezone": "EST"  // Ambiguous
}

Correct:

{
  "timezone": "America/New_York"
}

On this page