## 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 Parameters

- `chat: string`

### Query Parameters

- `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.

- `limit: optional number`

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

### Returns

- `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`

    - `class: "contact" or "consent" or "control"`

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

      - `"contact"`

      - `"consent"`

      - `"control"`

    - `seq: number`

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

    - `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.

  - `consent: optional unknown`

    Four-state consent snapshot per category applying to this chat's handle kind: `granted`, `revoked`, `expired`, or `none`. First page only.

  - `consent_events: optional array of object { action, at, category, 2 more }`

    The subject's append-only consent history, time-ordered and complete. First page only.

    - `action: "granted" or "revoked" or "expired"`

      `granted`, `revoked`, or `expired`, an expiry lapse recorded by the sweep.

      - `"granted"`

      - `"revoked"`

      - `"expired"`

    - `at: string`

    - `category: string`

    - `capture_mode: optional string`

    - `source: optional string`

  - `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).

      - `"customer_initiated"`

      - `"invitation"`

    - `at: optional string`

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

    - `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.

      - `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.

### Example

```http
curl https://messages.api.linqapp.com/v1/chats/$CHAT/activity \
    -H "Authorization: Bearer $LINQ_AMB_API_KEY"
```

#### Response

```json
{
  "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"
      }
    }
  ]
}
```
