circle-so-python-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- circle_so_python_sdk-0.1.0/.env.example +2 -0
- circle_so_python_sdk-0.1.0/.github/workflows/ci.yml +21 -0
- circle_so_python_sdk-0.1.0/.github/workflows/publish.yml +19 -0
- circle_so_python_sdk-0.1.0/.gitignore +18 -0
- circle_so_python_sdk-0.1.0/CHANGELOG.md +18 -0
- circle_so_python_sdk-0.1.0/LICENSE +21 -0
- circle_so_python_sdk-0.1.0/PKG-INFO +120 -0
- circle_so_python_sdk-0.1.0/README.md +90 -0
- circle_so_python_sdk-0.1.0/docs/admin-api.md +98 -0
- circle_so_python_sdk-0.1.0/docs/auth-api.md +38 -0
- circle_so_python_sdk-0.1.0/docs/headless-api.md +103 -0
- circle_so_python_sdk-0.1.0/docs/models.md +40 -0
- circle_so_python_sdk-0.1.0/docs/quickstart.md +75 -0
- circle_so_python_sdk-0.1.0/docs/webhooks.md +26 -0
- circle_so_python_sdk-0.1.0/pyproject.toml +55 -0
- circle_so_python_sdk-0.1.0/src/circle/__init__.py +24 -0
- circle_so_python_sdk-0.1.0/src/circle/api/__init__.py +1 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_access_groups.py +133 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_community.py +122 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_courses.py +172 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_events.py +101 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_misc.py +305 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_posts.py +200 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_spaces.py +301 -0
- circle_so_python_sdk-0.1.0/src/circle/api/admin_tags.py +146 -0
- circle_so_python_sdk-0.1.0/src/circle/api/auth.py +63 -0
- circle_so_python_sdk-0.1.0/src/circle/api/headless_chat_notif_members.py +323 -0
- circle_so_python_sdk-0.1.0/src/circle/api/headless_misc.py +218 -0
- circle_so_python_sdk-0.1.0/src/circle/api/headless_spaces_posts.py +279 -0
- circle_so_python_sdk-0.1.0/src/circle/client.py +197 -0
- circle_so_python_sdk-0.1.0/src/circle/constants.py +5 -0
- circle_so_python_sdk-0.1.0/src/circle/exceptions.py +34 -0
- circle_so_python_sdk-0.1.0/src/circle/http.py +227 -0
- circle_so_python_sdk-0.1.0/src/circle/models/__init__.py +5 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/__init__.py +47 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/community.py +82 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/courses.py +30 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/events.py +67 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/members.py +105 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/misc.py +240 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/posts.py +172 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/spaces.py +146 -0
- circle_so_python_sdk-0.1.0/src/circle/models/admin/tags.py +85 -0
- circle_so_python_sdk-0.1.0/src/circle/models/auth.py +21 -0
- circle_so_python_sdk-0.1.0/src/circle/models/base.py +28 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/__init__.py +50 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/chat.py +134 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/comments.py +60 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/courses.py +109 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/members.py +105 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/misc.py +120 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/notifications.py +66 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/posts.py +137 -0
- circle_so_python_sdk-0.1.0/src/circle/models/headless/spaces.py +80 -0
- circle_so_python_sdk-0.1.0/src/circle/pagination.py +116 -0
- circle_so_python_sdk-0.1.0/src/circle/py.typed +1 -0
- circle_so_python_sdk-0.1.0/src/circle/rate_limit.py +36 -0
- circle_so_python_sdk-0.1.0/src/circle/validation.py +67 -0
- circle_so_python_sdk-0.1.0/src/circle/webhooks.py +39 -0
- circle_so_python_sdk-0.1.0/tests/__init__.py +0 -0
- circle_so_python_sdk-0.1.0/tests/conftest.py +70 -0
- circle_so_python_sdk-0.1.0/tests/integration/__init__.py +0 -0
- circle_so_python_sdk-0.1.0/tests/integration/conftest.py +21 -0
- circle_so_python_sdk-0.1.0/tests/integration/test_smoke.py +22 -0
- circle_so_python_sdk-0.1.0/tests/test_admin.py +229 -0
- circle_so_python_sdk-0.1.0/tests/test_audit.py +150 -0
- circle_so_python_sdk-0.1.0/tests/test_auth.py +70 -0
- circle_so_python_sdk-0.1.0/tests/test_client.py +92 -0
- circle_so_python_sdk-0.1.0/tests/test_coverage_expansion.py +255 -0
- circle_so_python_sdk-0.1.0/tests/test_headless.py +170 -0
- circle_so_python_sdk-0.1.0/tests/test_http.py +93 -0
- circle_so_python_sdk-0.1.0/tests/test_models.py +171 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- run: pip install -e .[dev]
|
|
21
|
+
- run: pytest tests/ -v --ignore=tests/integration
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write # trusted publishing
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-python@v5
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
- run: pip install build
|
|
18
|
+
- run: python -m build
|
|
19
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-03-14)
|
|
4
|
+
|
|
5
|
+
Initial release covering all three Circle.so APIs:
|
|
6
|
+
|
|
7
|
+
- Headless Auth API (4 endpoints)
|
|
8
|
+
- Admin API V2 (~118 endpoints)
|
|
9
|
+
- Headless Client API V1 (~101 endpoints)
|
|
10
|
+
|
|
11
|
+
Features:
|
|
12
|
+
- Sync and async clients via httpx
|
|
13
|
+
- Pydantic V2 models for all API responses
|
|
14
|
+
- Typed exceptions (AuthenticationError, NotFoundError, ValidationError, ForbiddenError, RateLimitError)
|
|
15
|
+
- Auto-retry with exponential backoff and Retry-After support
|
|
16
|
+
- Auto-pagination helpers (page-based and search_after cursor-based)
|
|
17
|
+
- Context manager support
|
|
18
|
+
- py.typed marker for PEP 561 compliance
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 boiyelove
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: circle-so-python-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Circle.so - Admin V2, Headless Auth, and Headless Client V1 APIs
|
|
5
|
+
Project-URL: Homepage, https://github.com/boiyelove/circle-so-python-sdk
|
|
6
|
+
Project-URL: Documentation, https://github.com/boiyelove/circle-so-python-sdk/tree/main/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/boiyelove/circle-so-python-sdk
|
|
8
|
+
Author: Damilola Afolabi
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: api,circle,circle.so,community,sdk
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Requires-Dist: httpx>=0.24.0
|
|
24
|
+
Requires-Dist: pydantic>=2.0.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# circle-so-python-sdk
|
|
32
|
+
|
|
33
|
+
[](https://github.com/boiyelove/circle-so-python-sdk/actions/workflows/ci.yml)
|
|
34
|
+
|
|
35
|
+
Python SDK for [Circle.so](https://circle.so) covering three APIs:
|
|
36
|
+
|
|
37
|
+
- Headless Auth API -- token management for headless integrations
|
|
38
|
+
- Admin API V2 -- server-side community management (~120 endpoints)
|
|
39
|
+
- Headless Client API V1 -- member-facing operations (~100 endpoints)
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install circle-so-python-sdk
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from circle import CircleClient
|
|
51
|
+
|
|
52
|
+
# Admin API usage
|
|
53
|
+
client = CircleClient(api_token="YOUR_ADMIN_TOKEN")
|
|
54
|
+
community = client.admin.get_community()
|
|
55
|
+
|
|
56
|
+
# Headless Auth -- get member tokens
|
|
57
|
+
token = client.auth.create_auth_token(email="member@example.com")
|
|
58
|
+
|
|
59
|
+
# Headless Client -- use member access token
|
|
60
|
+
headless = CircleClient(api_token=token.access_token, community_url="https://your-community.circle.so")
|
|
61
|
+
spaces = headless.headless.list_spaces()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Async Support
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from circle import AsyncCircleClient
|
|
68
|
+
|
|
69
|
+
async with AsyncCircleClient(api_token="YOUR_TOKEN") as client:
|
|
70
|
+
members = await client.admin.list_community_members()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API Coverage
|
|
74
|
+
|
|
75
|
+
| API | Endpoints | Sync | Async |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| Headless Auth | 4 | Yes | Yes |
|
|
78
|
+
| Admin V2 | ~118 | Yes | Yes |
|
|
79
|
+
| Headless Client V1 | ~101 | Yes | Yes |
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
- [Quickstart](docs/quickstart.md) -- install, auth, basic usage
|
|
84
|
+
- [Admin API](docs/admin-api.md) -- all admin endpoints with examples
|
|
85
|
+
- [Headless API](docs/headless-api.md) -- all headless endpoints with examples
|
|
86
|
+
- [Auth API](docs/auth-api.md) -- headless auth token management
|
|
87
|
+
- [Models](docs/models.md) -- complete models reference
|
|
88
|
+
- [Webhooks](docs/webhooks.md) -- signature verification and payload parsing
|
|
89
|
+
|
|
90
|
+
## Project Structure
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
src/circle/
|
|
94
|
+
__init__.py # Public API exports
|
|
95
|
+
client.py # CircleClient / AsyncCircleClient facade
|
|
96
|
+
http.py # Sync/Async HTTP transport with retry
|
|
97
|
+
exceptions.py # Typed exceptions (401/403/404/422/429)
|
|
98
|
+
pagination.py # Auto-pagination helpers
|
|
99
|
+
rate_limit.py # Token bucket rate limiter
|
|
100
|
+
validation.py # Request body validation models
|
|
101
|
+
webhooks.py # Webhook signature verification
|
|
102
|
+
models/
|
|
103
|
+
auth.py # HeadlessAuthToken, RefreshedAccessToken
|
|
104
|
+
admin/ # ~35 Pydantic models for Admin API
|
|
105
|
+
headless/ # ~40 Pydantic models for Headless API
|
|
106
|
+
api/
|
|
107
|
+
auth.py # Headless Auth client (4 endpoints)
|
|
108
|
+
admin_*.py # 8 Admin API client modules
|
|
109
|
+
headless_*.py # 3 Headless API client modules
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Contributing
|
|
113
|
+
|
|
114
|
+
1. Clone the repo and install in dev mode: `pip install -e .[dev]`
|
|
115
|
+
2. Run tests: `pytest tests/ -v --ignore=tests/integration`
|
|
116
|
+
3. Follow conventional commit format for commit messages
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# circle-so-python-sdk
|
|
2
|
+
|
|
3
|
+
[](https://github.com/boiyelove/circle-so-python-sdk/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
Python SDK for [Circle.so](https://circle.so) covering three APIs:
|
|
6
|
+
|
|
7
|
+
- Headless Auth API -- token management for headless integrations
|
|
8
|
+
- Admin API V2 -- server-side community management (~120 endpoints)
|
|
9
|
+
- Headless Client API V1 -- member-facing operations (~100 endpoints)
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install circle-so-python-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from circle import CircleClient
|
|
21
|
+
|
|
22
|
+
# Admin API usage
|
|
23
|
+
client = CircleClient(api_token="YOUR_ADMIN_TOKEN")
|
|
24
|
+
community = client.admin.get_community()
|
|
25
|
+
|
|
26
|
+
# Headless Auth -- get member tokens
|
|
27
|
+
token = client.auth.create_auth_token(email="member@example.com")
|
|
28
|
+
|
|
29
|
+
# Headless Client -- use member access token
|
|
30
|
+
headless = CircleClient(api_token=token.access_token, community_url="https://your-community.circle.so")
|
|
31
|
+
spaces = headless.headless.list_spaces()
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Async Support
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from circle import AsyncCircleClient
|
|
38
|
+
|
|
39
|
+
async with AsyncCircleClient(api_token="YOUR_TOKEN") as client:
|
|
40
|
+
members = await client.admin.list_community_members()
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## API Coverage
|
|
44
|
+
|
|
45
|
+
| API | Endpoints | Sync | Async |
|
|
46
|
+
|---|---|---|---|
|
|
47
|
+
| Headless Auth | 4 | Yes | Yes |
|
|
48
|
+
| Admin V2 | ~118 | Yes | Yes |
|
|
49
|
+
| Headless Client V1 | ~101 | Yes | Yes |
|
|
50
|
+
|
|
51
|
+
## Documentation
|
|
52
|
+
|
|
53
|
+
- [Quickstart](docs/quickstart.md) -- install, auth, basic usage
|
|
54
|
+
- [Admin API](docs/admin-api.md) -- all admin endpoints with examples
|
|
55
|
+
- [Headless API](docs/headless-api.md) -- all headless endpoints with examples
|
|
56
|
+
- [Auth API](docs/auth-api.md) -- headless auth token management
|
|
57
|
+
- [Models](docs/models.md) -- complete models reference
|
|
58
|
+
- [Webhooks](docs/webhooks.md) -- signature verification and payload parsing
|
|
59
|
+
|
|
60
|
+
## Project Structure
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
src/circle/
|
|
64
|
+
__init__.py # Public API exports
|
|
65
|
+
client.py # CircleClient / AsyncCircleClient facade
|
|
66
|
+
http.py # Sync/Async HTTP transport with retry
|
|
67
|
+
exceptions.py # Typed exceptions (401/403/404/422/429)
|
|
68
|
+
pagination.py # Auto-pagination helpers
|
|
69
|
+
rate_limit.py # Token bucket rate limiter
|
|
70
|
+
validation.py # Request body validation models
|
|
71
|
+
webhooks.py # Webhook signature verification
|
|
72
|
+
models/
|
|
73
|
+
auth.py # HeadlessAuthToken, RefreshedAccessToken
|
|
74
|
+
admin/ # ~35 Pydantic models for Admin API
|
|
75
|
+
headless/ # ~40 Pydantic models for Headless API
|
|
76
|
+
api/
|
|
77
|
+
auth.py # Headless Auth client (4 endpoints)
|
|
78
|
+
admin_*.py # 8 Admin API client modules
|
|
79
|
+
headless_*.py # 3 Headless API client modules
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Contributing
|
|
83
|
+
|
|
84
|
+
1. Clone the repo and install in dev mode: `pip install -e .[dev]`
|
|
85
|
+
2. Run tests: `pytest tests/ -v --ignore=tests/integration`
|
|
86
|
+
3. Follow conventional commit format for commit messages
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Admin API V2
|
|
2
|
+
|
|
3
|
+
Server-side community management. All methods available under `client.admin.*`.
|
|
4
|
+
|
|
5
|
+
## Sub-clients
|
|
6
|
+
|
|
7
|
+
| Namespace | Description |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `client.admin.community` | Community settings, member CRUD |
|
|
10
|
+
| `client.admin.access_groups` | Access groups and their members |
|
|
11
|
+
| `client.admin.spaces` | Spaces, space groups, space members |
|
|
12
|
+
| `client.admin.posts` | Posts, comments, topics |
|
|
13
|
+
| `client.admin.events` | Events and attendees |
|
|
14
|
+
| `client.admin.courses` | Course sections, lessons, progress |
|
|
15
|
+
| `client.admin.tags` | Member tags, tagged members, profile fields |
|
|
16
|
+
| `client.admin.misc` | Forms, segments, invitations, embeds, uploads, search, leaderboard, flagged content, live rooms |
|
|
17
|
+
|
|
18
|
+
## Community
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
community = client.admin.get_community()
|
|
22
|
+
updated = client.admin.community.update_community(name="New Name")
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Community Members
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
members = client.admin.community.list_community_members(page=1, per_page=20)
|
|
29
|
+
member = client.admin.community.show_community_member(123)
|
|
30
|
+
created = client.admin.community.create_community_member(email="new@example.com", name="New User")
|
|
31
|
+
client.admin.community.update_community_member(123, headline="Updated")
|
|
32
|
+
client.admin.community.deactivate_community_member(123)
|
|
33
|
+
found = client.admin.community.search_community_member(email="user@example.com")
|
|
34
|
+
client.admin.community.ban_community_member(123)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Spaces
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
spaces = client.admin.spaces.list_spaces(per_page=30)
|
|
41
|
+
space = client.admin.spaces.show_space(1)
|
|
42
|
+
new_space = client.admin.spaces.create_space(name="My Space", slug="my-space", space_group_id=1, space_type="basic")
|
|
43
|
+
client.admin.spaces.update_space(1, name="Renamed")
|
|
44
|
+
client.admin.spaces.delete_space(1)
|
|
45
|
+
summary = client.admin.spaces.get_space_ai_summary(1)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Space Groups
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
groups = client.admin.spaces.list_space_groups()
|
|
52
|
+
group = client.admin.spaces.create_space_group(name="VIP", slug="vip")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Posts
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
posts = client.admin.posts.list_posts(space_id=1)
|
|
59
|
+
created = client.admin.posts.create_post(space_id=1, name="Hello", body="World")
|
|
60
|
+
post = client.admin.posts.show_post(42)
|
|
61
|
+
client.admin.posts.update_post(42, name="Updated Title")
|
|
62
|
+
client.admin.posts.delete_post(42)
|
|
63
|
+
summary = client.admin.posts.get_post_summary(42)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Events
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
events = client.admin.events.list_events(space_id=2)
|
|
70
|
+
event = client.admin.events.create_event(space_id=2, name="Meetup", status="published",
|
|
71
|
+
event_setting_attributes={"starts_at": "2024-06-15T09:00:00Z", "location_type": "virtual"})
|
|
72
|
+
attendees = client.admin.events.list_event_attendees(event_id=1)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Courses
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
sections = client.admin.courses.list_course_sections(space_id=3)
|
|
79
|
+
lesson = client.admin.courses.create_course_lesson(name="Intro", section_id=1)
|
|
80
|
+
client.admin.courses.update_course_lesson_progress(lesson_id=1, member_email="user@example.com", status="completed")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Tags
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
tags = client.admin.tags.list_member_tags()
|
|
87
|
+
tag = client.admin.tags.create_member_tag(name="VIP", color="#FF0000")
|
|
88
|
+
client.admin.tags.create_tagged_member(member_tag_id=1, user_email="user@example.com")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Forms, Segments, and More
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
forms = client.admin.misc.list_forms()
|
|
95
|
+
segments = client.admin.misc.list_community_segments()
|
|
96
|
+
results = client.admin.misc.advanced_search(query="python")
|
|
97
|
+
leaderboard = client.admin.misc.get_leaderboard()
|
|
98
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Headless Auth API
|
|
2
|
+
|
|
3
|
+
Token management for headless integrations. Uses your admin API token to generate member access tokens.
|
|
4
|
+
|
|
5
|
+
## Endpoints
|
|
6
|
+
|
|
7
|
+
### Create Auth Token
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
token = client.auth.create_auth_token(email="member@example.com")
|
|
11
|
+
# or by SSO user ID
|
|
12
|
+
token = client.auth.create_auth_token(sso_user_id="abc123")
|
|
13
|
+
# or by community member ID
|
|
14
|
+
token = client.auth.create_auth_token(community_member_id=42)
|
|
15
|
+
|
|
16
|
+
print(token.access_token)
|
|
17
|
+
print(token.refresh_token)
|
|
18
|
+
print(token.community_member_id)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Refresh Access Token
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
refreshed = client.auth.refresh_access_token(refresh_token="...")
|
|
25
|
+
print(refreshed.access_token)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Revoke Access Token
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
client.auth.revoke_access_token(access_token="...")
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Revoke Refresh Token
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
client.auth.revoke_refresh_token(refresh_token="...")
|
|
38
|
+
```
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Headless Client API V1
|
|
2
|
+
|
|
3
|
+
Member-facing operations. Requires a member access token from the Headless Auth API.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from circle import CircleClient
|
|
9
|
+
|
|
10
|
+
# Get member token first
|
|
11
|
+
admin = CircleClient(api_token="ADMIN_TOKEN")
|
|
12
|
+
token = admin.auth.create_auth_token(email="member@example.com")
|
|
13
|
+
|
|
14
|
+
# Create headless client with member token
|
|
15
|
+
client = CircleClient(api_token=token.access_token, community_url="https://your.circle.so")
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Sub-clients
|
|
19
|
+
|
|
20
|
+
| Namespace | Description |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `client.headless.spaces_posts` | Spaces, posts, comments, replies, likes |
|
|
23
|
+
| `client.headless.chat_notif_members` | Chat, notifications, members, events |
|
|
24
|
+
| `client.headless.misc` | Courses, search, bookmarks, uploads, notification prefs |
|
|
25
|
+
|
|
26
|
+
## Spaces
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
spaces = client.headless.list_spaces()
|
|
30
|
+
space = client.headless.spaces_posts.get_space(1)
|
|
31
|
+
client.headless.spaces_posts.join_space(1)
|
|
32
|
+
client.headless.spaces_posts.leave_space(1)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Posts
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
posts = client.headless.list_posts(1, per_page=20)
|
|
39
|
+
post = client.headless.spaces_posts.get_post(1, 42)
|
|
40
|
+
new_post = client.headless.spaces_posts.create_post(1, name="My Post", body="Content")
|
|
41
|
+
client.headless.spaces_posts.like_post(42)
|
|
42
|
+
client.headless.spaces_posts.follow_post(42)
|
|
43
|
+
home = client.headless.spaces_posts.get_home_posts()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Comments and Replies
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
comments = client.headless.spaces_posts.list_comments(42)
|
|
50
|
+
comment = client.headless.spaces_posts.create_comment(42, body="Nice post!")
|
|
51
|
+
replies = client.headless.spaces_posts.list_replies(comment.id)
|
|
52
|
+
client.headless.spaces_posts.create_reply(comment.id, body="Thanks!")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Chat
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
rooms = client.headless.chat_notif_members.list_chat_rooms()
|
|
59
|
+
room = client.headless.chat_notif_members.create_chat_room(kind="direct", community_member_ids=["2"])
|
|
60
|
+
messages = client.headless.chat_notif_members.list_chat_messages("room-uuid")
|
|
61
|
+
client.headless.chat_notif_members.create_chat_message("room-uuid", rich_text_body={...})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Notifications
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
notifs = client.headless.chat_notif_members.list_notifications()
|
|
68
|
+
client.headless.chat_notif_members.mark_notification_read(1)
|
|
69
|
+
client.headless.chat_notif_members.mark_all_notifications_read()
|
|
70
|
+
count = client.headless.chat_notif_members.get_new_notifications_count()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Members
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
members = client.headless.chat_notif_members.list_community_members()
|
|
77
|
+
me = client.headless.chat_notif_members.get_current_member()
|
|
78
|
+
profile = client.headless.chat_notif_members.get_public_profile(2)
|
|
79
|
+
client.headless.chat_notif_members.update_profile(headline="New headline")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Courses
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
sections = client.headless.misc.list_course_sections(course_id=1)
|
|
86
|
+
lesson = client.headless.misc.get_lesson(course_id=1, lesson_id=2)
|
|
87
|
+
client.headless.misc.update_lesson_progress(1, 2, status="completed")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Search
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
results = client.headless.misc.search(search_text="python")
|
|
94
|
+
advanced = client.headless.misc.advanced_search(query="python", type="posts")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Bookmarks
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
bookmarks = client.headless.misc.list_bookmarks()
|
|
101
|
+
bm = client.headless.misc.create_bookmark(record_id=42, bookmark_type="post")
|
|
102
|
+
client.headless.misc.delete_bookmark(bm.id)
|
|
103
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Models Reference
|
|
2
|
+
|
|
3
|
+
All response models use Pydantic V2 with `extra="allow"` so new API fields won't break the SDK.
|
|
4
|
+
|
|
5
|
+
## Base
|
|
6
|
+
|
|
7
|
+
- `CircleModel` -- base for all models, allows extra fields
|
|
8
|
+
- `PaginatedResponse[T]` -- generic paginated list with `page`, `per_page`, `has_next_page`, `count`, `records`
|
|
9
|
+
- `ErrorResponse` -- `success`, `message`, `error_details`
|
|
10
|
+
|
|
11
|
+
## Auth Models (`circle.models.auth`)
|
|
12
|
+
|
|
13
|
+
- `HeadlessAuthToken` -- `access_token`, `refresh_token`, expiry timestamps, `community_member_id`, `community_id`
|
|
14
|
+
- `RefreshedAccessToken` -- `access_token`, `access_token_expires_at`
|
|
15
|
+
|
|
16
|
+
## Admin Models (`circle.models.admin`)
|
|
17
|
+
|
|
18
|
+
| Module | Key Models |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `community` | `Community`, `CommunitySetting`, `CommunityPrefs`, `ChatPreferences` |
|
|
21
|
+
| `members` | `CommunityMember`, `CommunityMemberList`, `CommunityMemberCreated` |
|
|
22
|
+
| `spaces` | `Space`, `SpaceGroup`, `SpaceMember`, `SpaceGroupMember`, `SpaceAISummary` |
|
|
23
|
+
| `posts` | `BasicPost`, `ImagePost`, `Comment`, `Topic` + created/updated/deleted responses |
|
|
24
|
+
| `events` | `Event`, `EventAttendee` |
|
|
25
|
+
| `courses` | `CourseSection`, `CourseLesson` |
|
|
26
|
+
| `tags` | `MemberTag`, `TaggedMember`, `ProfileField` |
|
|
27
|
+
| `misc` | `AccessGroup`, `Form`, `FormSubmission`, `CommunitySegment`, `InvitationLink`, `Embed`, `DirectUpload`, `LiveRoom`, `FlaggedContent`, `LeaderboardMember`, `AdvancedSearchResults` |
|
|
28
|
+
|
|
29
|
+
## Headless Models (`circle.models.headless`)
|
|
30
|
+
|
|
31
|
+
| Module | Key Models |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `spaces` | `HeadlessSpace`, `SpaceNotificationDetail`, `SpaceBookmark` |
|
|
34
|
+
| `posts` | `HeadlessPost`, `HeadlessImagePost`, `HeadlessEventPost`, `SharedCommunityMember` |
|
|
35
|
+
| `comments` | `HeadlessComment`, `UserLike` |
|
|
36
|
+
| `chat` | `ChatRoom`, `ChatRoomMessage`, `ChatRoomMessages`, `ChatThread`, `ChatRoomParticipant` |
|
|
37
|
+
| `notifications` | `Notification`, `NewNotificationsCount`, `MediumNotificationPreferences` |
|
|
38
|
+
| `members` | `CurrentCommunityMember`, `PublicProfile`, `BasicCommunityMember`, `SearchedMember` |
|
|
39
|
+
| `courses` | `Section`, `Lesson`, `LessonFile`, `QuizAttempt` |
|
|
40
|
+
| `misc` | `Bookmark`, `HeadlessEventAttendee`, `RecurringEvent`, `SearchResults`, `CommunityLink`, `HeadlessDirectUpload` |
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Quickstart
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install circle-so-python-sdk
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Authentication
|
|
10
|
+
|
|
11
|
+
Circle.so uses different auth schemes per API:
|
|
12
|
+
|
|
13
|
+
- Admin API V2: Uses `Token AUTH_TOKEN` header (server-side admin token)
|
|
14
|
+
- Headless Auth: Uses `Bearer AUTH_TOKEN` header (admin token to generate member tokens)
|
|
15
|
+
- Headless Client V1: Uses `Bearer ACCESS_TOKEN` header (member access token)
|
|
16
|
+
|
|
17
|
+
## Basic Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from circle import CircleClient
|
|
21
|
+
|
|
22
|
+
# Create client with your admin API token
|
|
23
|
+
client = CircleClient(api_token="YOUR_ADMIN_TOKEN")
|
|
24
|
+
|
|
25
|
+
# Admin API -- manage your community
|
|
26
|
+
community = client.admin.get_community()
|
|
27
|
+
members = client.admin.list_community_members(per_page=20)
|
|
28
|
+
|
|
29
|
+
# Headless Auth -- get a member access token
|
|
30
|
+
token = client.auth.create_auth_token(email="member@example.com")
|
|
31
|
+
|
|
32
|
+
# Headless Client -- act as a member
|
|
33
|
+
member_client = CircleClient(
|
|
34
|
+
api_token=token.access_token,
|
|
35
|
+
community_url="https://your-community.circle.so"
|
|
36
|
+
)
|
|
37
|
+
spaces = member_client.headless.list_spaces()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Async Usage
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from circle import AsyncCircleClient
|
|
44
|
+
|
|
45
|
+
async with AsyncCircleClient(api_token="YOUR_TOKEN") as client:
|
|
46
|
+
community = await client.admin.get_community()
|
|
47
|
+
members = await client.admin.list_community_members()
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Auto-Pagination
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from circle import CircleClient
|
|
54
|
+
from circle.pagination import paginate
|
|
55
|
+
|
|
56
|
+
client = CircleClient(api_token="YOUR_TOKEN")
|
|
57
|
+
|
|
58
|
+
# Iterate all members across all pages
|
|
59
|
+
for member in paginate(client.admin.community.list_community_members, per_page=100):
|
|
60
|
+
print(member.name)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Error Handling
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from circle import CircleClient, AuthenticationError, NotFoundError
|
|
67
|
+
|
|
68
|
+
client = CircleClient(api_token="YOUR_TOKEN")
|
|
69
|
+
try:
|
|
70
|
+
member = client.admin.community.show_community_member(99999)
|
|
71
|
+
except NotFoundError as e:
|
|
72
|
+
print(f"Not found: {e}")
|
|
73
|
+
except AuthenticationError as e:
|
|
74
|
+
print(f"Auth failed: {e}")
|
|
75
|
+
```
|