Calls API Guide
Calls API Guide
The Calls API allows you to access call records, download recordings, and retrieve transcripts and AI-generated insights from calls made through Sure Send CRM.
Overview
Call records contain:
- Basic call metadata (phone number, duration, direction)
- Recording file (downloadable via signed URL)
- Full transcript with speaker labels
- AI-generated intelligence (summary, sentiment, topics)
Retrieving Calls
List All Calls
Endpoint: GET /api/partner/calls
curl "https://api.suresend.ai/api/partner/calls?page=1&limit=25" \
-H "Authorization: Bearer YOUR_API_TOKEN"Query Parameters:
page- Page number (default: 1)limit- Items per page (default: 25, max: 100)
Response:
{
"calls": [
{
"id": "call-uuid",
"personId": "person-uuid",
"userId": "user-uuid",
"phone": "+1-555-1234",
"duration": 180,
"isIncoming": false,
"outcome": "answered",
"hasRecording": true,
"recordingUrl": "https://storage.example.com/signed-url...",
"recordingUrlExpiresIn": 3600,
"hasTranscript": true,
"conversationSummary": "Customer called to inquire about pricing options...",
"conversationTopics": ["pricing", "features", "timeline"],
"sentimentLabel": "positive",
"sentimentScore": 0.75,
"intelligenceProcessed": true,
"intelligenceProcessedAt": "2025-12-01T10:00:00Z",
"createdAt": "2025-12-01T09:30:00Z",
"updatedAt": "2025-12-01T10:00:00Z"
}
],
"meta": {
"total_count": 150,
"current_page": 1,
"total_pages": 6,
"per_page": 25
}
}Get a Specific Call
Endpoint: GET /api/partner/calls/{id}
curl https://api.suresend.ai/api/partner/calls/call-uuid \
-H "Authorization: Bearer YOUR_API_TOKEN"Downloading Call Recordings
When a call has a recording available, the call response includes a signed URL that you can use to download the audio file.
Checking for Recordings
Look for these fields in the call response:
{
"hasRecording": true,
"recordingUrl": "https://storage.example.com/signed-url...",
"recordingUrlExpiresIn": 3600
}hasRecording- Boolean indicating if a recording existsrecordingUrl- Signed URL to download the recording (only present ifhasRecordingis true)recordingUrlExpiresIn- Seconds until the URL expires (always 3600 = 1 hour)
Downloading the Recording
# Get the call to retrieve the recording URL
curl https://api.suresend.ai/api/partner/calls/call-uuid \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Download the recording using the recordingUrl from the response
curl -o recording.mp3 "https://storage.example.com/signed-url..."Important Notes on Recording URLs
- URLs expire after 1 hour - If you need to access the recording later, download and store it
- Get a fresh URL - Simply fetch the call again to get a new signed URL
- Format - Recordings are MP3 audio files
- No authentication needed - The signed URL includes temporary credentials
Example: Download and Store Recording
const axios = require('axios');
const fs = require('fs');
const API_TOKEN = process.env.API_TOKEN;
const API_URL = 'https://api.suresend.ai/api/partner';
async function downloadRecording(callId, outputPath) {
// Get the call to retrieve the recording URL
const callResponse = await axios.get(`${API_URL}/calls/${callId}`, {
headers: { Authorization: `Bearer ${API_TOKEN}` }
});
const call = callResponse.data;
if (!call.hasRecording) {
console.log('No recording available for this call');
return null;
}
console.log(`Recording URL expires in ${call.recordingUrlExpiresIn} seconds`);
// Download the recording
const recordingResponse = await axios.get(call.recordingUrl, {
responseType: 'stream'
});
// Save to file
const writer = fs.createWriteStream(outputPath);
recordingResponse.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', () => {
console.log(`Recording saved to ${outputPath}`);
resolve(outputPath);
});
writer.on('error', reject);
});
}
// Usage
downloadRecording('call-uuid', './recordings/call-123.mp3');Accessing Call Transcripts
For calls with transcription enabled, you can retrieve the full transcript with speaker labels.
Checking for Transcripts
Look for the hasTranscript field in the call response:
{
"hasTranscript": true
}Get Full Transcript
Endpoint: GET /api/partner/calls/{id}/transcript
curl https://api.suresend.ai/api/partner/calls/call-uuid/transcript \
-H "Authorization: Bearer YOUR_API_TOKEN"Response (200 OK):
{
"transcript": "[Agent]: Hello, thank you for calling Sure Send. How can I help you today?\n[Customer]: Hi, I'm interested in learning more about your pricing plans.\n[Agent]: Of course! Let me walk you through our options...",
"hasTranscript": true
}Response (404 Not Found):
{
"errorMessage": "No transcript available"
}Example: Get Call with Transcript
async function getCallWithTranscript(callId) {
// Get basic call info
const callResponse = await axios.get(`${API_URL}/calls/${callId}`, {
headers: { Authorization: `Bearer ${API_TOKEN}` }
});
const call = callResponse.data;
// Get transcript if available
if (call.hasTranscript) {
const transcriptResponse = await axios.get(
`${API_URL}/calls/${callId}/transcript`,
{ headers: { Authorization: `Bearer ${API_TOKEN}` } }
);
call.fullTranscript = transcriptResponse.data.transcript;
}
return call;
}AI-Generated Intelligence
Sure Send CRM automatically analyzes calls to extract insights. These are included directly in the call response.
Intelligence Fields
| Field | Type | Description |
|---|---|---|
conversationSummary | string | AI-generated 2-3 sentence summary of the call |
conversationTopics | array | Key topics discussed (e.g., ["pricing", "features"]) |
sentimentLabel | string | Overall sentiment: "positive", "negative", or "neutral" |
sentimentScore | number | Sentiment score from -1.0 (negative) to 1.0 (positive) |
intelligenceProcessed | boolean | Whether AI analysis has completed |
intelligenceProcessedAt | string | ISO timestamp when analysis completed |
Example Response with Intelligence
{
"id": "call-uuid",
"phone": "+1-555-1234",
"duration": 300,
"hasRecording": true,
"hasTranscript": true,
"conversationSummary": "Customer called to inquire about enterprise pricing. Agent explained the three tiers and customer expressed interest in the professional plan. Follow-up meeting scheduled for next week.",
"conversationTopics": ["pricing", "enterprise features", "demo request"],
"sentimentLabel": "positive",
"sentimentScore": 0.82,
"intelligenceProcessed": true,
"intelligenceProcessedAt": "2025-12-01T10:05:00Z"
}Checking Intelligence Status
async function waitForIntelligence(callId, maxAttempts = 10) {
for (let i = 0; i < maxAttempts; i++) {
const response = await axios.get(`${API_URL}/calls/${callId}`, {
headers: { Authorization: `Bearer ${API_TOKEN}` }
});
const call = response.data;
if (call.intelligenceProcessed) {
console.log('Intelligence ready:', call.conversationSummary);
return call;
}
console.log(`Waiting for intelligence processing... (attempt ${i + 1})`);
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
}
console.log('Intelligence processing timed out');
return null;
}Creating Call Records
Endpoint: POST /api/partner/calls
Create a call record for external calls (e.g., from your own phone system):
curl -X POST https://api.suresend.ai/api/partner/calls \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"personId": "person-uuid",
"phone": "+1-555-1234",
"isIncoming": false,
"outcome": "answered",
"duration": 180,
"note": "Discussed pricing options"
}'Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
personId | string | Yes | UUID of the person |
phone | string | Yes | Phone number |
userId | string | No | User who made/received the call |
isIncoming | boolean | No | True if incoming call |
outcome | string | No | Call outcome (answered, voicemail, no-answer, etc.) |
duration | integer | No | Call duration in seconds |
note | string | No | Notes about the call |
toNumber | string | No | Destination number |
fromNumber | string | No | Origin number |
Updating Call Records
Endpoint: PUT /api/partner/calls/{id}
curl -X PUT https://api.suresend.ai/api/partner/calls/call-uuid \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "Updated notes: Customer requested callback next week",
"outcome": "callback-scheduled"
}'Common Use Cases
1. Export Calls with Recordings
async function exportCallsWithRecordings(outputDir) {
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await axios.get(`${API_URL}/calls`, {
params: { page, limit: 100 },
headers: { Authorization: `Bearer ${API_TOKEN}` }
});
const { calls, meta } = response.data;
for (const call of calls) {
if (call.hasRecording) {
const filename = `${outputDir}/call-${call.id}.mp3`;
await downloadRecording(call.recordingUrl, filename);
}
}
hasMore = page < meta.total_pages;
page++;
}
}2. Analyze Call Sentiment Trends
async function analyzeSentimentTrends() {
const response = await axios.get(`${API_URL}/calls`, {
params: { limit: 100 },
headers: { Authorization: `Bearer ${API_TOKEN}` }
});
const calls = response.data.calls.filter(c => c.intelligenceProcessed);
const stats = {
positive: calls.filter(c => c.sentimentLabel === 'positive').length,
neutral: calls.filter(c => c.sentimentLabel === 'neutral').length,
negative: calls.filter(c => c.sentimentLabel === 'negative').length,
averageScore: calls.reduce((sum, c) => sum + (c.sentimentScore || 0), 0) / calls.length
};
console.log('Sentiment Analysis:', stats);
return stats;
}3. Search Transcripts for Keywords
async function searchTranscripts(keyword) {
const results = [];
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await axios.get(`${API_URL}/calls`, {
params: { page, limit: 100 },
headers: { Authorization: `Bearer ${API_TOKEN}` }
});
const { calls, meta } = response.data;
for (const call of calls) {
if (call.hasTranscript) {
const transcriptResponse = await axios.get(
`${API_URL}/calls/${call.id}/transcript`,
{ headers: { Authorization: `Bearer ${API_TOKEN}` } }
);
if (transcriptResponse.data.transcript.toLowerCase().includes(keyword.toLowerCase())) {
results.push({
callId: call.id,
personId: call.personId,
date: call.createdAt,
summary: call.conversationSummary
});
}
}
}
hasMore = page < meta.total_pages;
page++;
}
return results;
}
// Usage
searchTranscripts('pricing').then(results => {
console.log(`Found ${results.length} calls mentioning pricing`);
});Best Practices
Recording Downloads
- Cache recordings locally - URLs expire after 1 hour
- Check
hasRecordingfirst - Don't assume all calls have recordings - Handle large files - Use streaming for downloads
- Respect storage limits - Implement retention policies
Transcripts
- Check
hasTranscriptfirst - Not all calls have transcripts - Use separate endpoint - Full transcripts are retrieved via
/transcript - Parse speaker labels - Transcripts use
[Agent]:and[Customer]:format
Intelligence Data
- Check
intelligenceProcessed- AI analysis may not be immediate - Handle null values - Fields may be null if processing failed
- Use for insights - Leverage sentiment and topics for analytics
Error Handling
404 Not Found (Call):
{
"errorMessage": "Call not found"
}404 Not Found (Transcript):
{
"errorMessage": "No transcript available"
}401 Unauthorized:
{
"errorMessage": "Invalid or expired token"
}Next Steps
- Learn about People API to manage contacts
- Set up Webhooks for real-time call notifications
- Explore Events API for activity tracking
Need Help?
- API Reference: See full Calls endpoints in sidebar
- Support: [email protected]
Updated 9 days ago
