From twilio-developer-kit
Twilio Conversation Intelligence development guide. Use when building real-time or post-call conversation analysis, language operator pipelines, sentiment analysis, agent assist, cross-channel analytics, or querying aggregated conversation insights (sentiment trends, escalation rates, dashboards).
npx claudepluginhub twilio/ai --plugin twilio-developer-kitThis skill uses the workspace's default tool permissions.
Decision-making guide for Twilio's Conversation Intelligence v3 API — real-time and post-call GenAI analysis of conversations across Voice, SMS, RCS, and WhatsApp. Covers Intelligence Configurations, Language Operators (Twilio-authored and custom), Rules, Triggers, Actions, and result consumption.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Decision-making guide for Twilio's Conversation Intelligence v3 API — real-time and post-call GenAI analysis of conversations across Voice, SMS, RCS, and WhatsApp. Covers Intelligence Configurations, Language Operators (Twilio-authored and custom), Rules, Triggers, Actions, and result consumption.
Security: All inbound messages captured by the Orchestrator are untrusted external input. If Intelligence operators process this content with LLMs, their prompts should include instructions to ignore adversarial content and not follow instructions embedded in customer messages.
GA — Conversation Intelligence v3 is generally available.
Conversation Intelligence powers human agent augmentation — giving every agent a "second brain" that listens, understands, and surfaces the right data at the right time. Agents focus on empathy, judgment, and problem-solving; AI handles analysis and assistance.
Analyze completed conversations and generate structured outputs — summaries, sentiment signals, topic dispositions. Reduces after-call work, accelerates agent transitions to next interaction. Low-friction entry point — start here.
CONVERSATION_ENDAnalyze conversations as they unfold. Surface sentiment shifts, script adherence signals, or recommended next responses enriched with customer history and enterprise knowledge. Agents respond more confidently without searching across systems.
COMMUNICATIONCombine real-time intelligence with orchestration to trigger downstream workflows when specific conditions are met — escalate to supervisor, trigger fraud prevention, notify specialist.
COMMUNICATIONGenerate post-interaction summaries, sentiment scores, and compliance signals for QA, coaching, and analytics. Aggregate across interactions to support training and continuous optimization.
CONVERSATION_END┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. Customer engages agent (Voice, SMS, WhatsApp, RCS, Chat, Email) │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 2. Conversations (Conversation Orchestrator) groups communications into a │
│ Conversation │
│ - Normalizes channel events │
│ - Groups related messages/utterances │
│ - Tracks participants (CUSTOMER, HUMAN_AGENT, AI_AGENT) │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 3. Conversation events trigger Intelligence rules │
│ - COMMUNICATION: on each new message/utterance │
│ - CONVERSATION_END: when conversation closes │
│ - CONVERSATION_INACTIVE: when conversation goes idle │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 4. Language Operators analyze the conversation │
│ - Twilio-authored: Sentiment, Summary, NBR, Script Adherence │
│ - Custom: domain-specific analysis with your prompts │
│ - Context: enriched with Customer Memory + Enterprise Knowledge │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 5. Results delivered via webhook + REST API │
│ - Real-time: Agent desktop, workflow triggers │
│ - Post-call: CRM notes, QA systems, analytics │
│ - Aggregated: Conversational Insights for cross-conversation analysis │
└─────────────────────────────────────────────────────────────────────────────┘
Key insight: Real-time and post-conversation intelligence use the same underlying model. Start with low-friction post-call summaries, then progressively introduce real-time assist using the same components.
EXTRACTION is a read-only format returned by some Twilio-authored operators; it cannot be set on custom operators you createcount parameter (run every N communications, min 1, max 20){{parameters.name}} syntax), including knowledge base references (KNOWLEDGE_BASE_AND_SOURCE_IDS type — value format: knowledge_base_id:knowledge_source_id)context.memory.enabled: true) and Enterprise Knowledge (context.knowledge.bases: [...]) at the rule or operator leveltrainingExamples (input/output pairs) to custom operators to improve accuracyoperators[].version; omit to use latestintelligenceConfigurationId, conversationId, or operatorIdstatus, channels, createdAtBefore/createdAtAfter, channelId, intelligenceConfigurationIds, operatorIdsContent-Type: application/json. Form-encoded bodies return HTTP 415 with error 20422.prompt: null when retrieved via GET. The prompt is hidden and not configurable.size must be between 0 and 2 for actions.size must be between 0 and 5.outputSchema: minLength/maxLength (strings), patternProperties (objects), uniqueItems (arrays). Use basic types only.memoryStoreId points to a deleted or invalid store, capture still works but identity resolution and extraction silently fail with no error. Implement periodic health checks to verify Memory Store linkage is functioning.| Need | Use | Why |
|---|---|---|
| Real-time agent assist during live calls/chats | v3 + COMMUNICATION trigger + Next Best Response operator | Real-time webhook delivery per utterance |
| Post-call QA scoring | v3 + CONVERSATION_END trigger + Script Adherence operator | Runs once at conversation close, returns detailed score |
| Conversation sentiment tracking | v3 + Sentiment operator (Twilio-authored) | Conversation-level classification: positive/negative/neutral/mixed |
| Post-call recording transcription + analysis | v2 Voice Intelligence (existing) | v3 does not ingest recordings directly — v2 pipeline handles recording→transcript→operators |
| Custom domain-specific analysis | v3 + Custom operator with JSON output | Define prompt, parameters, structured output schema |
| Cross-channel conversation history | Conversations v2 (Conversation Orchestrator) alone | v3 adds analysis on top; Conversation Orchestrator handles capture and history |
| Simple keyword extraction | v3 + Custom operator (EXTRACTION format) | Structured extraction with custom prompt |
| Dimension | v2 (Voice Intelligence) | v3 (Conversation Intelligence) |
|---|---|---|
| Input source | Recording SIDs (audio) | Conversation Orchestrator conversations (text/transcriptions) |
| Channels | Voice only | SMS, Voice, RCS, WhatsApp, Chat, Email |
| Operator management | Console only (attach to Intelligence Service) | REST API (full CRUD on custom operators) |
| Trigger model | Post-transcription (async) | Real-time (per-message) or post-conversation |
| Result delivery | Webhook (voice_intelligence_transcript_available) | Webhook (per-rule action) + REST query |
| SDK support | client.intelligence.v2.transcripts | Twilio Node.js SDK supported |
| SID prefix | GA (service), GT (transcript), LY (operator) | intelligence_configuration_*, intelligence_operator_* |
| Status | GA | GA |
| Coexistence | Works alongside v3 | Works alongside v2 |
Use v2 when: You need post-call transcription from recordings, or need GA stability. Use v3 when: You need real-time analysis, cross-channel support, or API-managed custom operators.
| Factor | COMMUNICATION trigger | CONVERSATION_END trigger | CONVERSATION_INACTIVE trigger |
|---|---|---|---|
| When it fires | On each new message/utterance | When conversation closes | When conversation goes idle |
| Latency | Near real-time | Seconds after close | After inactive timeout |
| Use cases | Agent assist, escalation detection, live compliance | QA scoring, summaries, CRM updates | Idle conversation follow-up |
| Operator context | Accumulating — sees all messages so far | Complete conversation | Messages up to inactivity point |
| Throttling | count parameter (every N messages) | N/A | N/A |
| Cost implication | Runs per message (more executions) | Runs once per conversation | Runs once per inactivity event |
| Status | Behavior | When |
|---|---|---|
PREVIEW | Normal execution, restricted visibility | Internal/testing versions |
ACTIVE | Normal execution, full availability | Production-ready versions |
DEPRECATED | Executes with Warn event via Watch | Migration window — update to newer version |
RETIRED | Hard failure, Error logged in Watch | Must update Intelligence Configuration manually |
| Format | Use When | Result Shape | Schema Support |
|---|---|---|---|
| TEXT | Free-form analysis, summaries, translations | {"text": "..."} | Auto-generated (not customizable) |
| JSON | Structured extraction with custom fields | User-defined via outputSchema | Full JSON Schema (max 100 props, 10 nesting levels, 1000 enum values max) |
| CLASSIFICATION | Category labeling (sentiment, intent, topic) | {"label": "..."} | Auto-generated |
| EXTRACTION | Returned by some Twilio-authored operators only — cannot be set on custom operators | {"entities": [{"text": "...", "label": "..."}]} | N/A (read-only) |
Ready-to-use operators maintained by Twilio. Use these IDs directly in rules — no custom prompt required.
| Operator | ID | Best Trigger | Use Case |
|---|---|---|---|
| Sentiment | intelligence_operator_01kcrvw16kfa88qvgrfmr7y151 | COMMUNICATION | Real-time sentiment tracking (positive/negative/neutral/mixed) |
| Summary | intelligence_operator_01kcv35pnkeysaf6z6cqtbpegn | CONVERSATION_END | Post-call conversation summary |
| Next Best Response | intelligence_operator_01kea27sy7ffsafmtsfp17nzx4 | COMMUNICATION | Real-time agent assist with suggested responses |
| Script Adherence | intelligence_operator_01kf34tcyefpyb1t4m0nbd8rxg | CONVERSATION_END | QA scoring for script compliance |
Note: Twilio-authored operators have author: "TWILIO" and prompt: null when retrieved via GET. Prompts are hidden and not configurable. Use custom operators if you need control over the prompt.
Code samples use raw fetch() for clarity, but the Twilio Node.js SDK is also supported for v3.
const INTELLIGENCE_V3_BASE = 'https://intelligence.twilio.com/v3';
function getAuthHeaders() {
const credentials = Buffer.from(
`${process.env.TWILIO_ACCOUNT_SID}:${process.env.TWILIO_AUTH_TOKEN}`
).toString('base64');
return {
'Authorization': `Basic ${credentials}`,
'Content-Type': 'application/json',
};
}
// Step 1: Create configuration (empty rules initially)
const configResponse = await fetch(
`${INTELLIGENCE_V3_BASE}/ControlPlane/Configurations`,
{
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify({
displayName: 'Customer Support Analytics',
description: 'Real-time sentiment + post-call summary',
rules: [],
}),
}
);
const config = await configResponse.json();
// config.id = "intelligence_configuration_..."
// Step 2: Add rules via PUT (replaces all rules)
const updateResponse = await fetch(
`${INTELLIGENCE_V3_BASE}/ControlPlane/Configurations/${config.id}`,
{
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify({
displayName: 'Customer Support Analytics',
rules: [
{
operators: [
{ id: 'intelligence_operator_01kcrvw16kfa88qvgrfmr7y151' }, // Sentiment
],
triggers: [{ on: 'COMMUNICATION' }],
actions: [
{ type: 'WEBHOOK', method: 'POST', url: 'https://your-app.com/realtime-results' },
],
},
{
operators: [
{ id: 'intelligence_operator_01kcv35pnkeysaf6z6cqtbpegn' }, // Summary
],
triggers: [{ on: 'CONVERSATION_END' }],
actions: [
{ type: 'WEBHOOK', method: 'POST', url: 'https://your-app.com/post-call-results' },
],
},
],
}),
}
);
const updatedConfig = await updateResponse.json();
// updatedConfig.version = 2 (auto-incremented)
// Intelligence config must be linked to a Conversation Orchestrator conversation config
// See conversation-orchestrator skill for full Conversation Orchestrator setup
const convConfigResponse = await fetch(
'https://conversations.twilio.com/v2/ControlPlane/Configurations',
{
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify({
displayName: 'Support Config',
memoryStoreId: 'mem_store_...', // Required — create via Memory API first
conversationGroupingType: 'GROUP_BY_PARTICIPANT_ADDRESSES',
intelligenceConfigurationIds: [config.id],
channelSettings: {
SMS: {
statusTimeouts: { inactive: 5, closed: 10 },
captureRules: [{ from: '*', to: '+1XXXXXXXXXX', metadata: {} }],
},
},
}),
}
);
// Query all results for an intelligence configuration
const resultsResponse = await fetch(
`${INTELLIGENCE_V3_BASE}/OperatorResults?intelligenceConfigurationId=${config.id}`,
{ headers: getAuthHeaders() }
);
const results = await resultsResponse.json();
for (const operatorResult of results.items) {
console.log(`Operator: ${operatorResult.operator.id}`);
console.log(`Format: ${operatorResult.outputFormat}`);
console.log(`Payload: ${JSON.stringify(operatorResult.result)}`); // e.g. { text: "..." } or { label: "..." }
console.log(`Conversation: ${operatorResult.conversationId}`);
console.log(`Trigger: ${operatorResult.executionDetails.trigger.on}`);
// Context that was actually used at runtime (single source of truth):
console.log(`Memory profile: ${operatorResult.executionDetails.resolvedContext?.memory?.profileId}`);
console.log(`Knowledge sources: ${JSON.stringify(operatorResult.executionDetails.resolvedContext?.knowledge?.sources)}`);
// Cost/perf metadata:
console.log(`Model: ${operatorResult.metadata.system.resolvedModel}, latencyMs: ${operatorResult.metadata.system.latencyMs}`);
}
All list endpoints (/OperatorResults, /Conversations, /Operators, /Configurations) use cursor-based pagination. Default page size is 50; maximum is 1000.
async function* getAllOperatorResults(configId) {
let pageToken = undefined;
do {
const url = new URL(`${INTELLIGENCE_V3_BASE}/OperatorResults`);
url.searchParams.set('intelligenceConfigurationId', configId);
url.searchParams.set('pageSize', '1000');
if (pageToken) url.searchParams.set('pageToken', pageToken);
const response = await fetch(url, { headers: getAuthHeaders() });
const data = await response.json();
yield* data.items;
pageToken = data.meta?.nextToken; // null/undefined when no more pages
} while (pageToken);
}
// Usage:
for await (const result of getAllOperatorResults(config.id)) {
console.log(result.operator.id, result.result);
}
// Context is configured at the rule level (not the operator level)
rules: [
{
operators: [{ id: 'intelligence_operator_01kea27sy7ffsafmtsfp17nzx4' }], // NBR
triggers: [{ on: 'COMMUNICATION' }],
actions: [{ type: 'WEBHOOK', method: 'POST', url: 'https://your-app.com/nbr' }],
context: {
memory: { enabled: true }, // inject customer profile from Memory Store
knowledge: {
bases: ['knowledge_base_id_here'], // inject enterprise KB articles
},
},
},
]
const operatorResponse = await fetch(
`${INTELLIGENCE_V3_BASE}/ControlPlane/Operators`,
{
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify({
displayName: 'Escalation Risk Detector',
prompt: `Analyze this conversation between a customer and agent.
Product context: {{parameters.productName}}
Classify escalation risk as LOW, MEDIUM, or HIGH based on customer frustration signals.`,
outputFormat: 'CLASSIFICATION',
parameters: {
productName: { type: 'STRING', required: true, description: 'Product line being discussed' },
// KNOWLEDGE_BASE_AND_SOURCE_IDS parameters are passed as "kb_id:source_id" at rule time
knowledgeContext: { type: 'KNOWLEDGE_BASE_AND_SOURCE_IDS', required: false },
},
trainingExamples: [
{
input: 'Customer: This is the third time I have called about this issue',
output: 'HIGH',
},
{
input: 'Customer: Thanks, I think that might work',
output: 'LOW',
},
],
}),
}
);
const operator = await operatorResponse.json();
// Pin this operator to a specific version in your rule:
// operators: [{ id: operator.id, version: operator.version }]
Memory Store is required for Conversation Orchestrator: You cannot create a Conversations v2 Configuration without a memoryStoreId. The Memory API returns "memoryStoreId: must not be null" (error 20001). Create the Memory Store first via POST memory.twilio.com/v1/ControlPlane/Stores.
JSON-only API: All v3 endpoints require Content-Type: application/json. Form-encoded bodies return HTTP 415 with error 20422 ("does not support this payload format"). This matches Conversation Orchestrator but differs from most Twilio APIs.
v2 and v3 coexist independently: Creating v3 configurations does not affect v2 Intelligence Services (GA* SIDs). Both are accessible on the same account simultaneously. They share the intelligence.twilio.com host but use different URL paths (/v2/Services vs /v3/ControlPlane/Configurations).
PUT creates an inactive version — operators stop returning results: When you PUT to update an Intelligence Configuration, the new version is created in an inactive state. There is no activation API to make it live. Your operators will silently stop producing results. Workaround: DELETE the configuration and POST to recreate it with the updated rules/operators. This is the only reliable way to update a live configuration.
PUT replaces all rules: Updating a configuration replaces the entire rules array. There is no PATCH or per-rule update. Always include all rules in the PUT body, not just the changed one.
Config version auto-increments: Each PUT bumps the version field. Conversation Orchestrator conversation configs use version for optimistic locking, but Intelligence configs accept PUT without version checks.
Rules get their own IDs: When rules are created via PUT, each gets an auto-generated ID (intelligence_configurationrule_*). These IDs appear in OperatorResult references but are not user-settable.
Trigger count parameter throttles execution: Setting {"on":"COMMUNICATION","parameters":{"count":3}} runs the operator every 3 messages instead of every message.
Dual capture rules cause duplicate processing: If both inbound (from: *, to: +1XXX) and outbound (from: +1XXX, to: *) capture rules match the same SMS, Conversation Orchestrator creates two Communications for one message, and Intelligence produces two OperatorResults. Use unidirectional capture rules unless you specifically want both.
Twilio number is auto-typed HUMAN_AGENT: In Conversation Orchestrator conversations, the Twilio number is automatically assigned type: "HUMAN_AGENT" and the external number gets type: "CUSTOMER" with automatic memory profile resolution (mem_profile_*).
Sentiment accumulates across messages: The Sentiment operator analyzes the full conversation context, not individual messages. After a positive message, sentiment was "positive". After adding a negative message to the same conversation, it became "mixed".
Near real-time delivery for COMMUNICATION trigger: Results are delivered via webhook shortly after each utterance — the full pipeline is Conversation Orchestrator capture → Intelligence trigger → Operator execution → webhook delivery.
Custom operator TEXT output auto-wraps: Custom operators with outputFormat: "TEXT" always return {"text": "..."} regardless of the prompt. The outputSchema is auto-generated and not customizable for TEXT format.
conversationConfigurationId returns "unused": The v3 Conversations endpoint returns "conversationConfigurationId": "unused" instead of the actual Conversation Orchestrator config ID. Use intelligenceConfigurationIds array instead for linking.
No isTwilioAuthored field: Twilio-authored operators are distinguished by author: "TWILIO", custom operators by author: "SELF". There is no boolean isTwilioAuthored field.
Twilio-authored operator prompts are hidden: GET on a Twilio-authored operator returns prompt: null. You cannot inspect or modify the system prompt. Custom operators return the full prompt.
Two separate metadata sections: OperatorResults carry both metadata.system and executionDetails.resolvedContext — they serve different purposes:
metadata.system: cost and performance — resolvedModel (LLM used), latencyMs, inputCharacters/outputCharacters (billing units), inputTruncatedexecutionDetails.resolvedContext: what context was actually injected at runtime — memory (profileId, memoryStoreId) and knowledge (sources: array of {baseId, sourceId}). This is the single source of truth for context resolution.Error codes are consistent: v3 uses Twilio standard error codes: 20001 (bad request/validation), 20404 (not found), 20422 (unsupported format), 70001 (operator validation). All include userError: true and descriptive messages.
Invalid operator ID gives specific error: Using a non-existent operator ID in a rule returns 400 with code 70001 and message identifying the exact invalid operator.
All JSON schema fields are required by default — and Twilio auto-sets this: Twilio automatically sets additionalProperties: false and marks all provided fields as required in outputSchema. Do not add required or additionalProperties yourself — Twilio overwrites any values you provide. The practical consequence: if the LLM cannot populate a field, the operator execution fails. Use union types for nullable fields: "type": ["string", "null"].
Nullable field pattern: To make a field optional/nullable in JSON output, use array type union:
{
"outputSchema": {
"type": "object",
"properties": {
"requiredField": { "type": "string" },
"optionalField": { "type": ["string", "null"] }
}
}
}
This allows the operator to return null for fields where the LLM has insufficient context.
outputSchema and will be rejected. Stick to type, enum, properties, items, anyOf, $defs/$ref.minLength, maxLengthpatternProperties, unevaluatedProperties, propertyNames, minProperties, maxPropertiesunevaluatedItems, contains, minContains, maxContains, uniqueItemsexecutionDetails.context was removed: Older docs and some live responses may show executionDetails.context. This field was removed in a breaking change. Use executionDetails.resolvedContext — it contains memory (profileId, memoryStoreId) and knowledge (array of baseId/sourceId pairs).
Operator result query param is intelligenceConfigurationId (not intelligenceConfiguration): The REST API filter parameter for listing OperatorResults by config is intelligenceConfigurationId. Using the shorter form returns unfiltered results.
KNOWLEDGE_BASE_AND_SOURCE_IDS parameter values must use colon-separated format: When passing a knowledge base parameter to an operator at rule time, the value must be formatted as "knowledge_base_id:knowledge_source_id". Passing just the KB ID or using any other separator returns a validation error. Only plaintext KB sources are supported.
KNOWLEDGE_BASE_AND_SOURCE_IDS parameters do not support default: Unlike STRING, INTEGER, NUMBER, and BOOLEAN parameter types which all allow a default value, KNOWLEDGE_BASE_AND_SOURCE_IDS does not. Defining a default on a KB parameter will be ignored or rejected.
Each rule requires at least 1 operator: The operators array on a rule has minItems: 1. Submitting a rule with an empty operators array on create or update returns a 400 validation error.
List endpoints are paginated — don't assume you got all results: All list endpoints (/OperatorResults, /Conversations, /Operators, /Configurations) return a max of 50 items by default (max 1000 with pageSize). The response meta.nextToken is non-null when more pages exist. Always paginate when querying production data sets.
Where the Intelligence API gives you per-conversation OperatorResults, the Insights API v3 is the query layer for aggregating across thousands of conversations — grouping, filtering, and counting by dimensions like sentiment, channel, language, and operator output.
Base URL: https://insights.twilio.com
Public Beta — Insights v3 is currently in public beta. The query schema is subject to change.
| Goal | Use |
|---|---|
| Get the result for a specific conversation | Intelligence API: GET /v3/OperatorResults?conversationId=... |
| Count conversations by sentiment over time | Insights API: query with OperatorResult.Value dimension |
| Find all conversations where agent went off-script | Insights API: filter on OperatorResult.Value |
| Build a sentiment trend dashboard | Insights API: group by DateCreated + OperatorResults |
| Discover available metrics and dimensions | Insights API: GET /v3/InsightsDomains/Conversations/Metadata |
| Method | Path | Purpose |
|---|---|---|
POST | /v3/InsightsDomains/Conversations/Query | Execute a semantic query, returns first page |
GET | /v3/InsightsDomains/Conversations/Query?pageToken=... | Fetch subsequent pages |
GET | /v3/InsightsDomains/Conversations/Metadata | Discover available cubes, measures, dimensions |
Same Basic Auth as Intelligence API. JSON-only (Content-Type: application/json).
const INSIGHTS_BASE = 'https://insights.twilio.com';
const response = await fetch(
`${INSIGHTS_BASE}/v3/InsightsDomains/Conversations/Query`,
{
method: 'POST',
headers: getAuthHeaders(), // same helper as Intelligence API
body: JSON.stringify({
domain: 'Conversations',
query: {
measures: ['Conversation.Count'],
dimensions: ['OperatorResults', 'Channels', 'DateCreated'],
filters: [{
op: 'AND',
expressions: [
{ op: 'IN', field: 'OperatorResult.Value', values: ['positive', 'negative'] },
],
}],
orderBy: [{ field: 'OperatorResults.CreatedDate', direction: 'DESC' }],
},
}),
}
);
const data = await response.json();
// data.items = [{ Id: 'conv1', OperatorResults: 'positive', Channels: ['voice'], ... }]
// data.meta.nextToken — use for next page (null if last page)
Query fields:
| Field | Description |
|---|---|
query.measures | What to aggregate — e.g. "Conversation.Count", "OperatorResult.Count" |
query.dimensions | What to group by — e.g. "OperatorResults", "Channels", "Languages", "DateCreated" |
query.filters | Nested filter tree with op + expressions. Filter ops: AND, OR, EQ, NE, GT, LT, IN |
query.orderBy | Sort by field + ASC/DESC |
POST returns the first page. Subsequent pages use GET with pageToken. Stop when meta.nextToken is null.
async function* queryAll(queryBody) {
const first = await fetch(`${INSIGHTS_BASE}/v3/InsightsDomains/Conversations/Query`,
{ method: 'POST', headers: getAuthHeaders(), body: JSON.stringify(queryBody) }
).then(r => r.json());
yield* first.items;
let nextToken = first.meta?.nextToken;
while (nextToken) {
const page = await fetch(
`${INSIGHTS_BASE}/v3/InsightsDomains/Conversations/Query?pageToken=${nextToken}`,
{ headers: getAuthHeaders() }
).then(r => r.json());
yield* page.items;
nextToken = page.meta?.nextToken;
}
}
const meta = await fetch(
`${INSIGHTS_BASE}/v3/InsightsDomains/Conversations/Metadata`,
{ headers: getAuthHeaders() }
).then(r => r.json());
for (const cube of meta.cubes) {
console.log('Measures:', cube.measures.map(m => m.name));
console.log('Dimensions:', cube.dimensions.map(d => d.name));
}
Known dimensions: DateCreated, OperatorResults, OperatorResult.Value, Channels, Languages, Conversation.AccountSid
Known measures: Conversation.Count, OperatorResult.Count
GET /v3/OperatorResults for thatConversations