> ## Documentation Index
> Fetch the complete documentation index at: https://messages.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Group Chats

> Send and receive messages in iMessage group chats

iMessage group chats are first-class on Messages.dev. They show up in
[`GET /v1/chats`](/docs/api-reference/chats/list-chats) with `is_group: true` and a
populated `participants` array, and you address them by their `cht_...` ID.

<Note>
  Apple does not let third-party software create new group chats. Messages.dev
  syncs group chats that already exist on your line — typically because someone
  added your line to a group, or your line was on the original `addParticipants`
  call from another iMessage client.
</Note>

## Discover group chats

```typescript theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
import { createClient } from "@messages-dev/sdk";

const client = createClient();

const { data: chats } = await client.listChats({ from: "+15551234567" });

const groups = chats.filter((c) => c.isGroup);
for (const g of groups) {
  console.log(g.id, g.name ?? "(unnamed)", g.participants);
}
```

## Send into a group chat

Pass the chat's `cht_...` ID as `to`:

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
  await client.sendMessage({
    from: "+15551234567",
    to: "cht_abc123",
    text: "Hey team!",
  });
  ```

  ```bash curl theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
  curl -X POST "https://api.messages.dev/v1/messages" \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "from": "+15551234567",
      "to": "cht_abc123",
      "text": "Hey team!"
    }'
  ```
</CodeGroup>

Reactions, typing indicators, attachments, audio messages, and replies all
work the same way — anywhere a 1-on-1 endpoint accepts a phone number, it also
accepts a `cht_...` chat ID.

## Contact-first applies to groups too

A group chat must have at least one inbound message before you can send into
it. If you call `POST /v1/messages` against a chat that has only outbound
history (or none at all), you get:

```json theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
{
  "error": {
    "type": "invalid_request_error",
    "code": "contact_has_not_messaged",
    "message": "Cannot send to a chat that has not received an inbound message first.",
    "param": "to"
  }
}
```

In practice this means the chat needs to be a real, two-way conversation —
either a group you were added to, or one you started elsewhere where another
participant has since replied.

## Receive group messages

Inbound group messages flow through the standard `message.received` webhook.
The payload's `chat_id` points to the group, and `sender` identifies the
specific participant who sent it:

```json theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
{
  "event": "message.received",
  "data": {
    "id": "msg_abc123",
    "chat_id": "cht_abc123",
    "sender": "+15559876543",
    "text": "Coffee?",
    "is_from_me": false,
    "is_audio_message": false,
    "attachments": [],
    "sent_at": 1710000000000
  },
  "timestamp": 1710000000123
}
```

To list a group's history or look up participants, use
[`GET /v1/messages?to=cht_...`](/docs/api-reference/messages/list-messages) and
[`GET /v1/chats`](/docs/api-reference/chats/list-chats).
