diff --git a/docs/account.md b/docs/account.md
index 6d7c08b..dae4254 100644
--- a/docs/account.md
+++ b/docs/account.md
@@ -1558,6 +1558,7 @@ Each community contains information about:
- community metadata (name, tags)
- membership status
- number of members
+- every channel in the community, with the account's permissions on it
Returns `list[dict]` where each element represents a community.
@@ -1570,10 +1571,32 @@ Returns `list[dict]` where each element represents a community.
| `tags` | `list[str]` | Tags associated with the community. |
| `is_member` | `bool` | Whether the account is currently a member of the community. |
| `joined` | `bool` | Whether the account has joined the community. |
-| `joined_timestamp` | `datetime.datetime` | Timestamp when the account joined the community. |
-| `requested_timestamp` | `datetime.datetime` | Timestamp when the join request was submitted. |
+| `joined_timestamp` | `datetime.datetime`
`None` | Timestamp when the account joined the community. `None` when the account has not joined. |
+| `requested_timestamp` | `datetime.datetime`
`None` | Timestamp when the join request was submitted. `None` when no request was made. |
| `encrypted` | `bool` | Whether the community messaging is encrypted. |
| `members` | `int` | Total number of community members. |
+| `channels` | `list[dict]` | Every channel in the community. See [channels](./account.md#channels) below. |
+
+##### `channels`
+
+Each entry of `channels` describes one channel and what the account is allowed to do in it.
+
+| Key | Type | Description |
+|----|----|-------------|
+| `id` | `str` | The channel's own id, **without** the community id in front of it. |
+| `chat_id` | `str` | The community id and channel id joined together. **This is the value to pass** to [`send_message`](./account.md#send_messagechat_id-message-reply_to_message_idnone) and [`get_messages`](./account.md#get_messageschat_id-start_timestampnone-end_timestampnone) - `id` on its own will not work. |
+| `name` | `str` | The channel name, as shown in Status App. |
+| `description` | `str` | The channel description. |
+| `permissions` | `dict` | What the account can do in the channel - see below. |
+
+`permissions` holds four booleans:
+
+| Key | Type | Description |
+|----|----|-------------|
+| `posting` | `bool` | Whether the account can send messages to the channel. [`chats`](./account.md#chats) only lists channels where this is `True`. |
+| `viewing` | `bool` | Whether the account can read the channel. |
+| `reactions` | `bool` | Whether the account can post emoji reactions. |
+| `token_gated` | `bool` | Whether access to the channel is gated behind a token. |
```python
from status_sdk import Account
@@ -1588,7 +1611,21 @@ account.login(**params)
for community in account.communities:
print(community["name"], community["members"])
```
-**Note**: To work with a community's channels, members and settings, wrap its `id` in the [`Community`](./community.md) class - for example `Community(account, community["id"])`.
+
+Find every channel the account can post in, without going through [`chats`](./account.md#chats):
+
+```python
+for community in account.communities:
+ for channel in community["channels"]:
+ if not channel["permissions"]["posting"]:
+ continue
+
+ print(f"{community['name']} #{channel['name']}\t{channel['chat_id']}")
+```
+
+**Note**: To work with a community's channels, members and settings, wrap its `id` in the [`Community`](./community.md) class - for example `Community(account, community["id"])`. `communities` is a read-only snapshot: it lists the channels but cannot create, edit or delete them.
+
+**Note**: `joined` currently returns the same value as `verified`, because [`communities`](../status_sdk/account.py#L498) reads `community["verified"]` for both. Use `is_member` to check membership until that is fixed.
#### `chats`
diff --git a/docs/utils.md b/docs/utils.md
index 20deb5d..b5ab807 100644
--- a/docs/utils.md
+++ b/docs/utils.md
@@ -2,7 +2,7 @@

-Helper functions for setting up the Status Backend environment.
+Helper functions for setting up the Status Backend environment, and package level metadata.
## Methods
@@ -95,3 +95,45 @@ sudo chown -R $USER:$USER /path/to/status_sdk
sudo chmod -R a+rw /path/to/status_sdk
```
+## Properties
+
+### `__version__`
+
+The version of the installed `status-sdk` package. Returns `str`, matching the version published on [PyPI](https://pypi.org/project/status-sdk/).
+
+The value is read from the installed package metadata at import time, so it always reflects the version that is actually installed in your environment - not the version of any source checkout you happen to be standing in.
+
+```python
+import status_sdk
+
+print(status_sdk.__version__)
+# 1.1.0
+```
+
+It can also be imported directly:
+
+```python
+from status_sdk import __version__
+
+print(__version__)
+# 1.1.0
+```
+
+Please include it when [reporting an issue](https://github.com/status-im/status-python-sdk/issues), together with the [`status-go`](https://github.com/status-im/status-go) ref you passed to [`launch_docker_container`](./utils.md#launch_docker_containercommitnone-wait_seconds5-platformlinuxamd64) - the two together describe the exact setup a bug happened on:
+
+```python
+import status_sdk
+
+print(f"status-sdk {status_sdk.__version__}")
+```
+
+#### Running from a source
+
+`__version__` falls back to `dev` when the package has no installed metadata to read - which happens if you cloned the repository and imported `status_sdk` from the project folder without installing it. Install the repository in editable mode and the real version is reported again:
+
+```bash
+pip install -e .
+```
+
+Treat `dev` as "not installed" rather than as a real release - it is deliberately lower than every published version, so the `packaging` check above will fail against it.
+
diff --git a/status_sdk/__init__.py b/status_sdk/__init__.py
index 22843d1..e9dd45f 100644
--- a/status_sdk/__init__.py
+++ b/status_sdk/__init__.py
@@ -1,5 +1,13 @@
+from importlib.metadata import PackageNotFoundError, version as _version
+
from .account import Account
from .group_chat import GroupChat
from .community.base import Community
from .utils import launch_docker_container
from . import exceptions
+
+try:
+ __version__ = _version("status-sdk")
+except PackageNotFoundError:
+ # Running from a source checkout that was never installed
+ __version__ = "dev"