Documentation Index Fetch the complete documentation index at: https://docs.thoughtly.com/llms.txt
Use this file to discover all available pages before exploring further.
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 :
Create a Contact using /contact/create
Trigger a call using /contact/call with the Contact ID
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'
})
});
2. Automation-Based Triggering (Recommended)
Use Automations to trigger calls via webhooks.
Process :
Set up an Automation with a webhook trigger
Send webhook POST requests to trigger calls
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 →
A Note on Naming
In the API, Voice Agents are referred to as interviews (e.g., /interview/{interview_id}). This is an internal naming convention — “interview” and “Voice Agent” mean the same thing. All dashboard and documentation references use “Voice Agent,” but API paths and response payloads use interview.
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 :
Log into Thoughtly Dashboard
Navigate to Settings → Developer
Copy your API token and Team ID
Security Best Practices :
Never expose your API token in client-side code. Always make API calls from your backend server.
If an API token is compromised, revoke it immediately through the dashboard to prevent unauthorized access.
Regularly rotate API tokens as part of your security practices.
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
If your goal is to get structured data after a call ends , use an Automation with the Thoughtly -> On Call Completed trigger. It supports scoping to one agent, multiple agents, or All Agents , and keeps the workflow in Thoughtly (no webhook server required). See Triggers .
If you need server-to-server delivery to your own infrastructure, 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 →
API Reference
For complete API documentation, see:
API Reference Complete endpoint documentation with examples
Webhooks Receive real-time notifications about events
Automations Build workflows without code
Integration Examples Connect with popular platforms
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 === 403 ) {
// Forbidden - check if outbound calling is disabled
logger . error ( 'Outbound calling may be disabled for this agent' , error );
} 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
API Reference Explore complete API endpoint documentation ->