| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A Python client for automating a Skool.com account. It covers community, post, comment, member, and webhook management and ships a small CLI on top.
Skool does not publish a first-party REST API. The options available today are:
| Surface | Auth | Coverage | Stability |
|---|---|---|---|
| Zapier integration (built in to Skool) | per-group API key | triggers + a handful of actions | stable |
| SkoolAPI gateway — https://docs.skoolapi.com (community-built) | x-api-secret header | communities, posts, comments, members, chats, webhooks; expanding | stable, preferred |
| Direct skool.com endpoints (reverse-engineered, browser-style session) | email + password ⇒ cookie / bearer token | essentially everything the web UI does | fragile — internal routes change without notice |
| Apify scrapers | third-party | read-only | scraper-grade, fine for analytics |
skoolapp wraps the middle two options so you can stay on the stable gateway for the 95% case and drop into the direct client only where coverage is missing.
Important: Any automation of a Skool account must comply with Skool's Terms of Service. Use credentials you own or have been given automation rights on, and do not use the direct client to scrape communities you don't belong to.
pip install -e .[dev]Python 3.9+.
from skoolapp import SkoolClient
with SkoolClient(api_secret="sk_live_...") as client:
community = client.communities.get("my-community")
post = client.posts.create(
group=community["id"],
title="Release notes v3",
body="New classroom features shipped today.",
)
for reply in client.comments.list(post["id"], limit=20):
print(reply["author"]["name"], reply["body"])
client.webhooks.create(
group=community["id"],
url="https://example.com/skool/webhook",
events=["post.created", "comment.created", "member.joined"],
)The client reads SKOOLAPI_API_SECRET from the environment by default, so SkoolClient() with no args works once you've exported the secret.
from skoolapp import SkoolDirectClient
with SkoolDirectClient(email="you@example.com", password="...") as client:
client.login()
group = client.get_group("my-community")
for item in client.feed("my-community", sort="new", limit=10):
print(item["title"])
client.create_post(
group="my-community",
title="Live from the direct client",
body="Skool hasn't exposed this yet on the gateway.",
)Every resource is wired into skoolapp:
export SKOOLAPI_API_SECRET=sk_live_...
skoolapp communities list
skoolapp community show my-community
skoolapp posts list --group my-community --limit 5 --sort new
skoolapp post create --group my-community --title "Hi" --body "Hello"
skoolapp members list --group my-community --role admin
skoolapp webhook create \
--group my-community \
--url https://example.com/webhook \
--event post.created --event comment.createdOutput is JSONL for list commands and pretty JSON for single-object commands, so you can pipe it straight into jq.
from skoolapp.webhooks import verify_signature
ok = verify_signature(
payload=request.body,
signature_header=request.headers["X-Skool-Signature"],
secret="whsec_...",
)The header looks like t=<unix>,v1=<hex> and the digest is HMAC-SHA256(secret, f"{t}.{body}"). Signatures older than five minutes are rejected to defang replay attacks.
src/skoolapp/
├── __init__.py # public re-exports
├── client.py # SkoolClient (SkoolAPI gateway, x-api-secret)
├── direct.py # SkoolDirectClient (skool.com session login)
├── transport.py # httpx wrapper: retries, pagination, JSON decode
├── errors.py # SkoolAPIError hierarchy
├── webhooks.py # HMAC signature verification
├── cli.py # `skoolapp` CLI entry point
└── resources/
├── sessions.py # POST /v1/sessions/
├── communities.py # /v1/communities
├── posts.py # /v1/posts
├── comments.py # /v1/posts/{id}/comments (comments are posts!)
├── members.py # /v1/members
└── webhooks.py # /v1/webhooks/
Every resource module is independent — the only shared surface is the Transport, which handles retries (exponential backoff on 429/5xx and network errors), cursor pagination, and JSON decoding into typed exceptions.
pip install -e .[dev]
pytestTests use respx to mock HTTP, so no network access is required.
MIT. See LICENSE.
| Back | FazBrowse Home | New Git URL |