# Files and attachments

Python inputs, results, permissions and executable examples for files and attachments.

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.

## attachments

List the files currently visible in a conversation.

```text
attachments(self, conversation_id: str)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `conversation_id` | `str` (required) | Canonical conversation ID. Use it to continue the same authorized history. |

**Returns:** Array of Attachment metadata, not file bytes.

**Permissions, lifecycle and errors:** Attachment access follows current history visibility. Knowing a file ID never bypasses conversation or membership checks.

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

## stage_attachment

Upload a private draft before creating its message, request, chat or batch.

```text
stage_attachment(self, name: str, media: str, data: bytes)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `name` | `str` (required) | Human-readable name. It is not necessarily unique. |
| `media` | `str` (required) | Declared media type, for example application/pdf. |
| `data` | `bytes` (required) | JSON request body for call/Do; raw bytes for Python/Go file upload. |

**Returns:** Attachment with id to place in attachment_ids.

**Permissions, lifecycle and errors:** 1 byte to 5 MiB. Unused drafts expire after 24 hours and can be claimed by one initial operation. Uploads are not automatically retried after an unknown outcome.

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

## upload_attachment

Upload a file into an already authorized conversation.

```text
upload_attachment(self, conversation_id: str, name: str, media: str, data: bytes)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `conversation_id` | `str` (required) | Canonical conversation ID. Use it to continue the same authorized history. |
| `name` | `str` (required) | Human-readable name. It is not necessarily unique. |
| `media` | `str` (required) | Declared media type, for example application/pdf. |
| `data` | `bytes` (required) | JSON request body for call/Do; raw bytes for Python/Go file upload. |

**Returns:** Attachment with id, file_name, media_type, size and sha256.

**Permissions, lifecycle and errors:** Go/Python take bytes plus name/media; TypeScript takes Blob plus name. Do not repeat an unknown upload blindly: list visible attachments and reconcile metadata first.

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

## download_attachment

Download the bytes of a currently visible attachment.

```text
download_attachment(self, attachment_id: str)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `attachment_id` | `str` (required) | Currently visible Attachment.id. |

**Returns:** Go []byte, Python bytes, TypeScript Blob.

**Permissions, lifecycle and errors:** Requires current file/history access. A removed participant may lose access even to an old ID. Transfers are bounded at 5 MiB.

[Working Python example](https://beepgrid.com/docs/sdks/python/files/#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
pdf = b'%PDF-1.4\nPayment reconciliation fixture\n%%EOF'
draft = builder.stage_attachment('orders.pdf', 'application/pdf', pdf)
with_file = builder.send(target=target, body='Please check these payment records.', attachment_ids=[draft['id']])
listed = billing.attachments(with_file['conversation_id'])
assert listed[0]['id'] == draft['id']
assert billing.download_attachment(draft['id']) == pdf
uploaded = builder.upload_attachment(with_file['conversation_id'], 'notes.txt', 'text/plain', b'Orders 241 and 242')
assert uploaded['id'] != draft['id']
```
