Skip to main content
Query reports for call requests, including all attempts, events, and flow execution details.
Base path: /call-report

Types

// ============================================
// 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
            }
          }
        }
      ]
    }
  ]
}
Queued job (not yet executed):
{
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "attempts": []
}
Error Responses:
CodeErrorDescription
404NotFoundExceptionJob 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 }
      }
    }
  ]
}
Note: 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:
CodeErrorDescription
404NotFoundExceptionCall 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)
  • attempts array is ordered by attempt number (1, 2, 3…)
  • status is derived from BullMQ state if available, otherwise from call outcomes
  • finalOutcome is the outcome of the last attempt
  • executionPath shows exact nodes executed with their output paths
  • events include nodeContext to correlate with flow execution
  • Works for both ad-hoc calls (via /call-requests) and program calls