Skip to main content
After building a Voice Agent using our no-code interface, deploy it using our RESTful API to integrate with your existing systems or build custom solutions.

Two Approaches to Triggering Calls

1. API-Based Triggering (Programmatic)

Trigger calls programmatically from your application code. Process:
  1. Create a Contact using /contact/create
  2. Trigger a call using /contact/call with the Contact ID
  3. Receive webhook notifications about call status
Best For:
  • Custom applications
  • Direct system integration
  • Real-time call triggering
  • Fine-grained control
Example:
// Create a contact
const contact = await fetch('https://api.thoughtly.com/contact/create', {
  method: 'POST',
  headers: {
    'x-api-token': 'your_api_token',
    'team_id': 'your_team_id',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phone_number: '+15551234567',
    name: 'John Doe',
    email: 'john@example.com'
  })
});

// Trigger the call
const call = await fetch('https://api.thoughtly.com/contact/call', {
  method: 'POST',
  headers: {
    'x-api-token': 'your_api_token',
    'team_id': 'your_team_id',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    contact_id: contact.id,
    agent_id: 'your_agent_id'
  })
});
Use Automations to trigger calls via webhooks. Process:
  1. Set up an Automation with a webhook trigger
  2. Send webhook POST requests to trigger calls
  3. Configure workflow logic in the Thoughtly UI
Best For:
  • Team collaboration (non-engineers can modify logic)
  • Complex workflows
  • No-code/low-code solutions
  • Rapid iteration
Benefits:
  • Non-technical teams can modify call logic
  • No code changes required for workflow updates
  • Visual workflow builder for complex scenarios
  • Flexible webhook payload for dynamic data
Learn More: Automations Documentation →

Authentication

All API requests require two headers:
{
  'x-api-token': 'your_api_token',      // Found in dashboard settings
  'team_id': 'your_team_id'              // Your team identifier
}
Find Your Credentials:
  1. Log into Thoughtly Dashboard
  2. Navigate to SettingsDevelopers
  3. Copy your API token and Team ID
Security Best Practice: Never expose your API token in client-side code. Always make API calls from your backend server.

Rate Limits

  • Limit: 100 requests per minute
  • Response: 429 Too Many Requests if exceeded
  • Best Practice: Implement exponential backoff for retries
async function apiCallWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);
    
    if (response.status === 429) {
      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
      continue;
    }
    
    return response;
  }
  throw new Error('Max retries exceeded');
}

Common Integration Patterns

Pattern 1: CRM-Triggered Calls

When a new lead is added to your CRM, trigger a qualification call:
// Webhook from CRM (e.g., Salesforce)
app.post('/webhook/new-lead', async (req, res) => {
  const { phone, name, email, company } = req.body;
  
  // Create contact in Thoughtly
  const contact = await thoughtly.createContact({
    phone_number: phone,
    name: name,
    email: email,
    custom_fields: { company }
  });
  
  // Trigger call with qualification agent
  await thoughtly.triggerCall({
    contact_id: contact.id,
    agent_id: 'qualification_agent_id'
  });
  
  res.status(200).send('Call triggered');
});

Pattern 2: Calendar-Based Reminders

Send appointment reminders 24 hours before scheduled appointments:
// Daily cron job
cron.schedule('0 9 * * *', async () => {
  const tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);
  
  // Get appointments for tomorrow
  const appointments = await getAppointments(tomorrow);
  
  // Trigger reminder call for each
  for (const apt of appointments) {
    await thoughtly.triggerAutomation({
      webhook_url: 'your_automation_webhook',
      payload: {
        contact_phone: apt.phone,
        appointment_time: apt.time,
        service_name: apt.service
      }
    });
  }
});

Pattern 3: Real-Time Customer Support

Connect voice agent to your support queue:
// When customer requests callback
app.post('/request-callback', async (req, res) => {
  const { phone, issue_type, priority } = req.body;
  
  // Create contact with context
  const contact = await thoughtly.createContact({
    phone_number: phone,
    custom_fields: {
      issue_type,
      priority,
      timestamp: new Date().toISOString()
    }
  });
  
  // Trigger immediate callback
  await thoughtly.triggerCall({
    contact_id: contact.id,
    agent_id: 'support_agent_id',
    priority: priority === 'urgent' ? 'high' : 'normal'
  });
  
  res.json({ message: 'Callback initiated' });
});

Webhooks: Receiving Call Data

Configure webhooks to receive real-time updates about calls:
// Webhook endpoint to receive call completion data
app.post('/webhook/call-completed', async (req, res) => {
  const { 
    call_id, 
    agent_id, 
    duration, 
    outcome, 
    transcript,
    variables 
  } = req.body;
  
  // Update your CRM
  await crm.updateLead({
    phone: variables.phone,
    call_outcome: outcome,
    call_duration: duration,
    last_contacted: new Date()
  });
  
  // Send notification to sales team
  if (outcome === 'qualified') {
    await slack.notify('#sales', `New qualified lead: ${variables.name}`);
  }
  
  res.status(200).send('Webhook processed');
});
Learn More: Webhooks Documentation →

SDK & Libraries

JavaScript/TypeScript

npm install @thoughtly/sdk
import { ThoughtlyClient } from '@thoughtly/sdk';

const client = new ThoughtlyClient({
  apiToken: process.env.THOUGHTLY_API_TOKEN,
  teamId: process.env.THOUGHTLY_TEAM_ID
});

// Create and call
const contact = await client.contacts.create({
  phone_number: '+15551234567',
  name: 'Jane Doe'
});

await client.calls.trigger({
  contact_id: contact.id,
  agent_id: 'agent_123'
});

Python

pip install thoughtly-python
from thoughtly import ThoughtlyClient

client = ThoughtlyClient(
    api_token=os.getenv('THOUGHTLY_API_TOKEN'),
    team_id=os.getenv('THOUGHTLY_TEAM_ID')
)

# Create and call
contact = client.contacts.create(
    phone_number='+15551234567',
    name='Jane Doe'
)

client.calls.trigger(
    contact_id=contact.id,
    agent_id='agent_123'
)

API Reference

For complete API documentation, see:

Best Practices

1. Always Validate Phone Numbers

function isValidPhone(phone) {
  // E.164 format: +[country code][number]
  const regex = /^\+[1-9]\d{1,14}$/;
  return regex.test(phone);
}

2. Handle Errors Gracefully

try {
  await thoughtly.triggerCall({ contact_id, agent_id });
} catch (error) {
  if (error.status === 429) {
    // Rate limited - retry later
    await queueForRetry({ contact_id, agent_id });
  } else if (error.status === 400) {
    // Invalid request - log and alert
    logger.error('Invalid API request', error);
  } else {
    // Unexpected error
    throw error;
  }
}

3. Use Environment Variables

// .env file
THOUGHTLY_API_TOKEN=your_token_here
THOUGHTLY_TEAM_ID=your_team_id_here
THOUGHTLY_AGENT_ID=your_agent_id_here

// In your code
const config = {
  apiToken: process.env.THOUGHTLY_API_TOKEN,
  teamId: process.env.THOUGHTLY_TEAM_ID,
  agentId: process.env.THOUGHTLY_AGENT_ID
};

4. Implement Logging

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'thoughtly.log' })
  ]
});

logger.info('Call triggered', { 
  contact_id, 
  agent_id, 
  timestamp: new Date() 
});

Support & Resources