Call Analytics API documentation

Built for AI agents

This API is designed to be driven by autonomous agents. The shapes are stable and strict, the report is fully machine-readable, and we publish both an OpenAPI spec and an llms.txt so an agent can discover and call the API with no human in the loop.

Machine-readable resources

Both live on this docs host: https://docs.callanalyticsapi.com/llms.txt and https://docs.callanalyticsapi.com/openapi.json.

Tool / function schemas

Drop these straight into your LLM tool definitions. They mirror the API exactly. Authenticate the underlying HTTP calls with Authorization: Bearer <api_key>.

submit_sales_call

{
  "name": "submit_sales_call",
  "description": "Submit a sales call recording for transcription and AI analysis. Returns a call_id used to poll for the report. Safe to retry: passing the same external_call_id will not create a duplicate.",
  "parameters": {
    "type": "object",
    "properties": {
      "external_call_id": { "type": "string", "description": "Your stable id for the call; used for deduplication." },
      "recording_url":    { "type": "string", "description": "Publicly fetchable audio URL (mp3/wav/m4a)." },
      "rep_name":         { "type": "string" },
      "rep_email":        { "type": "string" },
      "customer_name":    { "type": "string" },
      "customer_phone":   { "type": "string" },
      "customer_email":   { "type": "string" },
      "call_started_at":  { "type": "string", "description": "ISO 8601." },
      "call_ended_at":    { "type": "string", "description": "ISO 8601." },
      "duration_seconds": { "type": "integer" },
      "source_system":    { "type": "string", "description": "Origin label, e.g. 'gohighlevel'." },
      "crm_contact_id":   { "type": "string" },
      "crm_deal_id":      { "type": "string" },
      "metadata": {
        "type": "object",
        "properties": {
          "high_value_opportunity": { "type": "boolean" }
        }
      }
    },
    "required": ["recording_url"]
  }
}

Maps to POST https://api.callanalyticsapi.com/v1/calls. Returns { "call_id": int, "status": "received" | "duplicate", "processing_status_url": str }.

get_call_report

{
  "name": "get_call_report",
  "description": "Fetch the structured analysis report for a call. If the report is not ready yet the API returns 409 with the current processing status; wait and retry.",
  "parameters": {
    "type": "object",
    "properties": {
      "call_id": { "type": "integer", "description": "The call_id returned by submit_sales_call." }
    },
    "required": ["call_id"]
  }
}

Maps to GET https://api.callanalyticsapi.com/v1/calls/{call_id}/report. Returns { "call_id": int, "report": { … } } on success, or 409 {"error":"report_not_ready","status":"…"} while still processing. To check status without fetching the full report, call GET /v1/calls/{call_id} and read report_status.

A worked agent loop

The canonical loop: submit → poll status → fetch report → act on the coaching output.

# pseudocode

call = submit_sales_call(
    external_call_id = lead["id"],
    recording_url    = lead["recording"],
    customer_name    = lead["company"],
    rep_email        = lead["owner_email"],
)

# 2. Poll status with backoff until the report is ready
while True:
    state = GET /v1/calls/{call.call_id}        # read report_status
    if state.report_status == "ready": break
    if state.processing_status == "failed": handle_failure(); break
    sleep(backoff())                            # honor Retry-After on 429

# 3. Fetch the report (handle 409 as "not ready, keep waiting")
report = get_call_report(call.call_id)["report"]

# 4. Act on it
if report["overall_score"] < 60 or report["manager_review_required"]:
    notify_manager(report["summary"], report["coaching_notes"])

for signal in report["buying_signals"]:
    if signal["strength"] == "high":
        create_task("Follow up: " + report["suggested_follow_up"])

if report["compliance_alerts"]:
    open_compliance_ticket(report["compliance_alerts"])

write_crm_note(lead["id"], report["crm_note"])

Prefer event-driven over polling? Subscribe an endpoint to call.report_completed and skip the poll loop entirely — see Webhooks.

Report fields an agent should act on

FieldSuggested action
overall_scoreRoute low scores to coaching / manager review; tag high scores as exemplars.
close_likelihoodPrioritize follow-up and forecast updates.
buying_signalsCreate high-priority follow-up tasks for strong signals.
objectionsSurface unhandled objections (handled: false) with the suggested response.
compliance_alertsOpen a ticket / escalate when non-empty.
suggested_follow_upDraft the next outreach or schedule the next step.
crm_noteWrite back to the CRM contact/deal verbatim.
coaching_notes / rep_weaknessesAssign training; feed the rep's coaching feed.
confidence_levelGate automated actions on high; route low to a human.

Gate consequential actions (emails to customers, CRM stage changes) on confidence_level == "high" and a sane overall_score. When confidence is low, prefer a human review step.