Call Results API

Retrieve call outcomes, transcripts, and recordings programmatically. Set up webhooks to get notified the moment a call ends. No more SSH into your server to parse transcript files.

Authentication

All read endpoints require a Bearer API key with the voice:read scope. Webhook configuration (PUT) requires the voice:call scope. Create keys in your voice portal API keys page.

Authorization: Bearer mbn_live_...

The voice:read scope gives read-only access to call data and recordings. It cannot place calls. To place calls AND read results, your key needs both voice:call and voice:read scopes.

Retrieve a single call

Get the full details of a completed call by its ID. The call ID is the callControlId returned when you placed the call, or found in the call log.

GET https://api.talktomyagent.io/v1/voice/calls/{callId}
Authorization: Bearer mbn_live_...

Response

{
  "data": {
    "id": "v3:abc123...",
    "direction": "outbound",
    "status": "completed",
    "endedReason": "callerHangup",
    "callerNumber": "+16473705600",
    "calledNumber": "+16475551234",
    "startedAt": "2026-05-25T14:30:00.000Z",
    "endedAt": "2026-05-25T14:35:12.000Z",
    "durationSeconds": 312,
    "recordingAvailable": true,
    "hasTranscript": true,
    "transcript": "[Agent] Hi, this is Sol... [Caller] Yeah...",
    "task": {
      "goal": "Collect $154.56 from Bobby",
      "script": "debt-collection",
      "facts": { "debtor_name": "Bobby", "amount_due": "$154.56" },
      "escalation": null
    },
    "usage": {
      "turnCount": 8,
      "inputTokens": 4521,
      "outputTokens": 2130
    },
    "quality": {
      "grade": "A",
      "p50ResponseLatencyMs": 340,
      "p95ResponseLatencyMs": 890
    }
  }
}

The transcript field contains the full conversation text. For inbound calls, task is null. For calls made before this feature launched, endedReason and transcript may be null.

Transcripts are only available via the API when the Ship Transcripts toggle is enabled in your voice portal settings. When disabled, transcripts are still saved as text files on your server but are not sent to the cloud. hasTranscript will be false and transcript will be null for calls made while shipping was off. Recordings are controlled independently by the Call Recording toggle.

Call end reasons

The endedReason field tells you exactly why a call ended. Use it to route post-call workflows, flag failed calls, or track agent performance.

ReasonMeaning
callerHangupThe other party hung up
botHangupYour agent ended the call (said goodbye)
callTimeoutMaximum call duration reached
silenceTimeoutExtended silence on the line
idleTimeoutNo activity detected
gatewayShutdownVoice gateway restarted
aiConnectionFailedCould not connect to AI backend
aiSessionLostAI session dropped and could not reconnect
mediaStreamDroppedPhone audio stream was interrupted
setupFailedCall could not be set up (network/dial error)
unknownReason not available

List calls

Retrieve your call history with cursor-based pagination. Filter by direction, end reason, or date range.

GET https://api.talktomyagent.io/v1/voice/calls?limit=25
Authorization: Bearer mbn_live_...

Query parameters

ParamDescription
limitResults per page (1-100, default 25)
cursorOpaque cursor from a previous response
directionFilter: "inbound" or "outbound"
endedReasonFilter by end reason (e.g. "callerHangup")
afterOnly calls after this ISO 8601 timestamp
beforeOnly calls before this ISO 8601 timestamp

Only one of direction or endedReason can be used per request. The transcript field is omitted from list responses to keep them compact. Use the single-call endpoint to get the full transcript.

Pagination

The response includes a pagination object. When hasMore is true, pass the cursor value to the next request:

GET /v1/voice/calls?limit=25&cursor=eyJtcyI6MTcx...

Download recordings

Get a short-lived signed URL to download the call recording as an MP3 file. The URL expires in 5 minutes.

GET https://api.talktomyagent.io/v1/voice/calls/{callId}/recording
Authorization: Bearer mbn_live_...

Response

