Skip to main content

Call Notes & Scoring

Turn a finished call or chat into structured notes, push them to your CRM, and grade the conversation against a QA scorecard you write — with a transcript quote behind every score.

Overview

Two post-conversation tools, both keyed by a conversation id (the id from Conversations; every voice call and chat has one):

  • Call notes — POST /api/v1/calls/{conversation_id}/notes reads the transcript and writes a structured note: a summary, action items, a disposition, a follow-up date and tags. Edit it, then push it to your CRM.
  • Call scoring — write a scorecard (a rubric of weighted criteria), then POST /api/v1/calls/{conversation_id}/score grades the conversation against it. Every criterion comes back with a 0–100 score and the transcript line that justifies it.

Both run one language-model completion and are billed in credits at that model's per-token LLM rate. Reading, editing and pushing notes, and managing scorecards, are free.

Authentication

Authorization: Bearer cm_your_api_key
OperationScope
Read notes, list/get scorecards, read a scoreconversations:read
Generate/edit/push notes, create/update/delete scorecards, score a callconversations:write

Base URL: https://api.callmissed.com. Errors are {"detail": "..."}. A conversation or scorecard outside your workspace returns 404, never 403.


Call notes

The notes object

{
  "conversation_id": "c0ffee00-1111-2222-3333-444455556666",
  "notes": {
    "summary": "Caller asked to move her Thursday appointment. Agent offered Friday 11:00, which she accepted.",
    "action_items": ["Send the Friday confirmation by WhatsApp"],
    "disposition": "rescheduled",
    "follow_up_date": "2026-10-09",
    "tags": ["appointment", "reschedule"],
    "generated_at": "2026-10-02T09:30:00+00:00",
    "edited_at": null,
    "edited_by": null,
    "pushed": null
  }
}

notes is null until notes have been generated.

FieldTypeNotes
summarystringUp to 2,000 characters
action_itemsstring[]Up to 10 items, 300 characters each
dispositionstring | nullShort outcome label, up to 64 characters
follow_up_datestring | nullYYYY-MM-DD. A date the model could not express this way is dropped, not guessed
tagsstring[]Up to 10, 40 characters each, lower-cased
generated_atstringISO 8601
edited_atstring | nullSet by PATCH
edited_bystring | nullThe dashboard user who edited; null for an API-key edit
pushedobject | nullAfter a CRM push: {provider, at, note_id, contact_id}

GET /api/v1/calls/{conversation_id}/notes

Returns the notes object — notes: null if none have been generated yet.

POST /api/v1/calls/{conversation_id}/notes

Generates notes from the transcript and saves them.

FieldTypeRequiredDefaultNotes
forcebooleanNofalseRegenerate even if notes exist. Without it, existing notes are returned unchanged and nothing is billed
curl -X POST https://api.callmissed.com/api/v1/calls/c0ffee00-1111-2222-3333-444455556666/notes \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{}'

The note is written by the conversation agent's configured model, or gpt-oss-120b when the agent has none, and billed at that model's token rate.

StatusCause
400The conversation has no messages yet
402Insufficient credits, or Monthly budget cap reached
404Conversation not found
502The model failed or returned an unusable note — retry

PATCH /api/v1/calls/{conversation_id}/notes

Edit the stored notes. Every field is optional; only what you send changes.

FieldTypeNotes
summarystringUp to 2,000 characters. Cannot be empty (422)
action_itemsstring[]Replaces the list
dispositionstringUp to 64 characters
follow_up_datestringYYYY-MM-DD; "" clears it. Anything else is 422 follow_up_date must be YYYY-MM-DD
tagsstring[]Replaces the list

404 when no notes have been generated yet.

POST /api/v1/calls/{conversation_id}/notes/push

Pushes the stored notes to your CRM as a note, attached to the matching CRM contact when the conversation's contact has an email that exists there.

FieldTypeDefaultNotes
providerstring"hubspot"hubspot is the only CRM available today

