Schedule Call
Schedule a single outbound call with comprehensive metadata and Make.com compatibility
Schedule Call
Schedule a single outbound call to a contact. This endpoint supports rich metadata, timezone-aware scheduling, and is fully compatible with Make.com automation.
Endpoint
POST /api/v1/calls/scheduleAuthentication
Supports multiple authentication methods:
# API Key
x-api-key: YOUR_API_KEY
# Bearer Token
Authorization: Bearer YOUR_API_KEY
# Internal API Key (for service-to-service)
x-api-key: INTERNAL_API_KEYRequest Body
Required Fields
| Field | Type | Description |
|---|---|---|
agentId | string (UUID) | ID of the voice agent to use |
contactPhone | string | Contact phone number in E.164 format (e.g., +14155552671) |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
contactName | string | null | Contact's full name |
contactEmail | string | null | Contact's email address |
callerId | string | Agent's first phone | Specific phone number to use as caller ID |
scheduledAt | string (ISO 8601) | Immediate | When to make the call |
priority | integer (0-10) | 0 | Call priority (0=highest, 10=lowest) |
maxRetries | integer | null | Maximum retry attempts (auto-calculated from retry config if not set) |
retrySchedule | array | null | Fixed retry schedule with absolute timestamps |
retryIntervals | array | null | Relative retry intervals (e.g., "2 hours", "1 day") |
callMetadata | object | Rich contact and call context data | |
metadata | object | Additional custom metadata |
Call Metadata Object
The callMetadata object supports comprehensive contact information and call context:
{
// Contact Information
firstName?: string;
lastName?: string;
company?: string;
jobTitle?: string;
timezone?: string; // IANA timezone (e.g., "America/New_York")
preferredLanguage?: string; // ISO 639-1 code (e.g., "en", "es")
// Contact Preferences
preferredCallTime?: string; // e.g., "09:00-17:00"
doNotCallBefore?: string; // ISO 8601 time
doNotCallAfter?: string; // ISO 8601 time
// Context Data
accountId?: string;
accountType?: string; // e.g., "premium", "standard"
customerSince?: string; // ISO 8601 date
lastInteraction?: string; // ISO 8601 datetime
purchaseHistory?: array;
// Call Purpose
callPurpose?: string; // e.g., "follow-up", "support", "sales"
campaignId?: string;
scriptId?: string;
expectedDuration?: number; // in seconds
// Custom Fields
customFields?: object; // Any additional key-value pairs
tags?: string[]; // Array of tags
notes?: string; // Special notes for the agent
}Retry Configuration
You can configure automatic retries using either relative intervals or fixed schedules:
Relative Retry Intervals (Recommended)
Use retryIntervals for flexible, relative timing between retry attempts:
{
retryIntervals: [
{ value: 2, unit: "hours" }, // 1st retry: 2 hours after initial call
{ value: 1, unit: "days" }, // 2nd retry: 1 day after 1st retry
{ value: 3, unit: "days" } // 3rd retry: 3 days after 2nd retry
]
}Supported units: "minutes", "hours", "days"
Fixed Retry Schedule
Use retrySchedule for absolute timestamps when you need specific retry times:
{
retrySchedule: [
"2025-12-02T14:00:00Z", // 1st retry at specific time
"2025-12-03T10:00:00Z", // 2nd retry at specific time
"2025-12-04T16:00:00Z" // 3rd retry at specific time
]
}Retry Behavior
maxRetriesis automatically calculated from the length ofretryIntervalsorretryScheduleif not explicitly set- If no retry configuration is provided, the call will not be retried on failure
- Retries are triggered when a call fails due to no-answer, busy, or other retriable errors
- You can use either
retryIntervalsORretrySchedule, not both
Response
Response Schema
{
"data": {
"id": "string",
"status": "string",
"scheduledAt": "string|null",
"agent": {
"id": "string",
"name": "string"
},
"contact": {
"phone": "string",
"name": "string|null",
"email": "string|null"
}
},
"message": "Call scheduled successfully"
}Examples
Basic Call Schedule
curl -X POST https://v2.heppu.ai/api/v1/calls/schedule \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"contactPhone": "+14155552671",
"contactName": "John Doe",
"scheduledAt": "2025-12-02T14:00:00Z"
}'const response = await fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
contactPhone: '+14155552671',
contactName: 'John Doe',
scheduledAt: '2025-12-02T14:00:00Z'
})
});
const data = await response.json();
console.log('Call scheduled:', data.data);import requests
from datetime import datetime, timedelta
# Schedule for tomorrow at 2 PM UTC
scheduled_time = (datetime.utcnow() + timedelta(days=1)).replace(
hour=14, minute=0, second=0, microsecond=0
)
response = requests.post(
'https://v2.heppu.ai/api/v1/calls/schedule',
headers={'x-api-key': 'YOUR_API_KEY'},
json={
'agentId': '550e8400-e29b-41d4-a716-446655440000',
'contactPhone': '+14155552671',
'contactName': 'John Doe',
'scheduledAt': scheduled_time.isoformat() + 'Z'
}
)
data = response.json()
print(f"Call scheduled: {data['data']}")Immediate Call
curl -X POST https://v2.heppu.ai/api/v1/calls/schedule \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"contactPhone": "+14155552671",
"priority": 0
}'// Immediate call with high priority
const response = await fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
contactPhone: '+14155552671',
priority: 0 // High priority
})
});
const data = await response.json();
console.log('Immediate call initiated:', data.data);# Immediate call (no scheduledAt specified)
response = requests.post(
'https://v2.heppu.ai/api/v1/calls/schedule',
headers={'x-api-key': 'YOUR_API_KEY'},
json={
'agentId': '550e8400-e29b-41d4-a716-446655440000',
'contactPhone': '+14155552671',
'priority': 0 # High priority
}
)Call with Retry Intervals
Schedule a call with automatic retries using relative time intervals:
curl -X POST https://v2.heppu.ai/api/v1/calls/schedule \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"contactPhone": "+14155552671",
"contactName": "John Doe",
"scheduledAt": "2025-12-02T10:00:00Z",
"retryIntervals": [
{ "value": 2, "unit": "hours" },
{ "value": 1, "unit": "days" }
]
}'// Schedule call with automatic retries
const response = await fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
contactPhone: '+14155552671',
contactName: 'John Doe',
scheduledAt: '2025-12-02T10:00:00Z',
retryIntervals: [
{ value: 2, unit: 'hours' }, // Retry after 2 hours
{ value: 1, unit: 'days' } // Then retry after 1 day
]
})
});
const data = await response.json();
console.log('Call scheduled with retries:', data.data);# Schedule call with automatic retries
response = requests.post(
'https://v2.heppu.ai/api/v1/calls/schedule',
headers={'x-api-key': 'YOUR_API_KEY'},
json={
'agentId': '550e8400-e29b-41d4-a716-446655440000',
'contactPhone': '+14155552671',
'contactName': 'John Doe',
'scheduledAt': '2025-12-02T10:00:00Z',
'retryIntervals': [
{'value': 2, 'unit': 'hours'}, # Retry after 2 hours
{'value': 1, 'unit': 'days'} # Then retry after 1 day
]
}
)Call with Fixed Retry Schedule
Schedule a call with retries at specific times (useful for single-timezone campaigns):
curl -X POST https://v2.heppu.ai/api/v1/calls/schedule \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"contactPhone": "+14155552671",
"contactName": "John Doe",
"scheduledAt": "2025-12-02T10:00:00Z",
"retrySchedule": [
"2025-12-02T14:00:00Z",
"2025-12-03T10:00:00Z"
]
}'// Schedule call with fixed retry times
const response = await fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
contactPhone: '+14155552671',
contactName: 'John Doe',
scheduledAt: '2025-12-02T10:00:00Z',
retrySchedule: [
'2025-12-02T14:00:00Z', // 1st retry at 2 PM
'2025-12-03T10:00:00Z' // 2nd retry next day at 10 AM
]
})
});
const data = await response.json();
console.log('Call scheduled with fixed retries:', data.data);# Schedule call with fixed retry times
response = requests.post(
'https://v2.heppu.ai/api/v1/calls/schedule',
headers={'x-api-key': 'YOUR_API_KEY'},
json={
'agentId': '550e8400-e29b-41d4-a716-446655440000',
'contactPhone': '+14155552671',
'contactName': 'John Doe',
'scheduledAt': '2025-12-02T10:00:00Z',
'retrySchedule': [
'2025-12-02T14:00:00Z', # 1st retry at 2 PM
'2025-12-03T10:00:00Z' # 2nd retry next day at 10 AM
]
}
)Call with Rich Metadata
curl -X POST https://v2.heppu.ai/api/v1/calls/schedule \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"contactPhone": "+14155552671",
"contactName": "John Doe",
"contactEmail": "john.doe@example.com",
"scheduledAt": "2025-12-02T14:00:00Z",
"priority": 5,
"callMetadata": {
"firstName": "John",
"lastName": "Doe",
"company": "Acme Corp",
"jobTitle": "CTO",
"timezone": "America/New_York",
"preferredLanguage": "en",
"accountId": "ACC-12345",
"accountType": "premium",
"customerSince": "2024-01-15",
"callPurpose": "product_demo",
"campaignId": "holiday-2025",
"tags": ["vip", "tech-savvy"],
"notes": "Interested in enterprise features"
}
}'const response = await fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
contactPhone: '+14155552671',
contactName: 'John Doe',
contactEmail: 'john.doe@example.com',
scheduledAt: '2025-12-02T14:00:00Z',
priority: 5,
callMetadata: {
firstName: 'John',
lastName: 'Doe',
company: 'Acme Corp',
jobTitle: 'CTO',
timezone: 'America/New_York',
preferredLanguage: 'en',
accountId: 'ACC-12345',
accountType: 'premium',
customerSince: '2024-01-15',
callPurpose: 'product_demo',
campaignId: 'holiday-2025',
tags: ['vip', 'tech-savvy'],
notes: 'Interested in enterprise features',
customFields: {
productInterest: 'Enterprise Suite',
budget: 'high',
decisionMaker: true
}
}
})
});
const data = await response.json();
console.log('Call scheduled with metadata:', data.data);from datetime import datetime, timedelta
response = requests.post(
'https://v2.heppu.ai/api/v1/calls/schedule',
headers={'x-api-key': 'YOUR_API_KEY'},
json={
'agentId': '550e8400-e29b-41d4-a716-446655440000',
'contactPhone': '+14155552671',
'contactName': 'John Doe',
'contactEmail': 'john.doe@example.com',
'scheduledAt': (datetime.utcnow() + timedelta(days=1)).isoformat() + 'Z',
'priority': 5,
'callMetadata': {
'firstName': 'John',
'lastName': 'Doe',
'company': 'Acme Corp',
'jobTitle': 'CTO',
'timezone': 'America/New_York',
'preferredLanguage': 'en',
'accountId': 'ACC-12345',
'accountType': 'premium',
'customerSince': '2024-01-15',
'callPurpose': 'product_demo',
'campaignId': 'holiday-2025',
'tags': ['vip', 'tech-savvy'],
'notes': 'Interested in enterprise features',
'customFields': {
'productInterest': 'Enterprise Suite',
'budget': 'high',
'decisionMaker': True
}
}
}
)
print(f"Call scheduled: {response.json()}")Make.com Integration
The endpoint is fully compatible with Make.com and handles hidden characters automatically:
// Make.com HTTP Module Configuration
{
"url": "https://v2.heppu.ai/api/v1/calls/schedule",
"method": "POST",
"headers": {
"x-api-key": "{{YOUR_API_KEY}}",
"Content-Type": "application/json"
},
"body": {
"agentId": "{{agentId}}",
"contactPhone": "{{phoneNumber}}",
"contactName": "{{firstName}} {{lastName}}",
"contactEmail": "{{email}}",
"scheduledAt": "{{scheduledTime}}",
"callMetadata": {
"firstName": "{{firstName}}",
"lastName": "{{lastName}}",
"company": "{{company}}",
"campaignId": "{{campaignId}}"
}
}
}Response Examples
Success Response (Scheduled)
{
"data": {
"id": "call_abc123",
"status": "initiated",
"scheduledAt": "2025-12-02T14:00:00Z",
"agent": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Customer Support Agent"
},
"contact": {
"phone": "+14155552671",
"name": "John Doe",
"email": "john.doe@example.com"
}
},
"message": "Call scheduled successfully"
}Success Response (Immediate)
{
"data": {
"id": "call_def456",
"status": "initiated",
"scheduledAt": null,
"agent": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Sales Agent"
},
"contact": {
"phone": "+14155552672",
"name": null,
"email": null
}
},
"message": "Call initiated successfully"
}Error Responses
Missing Required Fields
{
"error": {
"message": "Missing required fields: agentId and contactPhone are required",
"code": 400
}
}Invalid Phone Number Format
{
"error": {
"message": "Invalid phone number format. Must be E.164 format (e.g., +1234567890)",
"code": 400
}
}Agent Not Found
{
"error": {
"message": "Agent not found or access denied",
"code": 404
}
}Agent Not Voice Type
{
"error": {
"message": "Agent must be a voice agent to schedule calls",
"code": 400
}
}No Phone Number Assigned
{
"error": {
"message": "Agent does not have a phone number assigned",
"code": 400
}
}Invalid Scheduled Time
{
"error": {
"message": "Invalid scheduledAt format. Use ISO 8601 format",
"code": 400
}
}Validation Rules
Phone Number (E.164 Format)
Must match the pattern: ^\+[1-9]\d{1,14}$
Valid examples:
- US:
+14155552671 - UK:
+442071838750 - Germany:
+493012345678
Invalid examples:
- Missing
+:14155552671 - Has spaces:
+1 415 555 2671 - Has dashes:
+1-415-555-2671 - Too long:
+123456789012345678
Scheduled Time
- Must be ISO 8601 format:
YYYY-MM-DDTHH:mm:ssZ - If time is in the past, will be automatically adjusted to 5 seconds from now
- Optional field - omit for immediate calls
Priority
- Integer from 0 to 10
- 0-3: High priority (processed first)
- 4-6: Normal priority (default: 5)
- 7-10: Low priority (processed last)
Use Cases
CRM Integration
Schedule follow-up calls from your CRM:
async function scheduleFollowUpCall(crmContact, agentId) {
// Calculate best time to call (next business day at 10 AM)
const scheduledTime = getNextBusinessDay();
scheduledTime.setHours(10, 0, 0, 0);
const response = await fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agentId: agentId,
contactPhone: crmContact.phone,
contactName: crmContact.fullName,
contactEmail: crmContact.email,
scheduledAt: scheduledTime.toISOString(),
priority: crmContact.vip ? 0 : 5,
callMetadata: {
firstName: crmContact.firstName,
lastName: crmContact.lastName,
company: crmContact.company,
accountId: crmContact.id,
accountType: crmContact.tier,
customerSince: crmContact.createdAt,
lastInteraction: crmContact.lastContactedAt,
callPurpose: 'follow_up',
notes: crmContact.notes,
customFields: {
dealValue: crmContact.dealValue,
dealStage: crmContact.dealStage,
assignedTo: crmContact.salesRep
}
}
})
});
return response.json();
}
function getNextBusinessDay() {
const date = new Date();
date.setDate(date.getDate() + 1);
// Skip weekends
while (date.getDay() === 0 || date.getDay() === 6) {
date.setDate(date.getDate() + 1);
}
return date;
}Appointment Reminder Calls
Schedule reminder calls for appointments:
def schedule_appointment_reminder(appointment, agent_id):
"""Schedule a reminder call 24 hours before appointment"""
from datetime import datetime, timedelta
# Calculate reminder time (24 hours before appointment)
appointment_time = datetime.fromisoformat(appointment['scheduledAt'])
reminder_time = appointment_time - timedelta(hours=24)
response = requests.post(
'https://v2.heppu.ai/api/v1/calls/schedule',
headers={'x-api-key': 'YOUR_API_KEY'},
json={
'agentId': agent_id,
'contactPhone': appointment['customerPhone'],
'contactName': appointment['customerName'],
'contactEmail': appointment['customerEmail'],
'scheduledAt': reminder_time.isoformat() + 'Z',
'priority': 3, # High priority for reminders
'callMetadata': {
'firstName': appointment['customerFirstName'],
'lastName': appointment['customerLastName'],
'callPurpose': 'appointment_reminder',
'appointmentId': appointment['id'],
'appointmentTime': appointment['scheduledAt'],
'appointmentType': appointment['type'],
'provider': appointment['providerName'],
'location': appointment['location'],
'notes': f"Reminder for {appointment['type']} appointment"
}
}
)
return response.json()Customer Outreach Campaign
Schedule personalized outreach calls:
async function scheduleCampaignCalls(customers, agentId, campaignId) {
const results = [];
for (const customer of customers) {
try {
// Calculate best time based on customer timezone
const scheduledTime = calculateBestCallTime(
customer.timezone,
customer.preferredCallTime
);
const response = await fetch('https://v2.heppu.ai/api/v1/calls/schedule', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agentId: agentId,
contactPhone: customer.phone,
contactName: customer.name,
contactEmail: customer.email,
scheduledAt: scheduledTime.toISOString(),
priority: customer.segment === 'vip' ? 2 : 5,
callMetadata: {
firstName: customer.firstName,
lastName: customer.lastName,
company: customer.company,
timezone: customer.timezone,
preferredLanguage: customer.language,
accountType: customer.segment,
customerSince: customer.signupDate,
purchaseHistory: customer.recentPurchases,
callPurpose: 'product_promotion',
campaignId: campaignId,
tags: customer.tags,
customFields: {
segment: customer.segment,
lifetimeValue: customer.ltv,
engagementScore: customer.engagementScore
}
}
})
});
const data = await response.json();
results.push({
customer: customer.id,
success: true,
callId: data.data.id
});
} catch (error) {
results.push({
customer: customer.id,
success: false,
error: error.message
});
}
}
return results;
}Best Practices
- Use E.164 format - Always format phone numbers correctly
- Provide rich metadata - More context helps agents perform better
- Set appropriate priority - Use priority to manage call queue
- Include timezone - Store contact timezone for better scheduling
- Handle errors - Always check response status and handle errors
- Validate before scheduling - Verify agent exists and has phone number
- Use ISO 8601 dates - Ensure scheduled times are in correct format
Related Endpoints
- Batch Schedule - Schedule multiple calls at once
- Outbound Call - Initiate immediate call via LiveKit
- List Calls - View scheduled calls
- Cancel Call - Cancel a scheduled call