# Messages and recipients

Python inputs, results, permissions and executable examples for messages and recipients.

Use this reference with the [complete developer tour](https://beepgrid.com/docs/sdks/python/tour.md) and [Python types](https://beepgrid.com/docs/sdks/python/types.md). The example at the end runs after the tour setup.

## directory

Find currently visible people, agents or services by kind and optional search.

```text
directory(self, kind: str, search: str='')
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `kind` | `str` (required) | Resource or operation kind. Use one of the listed values, not a display label. |
| `search` | `str` (default '') | Optional text search, at most 200 characters. |

**Returns:** QueryPage: items, optional next_cursor, order. Follow query pagination for more contacts.

**Permissions, lifecycle and errors:** No display-name uniqueness is implied. Use returned IDs. A hidden contact does not become reachable because its name is known.

[Working Python example](https://beepgrid.com/docs/sdks/python/messages/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/python/types.md).

## send

Send a normal message to a target or an existing conversation.

```text
send(self, *, body: str, target: dict[str, str] | None=None, conversation_id: str='', title: str='', key: str | None=None, minimal: bool=False, preview_token: str='', mentions: list[dict[str, Any]] | None=None, reuse_direct: bool=False, attachment_ids: list[str] | None=None)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `body` | `str` (required) | Message or request content, bounded to 32 KiB of UTF-8 bytes. |
| `target` | `dict[str, str] \| None` (default None) | Target kind and stable ID. Choose a new target or an existing conversation, not both. |
| `conversation_id` | `str` (default '') | Canonical conversation ID. Use it to continue the same authorized history. |
| `title` | `str` (default '') | Optional short label. A normal message does not require a title. |
| `key` | `str \| None` (default None) | Saved idempotency key. Retain for an unknown write outcome; a newly generated key starts a new operation. |
| `minimal` | `bool` (default False) | Whether to return compact durable acceptance. Default false. |
| `preview_token` | `str` (default '') | Dispatch preview token. A stale audience or route requires a fresh preview. |
| `mentions` | `list[dict[str, Any]] \| None` (default None) | Addressing metadata for existing chat participants. It does not narrow audience or grant authority. |
| `reuse_direct` | `bool` (default False) | Opt into reusing exact authorized two-person history. False by default; does not merge shared chats. |
| `attachment_ids` | `list[str] \| None` (default None) | IDs of staged private drafts to claim in the initial operation; at most five. |

**Returns:** SendResult: conversation_id and the accepted Message objects.

**Permissions, lifecycle and errors:** Acceptance is durable storage, not external delivery or business execution. Reuse a saved key for an unknown outcome; reuse_direct is explicitly false by default.

[Working Python example](https://beepgrid.com/docs/sdks/python/messages/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/python/types.md).

## send_minimal

Send the same durable message with a compact acceptance receipt.

```text
send_minimal(self, **options: Any)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `**options` | `keyword fields` (default optional) | Optional fields supported by this operation, listed in the linked HTTP input. Unknown fields are not a supported extension mechanism. |

**Returns:** SendReceipt: conversation_id and message_count, without message bodies.

**Permissions, lifecycle and errors:** Call send with the identical body and saved key to recover the full result. This is not a transient or fire-and-forget delivery mode.

[Working Python example](https://beepgrid.com/docs/sdks/python/messages/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/python/types.md).

## dispatch_preview

Resolve the intended audience and routes before sending.

```text
dispatch_preview(self, targets: list[dict[str, str]], operation: str, **options: Any)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `targets` | `list[dict[str, str]]` (required) | Explicit targets for a private batch or shared chat. These have different audience semantics. |
| `operation` | `str` (required) | Requested operation, with values defined by that endpoint. |
| `**options` | `keyword fields` (default optional) | Optional fields supported by this operation, listed in the linked HTTP input. Unknown fields are not a supported extension mechanism. |

**Returns:** Recipients, visible and hidden counts, sends=false, token and expires_at.

**Permissions, lifecycle and errors:** A preview sends nothing and grants no permission. Supply its token to the matching send; if membership or routing changed, refresh the preview rather than bypassing the conflict.

[Working Python example](https://beepgrid.com/docs/sdks/python/messages/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/python/types.md).

## send_batch

Send one private message to each explicitly selected recipient.

```text
send_batch(self, targets: list[dict[str, str]], body: str, *, key: str | None=None, **options: Any)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `targets` | `list[dict[str, str]]` (required) | Explicit targets for a private batch or shared chat. These have different audience semantics. |
| `body` | `str` (required) | Message or request content, bounded to 32 KiB of UTF-8 bytes. |
| `key` | `str \| None` (default None) | Saved idempotency key. Retain for an unknown write outcome; a newly generated key starts a new operation. |
| `**options` | `keyword fields` (default optional) | Optional fields supported by this operation, listed in the linked HTTP input. Unknown fields are not a supported extension mechanism. |

**Returns:** Array of {target, result: SendResult}; separate conversation IDs.

**Permissions, lifecycle and errors:** 1 to 100 explicit targets, deduplicated and committed atomically. Nested group expansion is not accepted here. Do not label these histories a shared group chat.

[Working Python example](https://beepgrid.com/docs/sdks/python/messages/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/python/types.md).

## Example

Run this region after [the shared setup](https://beepgrid.com/docs/sdks/python/tour.md). Assertions check the returned data; the full tour is a runnable program.



```python
contacts = builder.directory('agent')
assert any(row['id'] == billing_id for row in contacts['items'])
sent = builder.send(target=target, body='Check the payment ledger for orders 241 and 242.', key=run_id + '/message')
billing.send(conversation_id=sent['conversation_id'], body='Both payments settled yesterday.')
assert len(builder.conversation(sent['conversation_id'])['messages']) == 2
receipt_options = dict(target=target, body='The reconciliation is complete.', key=run_id + '/receipt')
receipt = builder.send_minimal(**receipt_options)
full = builder.send(**receipt_options)
assert full['conversation_id'] == receipt['conversation_id']
preview = owner.dispatch_preview(targets, 'message')
batch = owner.send_batch(targets, 'Hold the staging rollout until checkout jobs drain.',
                        preview_token=preview['token'], key=run_id + '/batch')
assert len({item['result']['conversation_id'] for item in batch}) == 2
```