Connect HubSpot under Integrations in the console first.

{
  "provider": "hubspot",
  "note_id": "81234567890",
  "contact_id": "5123",
  "associated": true
}

associated is false when no matching contact was found — the note is still created, just not attached.

StatusCause
400Unknown CRM provider
404Conversation not found, or no notes generated yet
409salesforce, zoho or pipedrive (not available yet), or HubSpot is not connected / needs reconnecting
502HubSpot rejected the push

Scorecards

A scorecard is your QA rubric.

{
  "id": "5c0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b",
  "name": "Support QA",
  "criteria": [
    { "label": "Verified caller identity", "weight": 2, "guidance": "Asked for name and booking reference before discussing the booking." },
    { "label": "Resolved or escalated", "weight": 3, "guidance": null },
    { "label": "Polite close", "weight": 1, "guidance": null }
  ],
  "created_at": "2026-10-01T08:00:00Z",
  "updated_at": "2026-10-01T08:00:00Z"
}
Criterion fieldTypeRequiredConstraints
labelstringYes1–200 characters, unique within the scorecard (case-insensitive)
weightnumberNo (default 1)0 < weight <= 100. Relative importance — weights need not sum to anything
guidancestringNoUp to 1,000 characters. What a good answer looks like

A scorecard has 1–20 criteria. A rule violation returns 400 naming the criterion.

GET /api/v1/scorecards

Newest first. limit 1..500 (default 100), offset 0..100000.

POST /api/v1/scorecards

Body: name (1–200 characters) and criteria. Returns 201 with the scorecard.

curl -X POST https://api.callmissed.com/api/v1/scorecards \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support QA",
    "criteria": [
      {"label": "Verified caller identity", "weight": 2},
      {"label": "Resolved or escalated", "weight": 3},
      {"label": "Polite close", "weight": 1}
    ]
  }'

GET /api/v1/scorecards/{scorecard_id}

Returns one scorecard.

PUT /api/v1/scorecards/{scorecard_id}

Replaces name and criteria (both required, same rules as create). Scores already taken keep their own breakdown, so past grades are unchanged.

DELETE /api/v1/scorecards/{scorecard_id}

Returns 204. Scores taken with it survive with scorecard_id: null.


Scoring a call

POST /api/v1/calls/{conversation_id}/score

FieldTypeRequired
scorecard_idUUIDYes
curl -X POST https://api.callmissed.com/api/v1/calls/c0ffee00-1111-2222-3333-444455556666/score \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"scorecard_id": "5c0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b"}'
{
  "conversation_id": "c0ffee00-1111-2222-3333-444455556666",
  "scorecard_id": "5c0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b",
  "total": 76.67,
  "breakdown": [
    { "criterion": "Verified caller identity", "score": 90, "evidence_quote": "Agent: Could I have your booking reference, please?" },
    { "criterion": "Resolved or escalated", "score": 70, "evidence_quote": "Agent: I've moved you to Friday at eleven." },
    { "criterion": "Polite close", "score": 60, "evidence_quote": null }
  ],
  "model": "gpt-5-mini",
  "created_at": "2026-10-02T09:31:00Z"
}
  • total is the weight-weighted mean of the criterion scores, on a 0–100 scale.
  • breakdown always follows your rubric, in order. A criterion the model skipped scores 0 rather than disappearing, so a missing line can never inflate the total.
  • evidence_quote is a verbatim transcript line, or null when nothing in the transcript supports the criterion.
  • Re-scoring the same conversation with the same scorecard replaces the previous score.
  • Billed at the model's LLM token rate. Long transcripts are trimmed from the middle before grading, keeping the opening and the close.
StatusCause
402Credit balance is zero
404Conversation or scorecard not found
409The conversation has no transcript yet
502The model returned an unreadable response (still billed — retry)
503Scoring is temporarily unavailable — retry

GET /api/v1/calls/{conversation_id}/score

The newest stored score for the conversation, across all scorecards. 404 This call has not been scored yet if there is none.