API Reference · v1

The hosted Skool API.

Skool has no official API. Skooly hosts the hard part — Playwright login, session refresh, CloudFront, cursor pagination, snake_case — behind stable, versioned /v1 routes. You automate your own authenticated Skool account.

Unofficial-API disclaimer

Every route rides a reverse-engineered surface (api2.skool.com + Next.js data). It can change without notice — when Skool drifts we surface skool_shape_changed (502) instead of silent garbage.

Quickstart

Four steps.

  1. Sign up (magic link or Google).
  2. Connect your Skool account in the dashboard.
  3. Mint an API key — it’s shown once.
  4. Make your first call:
curl
# 1. Sign up + connect your Skool account in the dashboard
# 2. Mint a key → sk_live_…
# 3. Call the API
curl https://api.skooly.dev/v1/groups/$GID/posts \
  -H "Authorization: Bearer $SKOOL_API_KEY"
Authentication

One Bearer token.

The Data API is authed with an API key: Authorization: Bearer sk_live_…. A key belongs to your account and carries scopes (posts:read, comments:read, …). If you linked several Skool accounts, target one with the X-Skool-Connectionheader; otherwise the key’s connection (or your single one) is used.

Rotate with POST /v1/keys/:id/rotate — the old key keeps working for a 24h grace window so you can swap without downtime. Revoke instantly with DELETE.

headers
Authorization: Bearer sk_live_xxxxxxxxxxxx
# optionally target a specific linked connection:
X-Skool-Connection: <connectionId>
Rate limits

Per-key, per-tier.

Tierreq/minreq/monthconnections
Free305k1
Pro120100k5
Scale6001M+25

Every response carries X-RateLimit-Limit / -Remaining / -Reset. Over the limit → 429 + Retry-After. A second per-connection throttle protects your underlying Skool account.

Response format

One envelope.

envelope
// success
{ "data": <resource | resource[]>,
  "meta": { "pagination": { "cursor": "abc", "hasMore": true, "truncated": false } } }
 
// error
{ "error": { "code": "session_unavailable", "message": "…", "status": 401 } }

Error codes

unauthorized401API key ausente, inválida o expirada.
session_unavailable401La conexión de Skool expiró o falta. Reconecta la cuenta.
forbidden403La API key no tiene el scope que la ruta exige.
rate_limited429Se superó el límite del tier. Ver Retry-After.
skool_bad_request400/403/404Skool respondió un 4xx duro (passthrough).
skool_upstream_error502Skool falló (5xx/429) tras los reintentos.
skool_shape_changed502La estructura de Skool cambió (respuesta irreconocible).
Resources

The /v1 surface.

Groups

GET/v1/groupsgrupos de la conexión activaImplemented
GET/v1/groups/:gidImplemented
GET/v1/groups/:gid/postsfeed ?pages=NImplemented

Posts

GET/v1/posts/:iddetalle + comentarios · ?group=Implemented
POST/v1/postscrear post — Phase 2Planned
PATCH/v1/posts/:idPlanned
DELETE/v1/posts/:idPlanned
POST/v1/posts/:id/pinPlanned

Comments

GET/v1/posts/:id/commentspaginación por cursor · ?group=Implemented
POST/v1/posts/:id/commentsPhase 2Planned
DELETE/v1/comments/:idPlanned

Members

GET/v1/groups/:gid/membersPlanned
POST/v1/members/:id/(approve|reject|ban)Planned

Courses · Chat · Events · Leaderboard

GET/v1/groups/:gid/coursesPlanned
GET/v1/dmsPlanned
GET/v1/groups/:gid/eventsPlanned
GET/v1/groups/:gid/leaderboardPlanned

Management (web-session authed)

POST/v1/connectionsconectar SkoolImplemented
GET/v1/connectionsImplemented
POST/v1/keysmint · devuelve la key una vezImplemented
POST/v1/keys/:id/rotateImplemented
GET/v1/mewhoami + usoImplemented
SDK

@skoolapi/sdk

Isomorphic, zero-dep, fetch-based. Typed errors mirror the envelope; iterate() auto-paginates. Ships in Phase 3.

TypeScript
import { SkoolClient } from "@skoolapi/sdk";
 
const skool = new SkoolClient({ apiKey: process.env.SKOOL_API_KEY });
 
const { data } = await skool.posts.list(groupId);
for await (const post of skool.posts.iterate(groupId)) {
  // typed errors mirror the envelope's error.code
}
CLI / AI agents

Built for agents.

Every command speaks JSON, with stable exit codes an agent can branch on. An MCP server exposes the same surface to Claude & Codex. Ships in Phase 4.

shell
# --json on every command → one JSON object to stdout
skool posts list $GID --json | jq '.data[].title'
# stable exit codes: 0 ok · 2 auth · 3 rate-limited · 4 upstream · 5 shape-changed