Skip to main content

Action items

Action items are persisted as first-class objects derived from the LLM analysis. Each item carries a provider-neutral intent and optional intentMetadata so the client can render launcher chips (Calendar, Gmail, dialer, …) without the backend constructing deep links.

GET /api/actions

List the authenticated user's action items. Newest first.

Response — 200 OK

[
{
"id": "a1b2c3d4-...",
"callRecordId": "f0a1d2e3-...",
"title": "Send revised pricing",
"description": "Revised pricing sheet by Friday",
"dueDate": "2026-06-26",
"status": "OPEN",
"sourceText": "priority=high; segments=seg_0002; text=\"I'll send the revised quote…\"",
"createdAt": "2026-05-29T13:00:42Z",
"updatedAt": "2026-05-29T13:00:42Z",
"ownerSpeakerId": "spk_1",
"ownerSpeakerLabel": "Speaker 1",
"ownerDisplayName": null,
"ownerRole": "USER",
"sourceSegmentIds": ["seg_0002"],
"intent": "email",
"intentMetadata": {
"toEmail": "alex@acme.com",
"toName": "Alex",
"subject": "Revised pricing sheet",
"bodyPreview": "Attaching the revised pricing reflecting the 12-month discount we discussed."
}
}
]

Fields

FieldTypeNotes
idUUIDStable row id. Use for PATCH /api/actions/{id}.
callRecordIdUUIDParent call. Filter client-side for per-call views.
titlestringShort action title from the LLM.
descriptionstringLonger context. Nullable.
dueDateISO dateYYYY-MM-DD. Null when the transcript didn't resolve one.
statusenumOPEN, IN_PROGRESS, DONE, or DISMISSED.
sourceTextstringForensic payload (priority, cited segments, excerpt).
ownerSpeakerIdstringStable spk_N from the normalised transcript.
ownerSpeakerLabelstringDisplay label at extraction time.
ownerDisplayNamestringRefined name when known.
ownerRolestringUSER / CONTACT / UNKNOWN.
sourceSegmentIdsstring[]Segment ids the LLM cited as evidence.
intentstringProvider-neutral classification — see below.
intentMetadataobjectTyped payload for deep-link construction. All fields optional.

Intent classification

The LLM classifies each action item with an abstract intent. The client (Android today, others later) decides which app(s) to offer as chips.

intentMeaningTypical chips (client-side)
meetingSchedule a video / phone meetingGoogle Calendar, Meet, Zoom, Teams
emailSend / draft an emailGmail, default mail app
callPhone the contact backDialer
messageSend a chat / SMSWhatsApp, SMS, Telegram
reminderSelf-reminder, no other partyCalendar reminder
taskTrack in a task systemShare sheet / task app
noneNo launchable intentNo chips

When the transcript was explicit about a provider ("let's hop on Zoom"), the LLM may set intentMetadata.providerHint (meet | zoom | teams | phone for meetings; whatsapp | sms | telegram for messages). This is a hint — the client makes the final call about which chip to show or prioritise.

intentMetadata by intent

Every field is optional. The LLM is instructed never to invent emails, phone numbers, or times not grounded in the transcript.

IntentTypically populated fields
meetingproviderHint, attendees: [{name, email?}], proposedAt (ISO datetime), durationMinutes, title, location
emailtoEmail, toName, subject, bodyPreview
callphoneNumber, contactName
messagechannel, phoneNumber or handle, bodyPreview
reminderremindAt (ISO datetime), title, notes
tasktitle, notes
none(empty / omitted)

GET /api/calls/{callId}/action-items

List the persistent action items attached to a specific call. Returns the same shape as GET /api/actions but scoped to one call. Includes both AI-extracted items (source: "AI") and user-created items (source: "MANUAL").

Response — 200 OK

Same array shape as GET /api/actions. Each item now also carries:

FieldTypeNotes
priorityenumLOW, MEDIUM, or HIGH. Null on legacy AI-extracted items.
sourcestring"AI" (extracted by pipeline) or "MANUAL" (created by user). Null on very old rows.

POST /api/calls/{callId}/action-items

Create a manual action item attached to a call.

Request

{
"title": "Send revised pricing",
"description": "Attach the updated Q3 sheet",
"dueDate": "2026-06-30",
"priority": "HIGH"
}
FieldRequiredNotes
titleYesShort action title.
descriptionNoLonger context.
dueDateNoYYYY-MM-DD.
priorityNoLOW, MEDIUM, or HIGH.

Response — 201 Created

The created ActionItemResponse with source: "MANUAL".

Errors

StatusCause
400Missing title or invalid field.
404Call not found or owned by another user.

PUT /api/action-items/{id}

Full replacement of a user-editable action item (title, description, dueDate, priority, status). All fields must be supplied; use the current values for fields the user did not change.

Request

{
"title": "Send revised pricing",
"description": "Attach the updated Q3 sheet",
"dueDate": "2026-06-30",
"priority": "HIGH",
"status": "OPEN"
}
FieldRequiredNotes
titleYes
descriptionNoPass null to clear.
dueDateNoYYYY-MM-DD. Pass null to clear.
priorityNoLOW, MEDIUM, or HIGH. Pass null to clear.
statusYesOPEN, IN_PROGRESS, DONE, or DISMISSED.

Response — 200 OK

The updated ActionItemResponse.

Errors

StatusCause
400Missing required field or invalid value.
404Item not found or owned by another user.

DELETE /api/action-items/{id}

Hard-deletes an action item. Idempotent — returns 404 if already deleted.

Response — 204 No Content

Errors

StatusCause
404Item not found or owned by another user.

PATCH /api/actions/{id}

Update an action item's status. Today only status is settable. Prefer PUT /api/action-items/{id} for full edits.

Request

{ "status": "DONE" }

status must be one of "OPEN", "IN_PROGRESS", "DONE", or "DISMISSED". The legacy values PENDING and COMPLETED were renamed in V19 and are no longer accepted.

Response — 200 OK

The updated ActionItemResponse (same shape as above, including intent and intentMetadata).

Errors

StatusCause
400Missing or invalid status.
404Item missing or owned by another user.

Client integration notes

  • Chips are a client concern. The backend classifies intent and extracts metadata; the Android app maps intent → list of ChipSpec (label + icon + Intent builder).
  • Two surfaces, same chips. intent + intentMetadata are returned on both GET /api/actions (the Actions tab) and on the action items inside GET /api/calls/{id}/analysis (the call-detail screen). The app renders identical integration chips on both via a shared renderer, so a call's action items show Calendar/Gmail/Call/Reminder chips inline — not only in the global Actions tab.
  • Completion is server-side. After the user finishes work in the target app, they tap the checkbox → PATCH /api/actions/{id} with { "status": "DONE" }. To un-complete, send { "status": "OPEN" }.
  • Full edit via PUT. Use PUT /api/action-items/{id} to update title, description, due date, priority, and status in one request. PATCH /api/actions/{id} remains for status-only toggles.
  • Manual creation. Users can add their own tasks on a call via POST /api/calls/{callId}/action-items. These items have source: "MANUAL" and priority can be set at creation time.
  • Priority. priority is LOW, MEDIUM, or HIGH. AI-extracted items may have null priority on older rows; the client should handle null gracefully (omit the badge rather than crash).
  • Legacy rows. Items extracted before intent classification was added have intent: null — render no chips.
  • Privacy. toEmail and phoneNumber are only populated when spoken in the transcript (or from call-log enrichment the user already consented to). The LLM is told to leave fields null rather than guess.