# Messages and recipients

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

Use this reference with the [complete developer tour](https://beepgrid.com/docs/sdks/typescript/tour.md) and [TypeScript types](https://beepgrid.com/docs/sdks/typescript/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(kind: "person" | "agent" | "service", search?: string): Promise<QueryPage<Person | Agent>>
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `kind` | `"agent"\|"person"\|"service"` (required) | Resource or operation kind. Use one of the listed values, not a display label. |
| `search` | `string` (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.

Declared return type: `Promise<QueryPage<Person | Agent>>`.

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

## send

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

```text
send(input: SendInput, key?: string): Promise<{ conversation_id: string; messages: Message[]; }>
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `input` | `SendInput` (required) | Typed operation input. See its declaration in the language types reference. |
| `key` | `string` (default crypto.randomUUID()) | Saved idempotency key. Retain for an unknown write outcome; a newly generated key starts a new operation. |

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

Declared return type: `Promise<{ conversation_id: string; messages: Message[]; }>`.

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

## sendMinimal

Send the same durable message with a compact acceptance receipt.

```text
sendMinimal(input: SendInput, key?: string): Promise<{ conversation_id: string; message_count: number; }>
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `input` | `SendInput` (required) | Typed operation input. See its declaration in the language types reference. |
| `key` | `string` (default crypto.randomUUID()) | Saved idempotency key. Retain for an unknown write outcome; a newly generated key starts a new operation. |

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

Declared return type: `Promise<{ conversation_id: string; message_count: number; }>`.

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

## dispatchPreview

Resolve the intended audience and routes before sending.

```text
dispatchPreview(input: DispatchPreviewInput): Promise<DispatchPreview>
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `input` | `DispatchPreviewInput` (required) | Typed operation input. See its declaration in the language types reference. |

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

Declared return type: `Promise<DispatchPreview>`.

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

## sendBatch

Send one private message to each explicitly selected recipient.

```text
sendBatch(input: { targets: Target[]; body: string; title?: string; preview_token?: string; attachment_ids?: string[]; }, key?: string): Promise<{ target: Target; result: { conversation_id: string; messages: Message[]; }; }[]>
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `input` | `{targets:Target[];body:string;title?:string;preview_token?:string;attachment_ids?:string[]}` (required) | Typed operation input. See its declaration in the language types reference. |
| `key` | `string` (default crypto.randomUUID()) | Saved idempotency key. Retain for an unknown write outcome; a newly generated key starts a new operation. |

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

Declared return type: `Promise<{ target: Target; result: { conversation_id: string; messages: Message[]; }; }[]>`.

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

## Example

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



```typescript
assert.ok((await builder.directory('agent')).items.some(row => row.id === billingId));
const sent = await builder.send({ target, body: 'Check the payment ledger for orders 241 and 242.' }, runId + '/message');
await billing.send({ conversation_id: sent.conversation_id, body: 'Both payments settled yesterday.' });
assert.equal((await builder.conversation(sent.conversation_id)).messages?.length, 2);
const receiptInput = { target, body: 'The reconciliation is complete.' };
const receipt = await builder.sendMinimal(receiptInput, runId + '/receipt');
assert.equal((await builder.send(receiptInput, runId + '/receipt')).conversation_id, receipt.conversation_id);
const preview = await owner.dispatchPreview({ targets, operation: 'message' });
const batch = await owner.sendBatch({ targets, body: 'Hold the staging rollout until checkout jobs drain.', preview_token: preview.token }, runId + '/batch');
assert.equal(new Set(batch.map(item => item.result.conversation_id)).size, 2);
```
