Skip to content
Linq

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 /events serves, 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’s seq is the event log’s own, so an activity item and its /events row are the same fact under the same id. class is a closed enum the server promises: contact | consent | control. actor is one of the closed set customer|partner|human|flow|system|brand; an operator’s identity, where one was recorded, is detail.operator.
  • entry_routed (class control) is one entry-point routing decision, recorded for every inbound your routing document routed, whatever it decided. Its detail carries intent and group (the biz-intent-id and biz-group-id your entry-point link delivered), matched (the 0-based index of the rule that fired in your routing document, or default), action (flow | human | none | entry_flow), flow (the flow that was started, empty when none was), outcome (applied | already_applied | entry_flow_unset), and routed_seq, the seq of 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 own seq.
  • origin, consent, and consent_events are returned on the FIRST page only (a request with no after_seq); a resumed request answers activity alone. Page activity with after_seq exactly as /events.
  • consent is a FOUR-STATE headline per category (granted | revoked | expired | none) over the categories that apply to the chat’s handle kind: expired is a grant whose expires_at has passed, reported the way the send gate already treats it, and none means no decision on record. consent_events is the append-only consent history (granted | revoked | expired), complete for the subject; each category’s history_recorded_since is its earliest recorded event.

Errors

  • HTTP 404: unknown chat, or one belonging to another brand.
Path ParametersExpand Collapse
chat: string
Query ParametersExpand Collapse
after_seq: optional number

Resume the activity page after this seq; omitted (or non-numeric) reads from the start and includes the origin/consent/consent_events blocks.

formatint64
limit: optional number

Page size for activity; absent or outside 1-100 reads as 100.

formatint32
ReturnsExpand Collapse
ActivityResponse object { activity, consent, consent_events, origin }

The activity timeline: the chat’s governance story as a read-time composition. origin, consent, and consent_events appear on the first page only; a resumed page (after_seq present) carries activity alone.

activity: array of object { actor, at, class, 3 more }

The governance events, seq-paged exactly as /events.

actor: string

Who did this: customer, partner, human, flow, system, or brand.

at: string
formatdate-time
class: "contact" or "consent" or "control"

Server-promised closed class; render by class for any type you do not map.

One of the following:
"contact"
"consent"
"control"
seq: number

The event log’s own seq: the same id the /events row carries.

formatint64
type: string

The event type (owner_changed, handoff_accepted, flow_entered, …).

detail: optional unknown

Per-type detail from the event’s payload. OPEN AND ADDITIVE by contract: keys may be added over time, never renamed or removed; operator, reason and the per-type ids are present whenever their event recorded them.

One of the following:
origin: optional object { kind, at, invitation }

Contact provenance. First page only.

kind: "customer_initiated" or "invitation"

customer_initiated (the customer’s first message created the chat) or invitation (business-initiated).

One of the following:
"customer_initiated"
"invitation"
at: optional string

First-contact instant for a customer-initiated chat: the chat’s own creation stamp.

formatdate-time
invitation: optional object { id, delivery, sent_at, 3 more }

The originating invitation, for kind: invitation.

id: string
delivery: string

Its delivery state.

sent_at: string

When the invitation was sent.

formatdate-time
response: optional string

The customer’s response, when one was recorded.

response_source: optional string

How the response was resolved: tap, or the literal-text fallback.

superseded_by_chat_id: optional string

Set when a later invitation superseded this conversation.

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"
      }
    }
  ]
}