Base path:
/call-reportTypes
Type Definitions
Type Definitions
// ============================================
// JOB STATUS
// ============================================
type JobStatus = 'queued' | 'active' | 'completed' | 'failed';
// ============================================
// CALL DETAILS
// ============================================
interface CallDetails {
status: string;
direction: 'inbound' | 'outbound';
from: string;
to: string;
createdAt: string; // ISO date
dialedAt?: string; // ISO date
answeredAt?: string; // ISO date
terminatedAt?: string; // ISO date
durationMs?: number;
}
// ============================================
// NODE EXECUTION PATH ENTRY
// ============================================
interface NodeExecutionPathEntry {
nodeId: string;
nodeType: string; // 'dial' | 'play' | 'dtmf' | 'record' | 'condition' | 'set_variable' | 'hangup' | 'answer'
nodeLabel?: string;
outputPath?: string; // Which output was taken (e.g., 'onAnswer', 'onBusy', 'onComplete')
timestamp: string; // ISO date
}
// ============================================
// FLOW EXECUTION DETAILS
// ============================================
interface FlowExecutionDetails {
flowId: string;
flowName: string;
flowVersion: number;
executionPath: NodeExecutionPathEntry[];
finalVariables: Record<string, string | number | boolean | null>;
nodeExecutionCount: number;
flowStartedAt?: string; // ISO date
flowCompletedAt?: string; // ISO date
}
// ============================================
// NODE CONTEXT (embedded in event data)
// ============================================
interface NodeContext {
nodeId: string;
nodeType: string;
nodeExecutionIndex: number;
}
// ============================================
// CALL EVENT
// ============================================
interface CallEvent {
type: string; // 'dial' | 'answer' | 'play' | 'record' | 'dtmf' | 'hangup' | etc.
timestamp: string; // ISO date
data: Record<string, unknown>; // Includes nodeContext when applicable
}
// ============================================
// CALL BILLING
// ============================================
interface NodeCostReport {
nodeId: string;
nodeType: string;
durationMs: number | null;
cost: number;
costPerUnit: number;
unit: 'second' | 'minute' | 'flat';
minDurationMs: number | null;
}
interface CallBillingReport {
nodes: NodeCostReport[];
totalCost: number;
}
// ============================================
// CALL ATTEMPT REPORT
// ============================================
interface CallAttemptReport {
/** Unique call ID (UUID) */
callId: string;
/** Attempt number (1-based) */
attempt: number;
/** Business context (if from program execution) */
programId?: string;
programExecutionId?: string;
contactId?: string;
/** Call metadata */
call: CallDetails;
/** Final outcome */
outcome: string;
/** Human-readable reason */
outcomeReason?: string;
/** Flow execution details (if flow was executed) */
flowExecution?: FlowExecutionDetails;
/** Billing breakdown (only for completed calls with cost) */
billing?: CallBillingReport;
/** Events timeline */
events: CallEvent[];
}
// ============================================
// JOB REPORT
// ============================================
interface JobReport {
/** Job ID (UUID from POST /call-requests) */
jobId: string;
/** Current job status */
status: JobStatus;
/** Final outcome (from last attempt) */
finalOutcome?: string;
/** All call attempts */
attempts: CallAttemptReport[];
}
Get full report for a call request job
Completed job with retry (first attempt busy, second answered):{
"jobId": "ec8edce0-f898-4d34-b2fc-542ef98f38a5",
"status": "completed",
"finalOutcome": "completed",
"attempts": [
{
"callId": "1cbdf482-4dac-41ed-a430-2e311add389d",
"attempt": 1,
"call": {
"status": "busy",
"direction": "outbound",
"from": "1000",
"to": "6001",
"createdAt": "2025-12-16T11:15:00.062Z",
"dialedAt": "2025-12-16T11:15:00.103Z",
"terminatedAt": "2025-12-16T11:15:07.352Z"
},
"outcome": "busy",
"outcomeReason": "Flow completed (Error in dial node: Remote hangup for call ...: busy (cause: 17, code: 17))",
"flowExecution": {
"flowId": "03418632-e6da-451e-875f-23b55f938e3e",
"flowName": "credit-dtmf-playback-test",
"flowVersion": 1,
"executionPath": [
{
"nodeId": "dial-1",
"nodeType": "dial",
"nodeLabel": "Dial Contact",
"timestamp": "2025-12-16T11:15:00.071Z",
"outputPath": "onBusy"
},
{
"nodeId": "hangup-1",
"nodeType": "hangup",
"nodeLabel": "End Call",
"timestamp": "2025-12-16T11:15:07.333Z",
"outputPath": "terminated"
}
],
"finalVariables": {
"contact.id": "6fd21c0b-bf05-407e-bcd7-9f9aab7ab91e",
"sys.callId": "1cbdf482-4dac-41ed-a430-2e311add389d",
"sys.attempt": 1,
"sys.maxAttempts": 3,
"contact.phone": "6001",
"contact.fullName": "dev-anouar-1",
"contact.customAttributes.credit": 90856
},
"nodeExecutionCount": 2,
"flowStartedAt": "2025-12-16T11:15:00.070Z",
"flowCompletedAt": "2025-12-16T11:15:07.352Z"
},
"events": [
{
"type": "dial",
"timestamp": "2025-12-16T11:15:00.072Z",
"data": {
"to": "6001",
"from": "1000",
"timeout": 30000,
"enableAMD": false,
"nodeContext": {
"nodeId": "dial-1",
"nodeType": "dial",
"nodeExecutionIndex": 2
}
}
},
{
"type": "hangup",
"timestamp": "2025-12-16T11:15:07.352Z",
"data": {
"hangupType": "busy",
"hangupReason": "Flow completed (...)",
"nodeContext": {
"nodeId": "hangup-1",
"nodeType": "hangup",
"nodeExecutionIndex": 3
}
}
}
]
},
{
"callId": "eae26ac8-be39-490b-b9ed-a82e7f4048f6",
"attempt": 2,
"call": {
"status": "completed",
"direction": "outbound",
"from": "1000",
"to": "6001",
"createdAt": "2025-12-16T11:15:30.105Z",
"dialedAt": "2025-12-16T11:15:30.139Z",
"answeredAt": "2025-12-16T11:15:34.479Z",
"durationMs": 7757
},
"outcome": "completed",
"flowExecution": {
"flowId": "03418632-e6da-451e-875f-23b55f938e3e",
"flowName": "credit-dtmf-playback-test",
"flowVersion": 1,
"executionPath": [
{
"nodeId": "dial-1",
"nodeType": "dial",
"nodeLabel": "Dial Contact",
"timestamp": "2025-12-16T11:15:30.114Z",
"outputPath": "onAnswer"
},
{
"nodeId": "play-credit",
"nodeType": "play",
"nodeLabel": "Play Credit Balance",
"timestamp": "2025-12-16T11:15:34.481Z",
"outputPath": "onComplete"
}
],
"finalVariables": {
"answeredBy": "human",
"sys.attempt": 2,
"sys.maxAttempts": 3,
"contact.customAttributes.credit": 90856
},
"nodeExecutionCount": 2,
"flowStartedAt": "2025-12-16T11:15:30.113Z"
},
"events": [
{
"type": "dial",
"timestamp": "2025-12-16T11:15:30.115Z",
"data": {
"to": "6001",
"from": "1000",
"timeout": 30000,
"enableAMD": false,
"nodeContext": {
"nodeId": "dial-1",
"nodeType": "dial",
"nodeExecutionIndex": 2
}
}
},
{
"type": "answer",
"timestamp": "2025-12-16T11:15:34.479Z",
"data": {
"answeredBy": "human",
"ringDurationMs": 4340,
"nodeContext": {
"nodeId": "dial-1",
"nodeType": "dial",
"nodeExecutionIndex": 2
}
}
},
{
"type": "play",
"timestamp": "2025-12-16T11:15:42.231Z",
"data": {
"durationMs": 6420,
"bufferCount": 2,
"completedBy": "stopped",
"nodeContext": {
"nodeId": "play-credit",
"nodeType": "play",
"nodeExecutionIndex": 3
}
}
}
]
}
]
}
{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"attempts": []
}
| Code | Error | Description |
|---|---|---|
| 404 | NotFoundException | Job not found (invalid jobId or job cleaned up with no calls) |
Get detailed report for a single call
Example Response:{
"callId": "60e8fbc0-2cda-4b2e-bc0f-221c3121bf09",
"attempt": 1,
"programId": "abc12345-1234-5678-9012-abcdef123456",
"programExecutionId": "exec-9876-5432-1098-fedcba987654",
"contactId": "6fd21c0b-bf05-407e-bcd7-9f9aab7ab91e",
"call": {
"status": "completed",
"direction": "outbound",
"from": "1000",
"to": "6001",
"createdAt": "2025-12-18T14:17:32.736Z",
"dialedAt": "2025-12-18T14:17:32.800Z",
"answeredAt": "2025-12-18T14:17:36.100Z",
"terminatedAt": "2025-12-18T14:18:01.134Z",
"durationMs": 25001
},
"outcome": "completed",
"outcomeReason": "Flow completed successfully",
"flowExecution": {
"flowId": "03418632-e6da-451e-875f-23b55f938e3e",
"flowName": "credit-dtmf-playback-test",
"flowVersion": 1,
"executionPath": [
{
"nodeId": "dial-1",
"nodeType": "dial",
"nodeLabel": "Dial Contact",
"timestamp": "2025-12-18T14:17:32.740Z",
"outputPath": "onAnswer"
},
{
"nodeId": "play-credit",
"nodeType": "play",
"nodeLabel": "Play Credit Balance",
"timestamp": "2025-12-18T14:17:36.105Z",
"outputPath": "onComplete"
}
],
"finalVariables": {
"contact.id": "6fd21c0b-bf05-407e-bcd7-9f9aab7ab91e",
"sys.callId": "60e8fbc0-2cda-4b2e-bc0f-221c3121bf09",
"sys.attempt": 1,
"contact.customAttributes.credit": 90856
},
"nodeExecutionCount": 2,
"flowStartedAt": "2025-12-18T14:17:32.738Z",
"flowCompletedAt": "2025-12-18T14:18:01.134Z"
},
"billing": {
"nodes": [
{
"nodeId": "dial-1",
"nodeType": "dial",
"durationMs": 25001,
"cost": 1.875075,
"costPerUnit": 0.075,
"unit": "second",
"minDurationMs": 10000
}
],
"totalCost": 1.875075
},
"events": [
{
"type": "dial",
"timestamp": "2025-12-18T14:17:32.741Z",
"data": {
"to": "6001",
"from": "1000",
"timeout": 30000,
"nodeContext": { "nodeId": "dial-1", "nodeType": "dial", "nodeExecutionIndex": 1 }
}
},
{
"type": "answer",
"timestamp": "2025-12-18T14:17:36.100Z",
"data": {
"answeredBy": "human",
"ringDurationMs": 3300,
"nodeContext": { "nodeId": "dial-1", "nodeType": "dial", "nodeExecutionIndex": 1 }
}
},
{
"type": "play",
"timestamp": "2025-12-18T14:17:58.500Z",
"data": {
"durationMs": 22000,
"completedBy": "stopped",
"nodeContext": { "nodeId": "play-credit", "nodeType": "play", "nodeExecutionIndex": 2 }
}
}
]
}
programId, programExecutionId, and contactId are populated when the call was made through a program execution. They are undefined for direct call-request API calls.
Error Responses:
| Code | Error | Description |
|---|---|---|
| 404 | NotFoundException | Call not found or does not belong to organization |
Event Types
Notes
- Report works even if BullMQ job has been cleaned up (call data persisted in DB)
attemptsarray is ordered by attempt number (1, 2, 3…)statusis derived from BullMQ state if available, otherwise from call outcomesfinalOutcomeis the outcome of the last attemptexecutionPathshows exact nodes executed with their output pathseventsincludenodeContextto correlate with flow execution- Works for both ad-hoc calls (via
/call-requests) and program calls