## Get a chat

**get** `/v1/chats/{chat}`

Retrieves a chat, including the customer's per-category consent and whether a send would currently be refused.

### Path Parameters

- `chat: string`

### Returns

- `ChatView object { id, brand, capabilities, 14 more }`

  The partner view of a chat.

  - `id: string`

    Chat id (`chat_…`). The LIST endpoint spells the same fact `chat_id`; neither is renamed to match the other.

  - `brand: object { id, business_hours, display_name, hours_timezone }`

    This chat's brand and its configured display/hours.

    - `id: string`

      The brand this chat belongs to; always your own.

    - `business_hours: optional unknown`

      Business hours as stored: a LIST of `["HH:MM","HH:MM"]` ranges per lowercase weekday key (`mon`…`sun`), so a split shift is expressible. Absent when no hours are configured.

    - `display_name: optional string`

      The brand's display name; absent when it has none.

    - `hours_timezone: optional string`

      The IANA zone the hours are stated in (`America/New_York`). Hours are never configured without it; it may be configured without hours.

  - `capabilities: array of string`

    The device's most recently announced capability tokens. Empty means unknown, never "supports nothing".

  - `consent: unknown`

    Per-category consent for this chat's subject, scoped to the caller's brand (empty when none is recorded).

  - `customer_handle: string`

    The customer identifier: an Apple Opaque ID, or canonical `tel:+E164`, per `handle_kind`.

  - `handle_kind: "opaque" or "tel"`

    Which identifier kind `customer_handle` holds; branch on this, never read the string itself. A `tel` chat is not addressable for sends or typing.

    - `"opaque"`

    - `"tel"`

  - `origin: "customer" or "invitation"`

    How the chat began. Not derivable from `handle_kind`: an accepted invitation arrives under a brand-new opaque id.

    - `"customer"`

    - `"invitation"`

  - `owner: string`

    Turn owner: `partner`, `flow`, `human_pending` or `human`. Sends while not `partner` return HTTP 409 `code` 2011. `flow` is a platform flow holding the turn, typically the survey `/resolve` starts or the question `/clarify` asks: it ends on the customer's answer or its own timeout, and ownership then returns, recorded by `chat.owner_changed`.

  - `owner_since: string`

    When the chat entered its CURRENT owner state: the queue clock, NOT `updated_at` (which any progress bumps). Stamped only when the owner actually changes. One exception, and it is self-clearing: a chat that has not changed owner since the column was deployed reports the deploy time instead, which is a CEILING: deploy time is later than the true entry, so a wait derived from it reads SHORTER than the real one until that chat's next owner move. Don't page on it alone.

  - `send_blocked: object { blocked, code, message }`

    Whether a send would be refused right now, and why; read it BEFORE composing.

    - `blocked: boolean`

    - `code: number`

      The code the send would return, byte-identical to the `error.code` a real send would answer with; `0` when `blocked` is false.

    - `message: string`

      The message the send would return, verbatim; empty when `blocked` is false.

  - `state: string`

    Lifecycle phase: `open` or `closed`. Sends to a closed chat returns HTTP 409 `code` 2010.

  - `updated_at: string`

    Last change of any kind, machine progress included.

  - `assigned_operator: optional string`

    The operator holding this chat; absent when nobody does (the common case).

  - `business_id: optional string`

    The Apple business UUID your brand currently resolves to on this channel: the channel binding of record, present only when one is on file. This is the current binding, not a per-message historical value, so it is the id you can act on today. Distinct from `brand.id`, which is your logical brand on this platform.

  - `capabilities_announced_at: optional string`

    When a device last ANNOUNCED a `capability-list`; NOT when we last heard from them (an inbound carrying no capability header moves `last_inbound_at` and leaves this alone). Absent means no device has ever announced.

  - `capture: optional object { expires_at, group_id, opened_at, page_id }`

    The chat's open reply capture (a degraded form mid-collection), so a takeover desk can warn before ending it: the group id `form.response` will carry, your page id, and the open/expiry instants. Absent when none is open; an expired capture is filtered out here, never closed by a read.

    - `expires_at: string`

    - `group_id: string`

      The degraded fan's correlation id: the primary prompt message's own id.

    - `opened_at: string`

    - `page_id: optional string`

      Your form page's id.

  - `last_inbound_at: optional string`

    When we last heard from the customer; any inbound, a message or a chat close. ABSENT when they have never written (an invitation nobody has answered yet). A typing indicator is not recorded and does not move it; neither does anything the business sends.

### Example

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

#### Response

```json
{
  "id": "chat_4f81b2",
  "state": "open",
  "owner": "partner",
  "capabilities": [
    "TEXT",
    "LIST",
    "TIME",
    "QUICK",
    "FORM"
  ],
  "customer_handle": "urn:mbid:AQAAY7c1",
  "handle_kind": "opaque",
  "origin": "customer",
  "owner_since": "2026-08-06T14:02:11Z",
  "last_inbound_at": "2026-08-06T14:01:58Z",
  "updated_at": "2026-08-06T14:02:11Z",
  "capabilities_announced_at": "2026-08-06T14:01:58Z",
  "consent": {
    "marketing": {
      "state": "granted"
    },
    "account_notification": {
      "state": "granted"
    }
  },
  "brand": {
    "id": "biz_9f2c1a",
    "display_name": "CurbFare"
  },
  "send_blocked": {
    "blocked": false,
    "code": 0,
    "message": ""
  }
}
```
