Analyze Calls
Import call recordings, transcribe audio, and extract insights with AI
Import your call recordings and Chanl extracts sentiment, topics, quality metrics, and custom data fields automatically. The workflow is: import a call, wait for processing, read the results.
Installation
npm install @chanl/sdkSetup
import { Chanl } from '@chanl/sdk';
const chanl = new Chanl({
apiKey: process.env.CHANL_API_KEY,
});Import a call
Pass a transcript, audio URL, or S3 reference. Chanl handles transcription (if needed), speaker detection, and AI analysis.
const result = await chanl.calls.import({
transcript: `
Agent: Thank you for calling Acme Support. My name is Sarah.
Customer: Hi Sarah, I ordered a laptop last week and it arrived damaged.
Agent: I'm so sorry to hear that. Let me look up your order right away.
Customer: The order number is ORDER-12345.
Agent: I found it. I can send a replacement today with express shipping at no charge.
Customer: That would be great, thank you!
`,
customerName: 'John Doe',
agentName: 'Sarah',
direction: 'inbound',
externalReferenceIds: {
orderId: 'ORDER-12345',
customerId: 'cust_abc123',
},
analysisFields: ['sentiment', 'topics', 'quality', 'keywords'],
});
console.log('Call ID:', result.callId);
console.log('Status:', result.status);Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
transcript | string | One of transcript/audioUrl/s3/audioId | Plain text transcript |
audioUrl | string | One of transcript/audioUrl/s3/audioId | URL to an audio file |
s3 | object | One of transcript/audioUrl/s3/audioId | S3 bucket config (bucket, key, region, credentials) |
audioId | string | One of transcript/audioUrl/s3/audioId | Reference to previously uploaded audio |
customerName | string | No | Customer name |
agentName | string | No | Agent name |
direction | string | No | inbound, outbound, or web |
externalReferenceIds | object | No | Key-value pairs for linking to your systems |
analysisFields | string[] | No | Which analyses to run |
scorecardId | string | No | Auto-evaluate with this scorecard |
customExtractions | array | No | Custom data fields to extract |
Returns: Promise<{ callId: string; status: string }>
Wait for processing
Processing typically takes 5 to 15 seconds. Poll for status or use webhooks in production.
// Option 1: Poll for completion
let call = await chanl.calls.get(result.callId);
while (call.status !== 'ended') {
await new Promise((resolve) => setTimeout(resolve, 2000));
call = await chanl.calls.get(result.callId);
}
// Option 2: Webhooks (recommended for production)
// Configure a webhook URL in your workspace settingsRead the results
Once processing completes, the call object contains all analysis data.
const call = await chanl.calls.get(result.callId);
console.log('Sentiment:', call.summary?.sentiment);
console.log('Sentiment Trend:', call.summary?.sentimentTrend);
console.log('Topics:', call.summary?.topics?.join(', '));
console.log('Keywords:', call.summary?.keywords?.join(', '));
console.log('Quality Score:', call.metrics?.quality);Sentiment: positive
Sentiment Trend: improving
Topics: damaged product, order lookup, replacement, express shipping
Keywords: laptop, damaged, replacement, express shipping
Quality Score: 92Import from different sources
Audio URL
Import from a publicly accessible audio file.
const result = await chanl.calls.import({
audioUrl: 'https://storage.example.com/calls/call-123.mp3',
analysisFields: ['sentiment', 'topics', 'quality'],
});Supported formats: MP3, WAV, M4A, FLAC, OGG, WEBM.
S3 Bucket
Import directly from S3 with credentials.
const result = await chanl.calls.import({
s3: {
bucket: 'my-calls-bucket',
key: 'recordings/2026/01/call-123.mp3',
region: 'us-east-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
analysisFields: ['sentiment', 'topics', 'quality'],
});Pre-uploaded audio
Reference audio you already uploaded to Chanl.
const upload = await chanl.audio.upload({
file: audioBuffer,
filename: 'call-123.mp3',
});
const result = await chanl.calls.import({
audioId: upload.id,
analysisFields: ['sentiment', 'topics', 'quality'],
});Analysis fields
Control what gets analyzed by specifying analysisFields:
| Field | Description | Use case |
|---|---|---|
sentiment | Overall sentiment and trend | Customer satisfaction tracking |
topics | Main discussion topics | Call categorization |
keywords | Key terms and phrases | Search and filtering |
quality | Call quality score | Agent evaluation |
speakers | Speaker identification | Multi-party calls |
followups | Suggested follow-up actions | Task management |
predictions | Outcome predictions | Churn risk, upsell potential |
metrics | Talk time, response time, etc. | Performance analytics |
extraction | Custom data extraction | Order IDs, dates, amounts |
// Full analysis
const result = await chanl.calls.import({
transcript: '...',
analysisFields: [
'sentiment', 'topics', 'keywords', 'quality',
'speakers', 'followups', 'predictions', 'metrics', 'extraction',
],
});
// Lightweight analysis
const result = await chanl.calls.import({
transcript: '...',
analysisFields: ['sentiment', 'topics'],
});Custom data extraction
Extract specific structured data from calls using natural language descriptions.
const result = await chanl.calls.import({
transcript: `
Agent: What's your order number?
Customer: It's ORDER-12345.
Agent: And when did you place the order?
Customer: Last Tuesday, January 15th.
Agent: The total was $299.99, correct?
Customer: Yes, that's right.
`,
customExtractions: [
{ key: 'order_number', description: 'The order number mentioned by the customer', type: 'string' },
{ key: 'order_date', description: 'When the order was placed', type: 'date' },
{ key: 'order_amount', description: 'The total order amount', type: 'number' },
],
analysisFields: ['extraction'],
});
const call = await chanl.calls.get(result.callId);
console.log('Extracted:', call.extractedData);
// {
// order_number: { value: 'ORDER-12345', confidence: 0.98 },
// order_date: { value: '2026-01-15', confidence: 0.85 },
// order_amount: { value: 299.99, confidence: 0.95 }
// }Link calls to your systems
Use external reference IDs to connect calls to records in your CRM, ticketing system, or other tools.
// Import with external references
const result = await chanl.calls.import({
transcript: '...',
externalReferenceIds: {
orderId: 'ORDER-12345',
ticketId: 'TICKET-789',
customerId: 'cust_abc123',
},
});
// Find calls by external reference later
const { calls } = await chanl.calls.list({
externalRefs: { orderId: 'ORDER-12345' },
});Full example
Import a customer service call and return structured insights.
import { Chanl } from '@chanl/sdk';
const chanl = new Chanl({
apiKey: process.env.CHANL_API_KEY,
});
async function analyzeCustomerCall(orderId: string, transcript: string) {
// 1. Import the call
const result = await chanl.calls.import({
transcript,
externalReferenceIds: { orderId },
analysisFields: ['sentiment', 'topics', 'quality', 'followups', 'extraction'],
customExtractions: [
{ key: 'issue_type', description: 'Type of issue reported', type: 'string' },
{ key: 'resolution', description: 'How the issue was resolved', type: 'string' },
{ key: 'customer_satisfied', description: 'Was the customer satisfied?', type: 'boolean' },
],
});
// 2. Wait for processing
let call = await chanl.calls.get(result.callId);
while (call.status !== 'ended') {
await new Promise((r) => setTimeout(r, 2000));
call = await chanl.calls.get(result.callId);
}
// 3. Return structured insights
return {
callId: call.id,
sentiment: call.summary?.sentiment,
topics: call.summary?.topics,
qualityScore: call.metrics?.quality,
issueType: call.extractedData?.issue_type?.value,
resolution: call.extractedData?.resolution?.value,
customerSatisfied: call.extractedData?.customer_satisfied?.value,
suggestedFollowups: call.followups,
};
}
const insights = await analyzeCustomerCall('ORDER-12345', `
Agent: Thank you for calling, how can I help?
Customer: My order arrived damaged. The screen is cracked.
Agent: I'm sorry to hear that. Let me process a replacement right away.
Customer: That would be great.
Agent: Done! You'll receive a new laptop within 2 business days.
Customer: Perfect, thank you so much for the quick help!
`);
console.log(insights);