Chanl

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/sdk

Setup

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:

ParameterTypeRequiredDescription
transcriptstringOne of transcript/audioUrl/s3/audioIdPlain text transcript
audioUrlstringOne of transcript/audioUrl/s3/audioIdURL to an audio file
s3objectOne of transcript/audioUrl/s3/audioIdS3 bucket config (bucket, key, region, credentials)
audioIdstringOne of transcript/audioUrl/s3/audioIdReference to previously uploaded audio
customerNamestringNoCustomer name
agentNamestringNoAgent name
directionstringNoinbound, outbound, or web
externalReferenceIdsobjectNoKey-value pairs for linking to your systems
analysisFieldsstring[]NoWhich analyses to run
scorecardIdstringNoAuto-evaluate with this scorecard
customExtractionsarrayNoCustom 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 settings

Read 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: 92

Import 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:

FieldDescriptionUse case
sentimentOverall sentiment and trendCustomer satisfaction tracking
topicsMain discussion topicsCall categorization
keywordsKey terms and phrasesSearch and filtering
qualityCall quality scoreAgent evaluation
speakersSpeaker identificationMulti-party calls
followupsSuggested follow-up actionsTask management
predictionsOutcome predictionsChurn risk, upsell potential
metricsTalk time, response time, etc.Performance analytics
extractionCustom data extractionOrder 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 }
// }

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);

Next steps

On this page