{
  "data": {
    "url": "https://storage.googleapis.com/...",
    "expiresAt": "2026-05-25T14:40:00.000Z"
  }
}

Returns 404 if no recording is available. The recordingAvailable field on the call object tells you in advance whether a recording exists.

Webhooks

Instead of polling, configure a webhook URL to receive a POST request automatically every time a call ends. You get the full call data, including the transcript and task results, the moment they are ready.

Configure your webhook

Use your agent's phone number (from) to identify which deployment to configure:

PUT https://api.talktomyagent.io/v1/voice/webhooks
Authorization: Bearer mbn_live_...
Content-Type: application/json

{
  "from": "+16473705600",
  "url": "https://your-server.com/webhooks/ttma",
  "secret": "your-signing-secret-at-least-32-characters-long",
  "enabled": true
}

Your webhook URL must use HTTPS and must not point to private IP ranges or localhost. The signing secret is stored securely and never returned in full (only the last 4 characters are shown).

Webhook payload

When a call ends, we POST the following JSON to your URL:

{
  "event": "call.ended",
  "deliveryId": "a1b2c3d4-...",
  "timestamp": "2026-05-25T14:35:12.000Z",
  "data": {
    "id": "v3:abc123...",
    "direction": "outbound",
    "status": "completed",
    "endedReason": "botHangup",
    "callerNumber": "+16473705600",
    "calledNumber": "+16475551234",
    "startedAt": "2026-05-25T14:30:00.000Z",
    "endedAt": "2026-05-25T14:35:12.000Z",
    "durationSeconds": 312,
    "recordingAvailable": true,
    "hasTranscript": true,
    "transcript": "[Agent] Hi, this is Sol...",
    "task": { "goal": "...", "facts": { ... } },
    "usage": { "turnCount": 8 },
    "quality": { "grade": "A" }
  }
}

The data object is the same shape as the single-call GET response. Headers included with every delivery:

HeaderDescription
X-TTMA-EventEvent type (always "call.ended")
X-TTMA-Delivery-IdUnique delivery ID for deduplication
X-TTMA-SignatureHMAC-SHA256 signature for verification

Webhook payloads may include task.facts which can contain PII (names, payment amounts, phone numbers). Use HTTPS endpoints, validate the HMAC signature, and handle the payload in a secure environment.

Verify the signature

Every webhook delivery is signed with your secret using HMAC-SHA256. Always verify the signature before processing the payload:

// Node.js verification example
const crypto = require("crypto");

function verifyWebhook(rawBody, signatureHeader, secret) {
  // Parse the header: "t=1716648912,v1=abc123..."
  const parts = {};
  signatureHeader.split(",").forEach(p => {
    const [k, v] = p.split("=");
    parts[k] = v;
  });

  // Reject old deliveries (replay defense)
  const age = Math.abs(Date.now() / 1000 - Number(parts.t));
  if (age > 300) return false; // 5-minute window

  // Compute expected signature
  const expected = crypto
    .createHmac("sha256", secret)
    .update(parts.t + "." + rawBody)
    .digest("hex");

  // Constant-time comparison
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(parts.v1, "hex")
  );
}

Delivery behavior

Webhooks wait for the recording to be ready before delivering (up to 60 seconds). If a recording doesn't arrive in time, the webhook fires anyway with recordingAvailable: false. Failed deliveries are retried up to 5 times. If your endpoint returns 410 Gone, the webhook is automatically disabled.

Using with n8n and automation tools

The webhook is standard JSON over HTTPS, making it easy to connect to any automation platform. For n8n:

1. Create a Webhook node with your URL

2. Configure your TTMA webhook to point at the n8n webhook URL

3. The payload arrives as structured JSON. No regex parsing needed. Access fields directly: {{ $json.data.endedReason }}, {{ $json.data.task.facts.debtor_name }}, etc.

This replaces the previous approach of SSHing into the server and parsing transcript text files. All the same data is available in structured JSON, delivered automatically.

Full API reference

For the complete endpoint specification including all fields, error codes, and rate limits, see the interactive API reference.