Get a chat's activity timeline
GET/v1/chats/{chat}/activity
The chat’s activity timeline: the governance story, distinct from the transcript: how contact began, what consent stands, who controlled the conversation when. Read-only, composed at read time.
Behavior
activity[]carries the same event-log rows/eventsserves, narrowed to governance events (ownership, handoffs, flows, entry-point routing decisions, close/reopen, invitation responses, enforcement audit rows), never messages, typing, or reactions. Each item’sseqis the event log’s own, so an activity item and its/eventsrow are the same fact under the same id.classis a closed enum the server promises:contact | consent | control.actoris one of the closed setcustomer|partner|human|flow|system|brand; an operator’s identity, where one was recorded, isdetail.operator.entry_routed(classcontrol) is one entry-point routing decision, recorded for every inbound your routing document routed, whatever it decided. Itsdetailcarriesintentandgroup(thebiz-intent-idandbiz-group-idyour entry-point link delivered),matched(the 0-based index of the rule that fired in your routing document, ordefault),action(flow|human|none|entry_flow),flow(the flow that was started, empty when none was),outcome(applied|already_applied|entry_flow_unset), androuted_seq, theseqof the inbound the decision was about. A customer can open a second entry point part way through a conversation, so a chat can carry several, each at its ownseq.origin,consent, andconsent_eventsare returned on the FIRST page only (a request with noafter_seq); a resumed request answersactivityalone. Pageactivitywithafter_seqexactly as/events.consentis a FOUR-STATE headline per category (granted | revoked | expired | none) over the categories that apply to the chat’s handle kind:expiredis a grant whoseexpires_athas passed, reported the way the send gate already treats it, andnonemeans no decision on record.consent_eventsis the append-only consent history (granted | revoked | expired), complete for the subject; each category’shistory_recorded_sinceis its earliest recorded event.
Errors
- HTTP 404: unknown chat, or one belonging to another brand.
Query Parameters
Get a chat's activity timeline
curl https://messages.api.linqapp.com/v1/chats/$CHAT/activity \
-H "Authorization: Bearer $LINQ_AMB_API_KEY"{
"origin": {
"kind": "invitation",
"invitation": {
"id": "inv_7f81c2",
"sent_at": "2026-08-14T17:55:34Z",
"delivery": "sent",
"response": "accepted",
"response_source": "tap"
}
},
"consent": {
"marketing": {
"state": "none",
"history_recorded_since": null
},
"account_notification": {
"state": "granted",
"source": "inbound_keyword",
"capture_mode": "linq_managed",
"granted_at": "2026-08-14T18:01:02Z",
"history_recorded_since": "2026-08-14T18:01:02Z"
}
},
"consent_events": [
{
"category": "account_notification",
"action": "granted",
"at": "2026-08-14T18:01:02Z",
"source": "inbound_keyword",
"capture_mode": "linq_managed"
}
],
"activity": [
{
"seq": 9,
"type": "handoff_accepted",
"class": "control",
"at": "2026-08-14T18:02:40Z",
"actor": "human",
"detail": {
"operator": "op_becca",
"reason": "customer asked"
}
}
]
}Returns Examples
{
"origin": {
"kind": "invitation",
"invitation": {
"id": "inv_7f81c2",
"sent_at": "2026-08-14T17:55:34Z",
"delivery": "sent",
"response": "accepted",
"response_source": "tap"
}
},
"consent": {
"marketing": {
"state": "none",
"history_recorded_since": null
},
"account_notification": {
"state": "granted",
"source": "inbound_keyword",
"capture_mode": "linq_managed",
"granted_at": "2026-08-14T18:01:02Z",
"history_recorded_since": "2026-08-14T18:01:02Z"
}
},
"consent_events": [
{
"category": "account_notification",
"action": "granted",
"at": "2026-08-14T18:01:02Z",
"source": "inbound_keyword",
"capture_mode": "linq_managed"
}
],
"activity": [
{
"seq": 9,
"type": "handoff_accepted",
"class": "control",
"at": "2026-08-14T18:02:40Z",
"actor": "human",
"detail": {
"operator": "op_becca",
"reason": "customer asked"
}
}
]
}