An honest API for creators.
Most creator platforms either don't ship an API or hide it behind a sales call. Ours is right here: scoped tokens, transparent rate limits, versioned endpoints, and docs you can ctrl-F through. Generate a key in your dashboard and you're integrating in five minutes.
What you get
Scoped bearer tokens
Every key is scoped: read:courses, read:students, write:enrollments, etc. Grant only what the integration needs. Revocable anytime, no support ticket.
Predictable rate limits
60 req/min, 1,000 req/day per key on every tier. Every response carries X-RateLimit-* headers so your client can throttle proactively.
Versioned + stable
All endpoints live under /api/v1/. Breaking changes ship under /v2 with a 6-month deprecation window for v1. You won't wake up to a broken integration.
Standard envelopes
Lists return { data, pagination }. Errors return { error: { code, message } }. Cursors not page numbers. JSON only — no XML legacy.
Open source on the wedge
Our data-export tooling, webhook receivers, and these endpoint contracts are MIT-licensed. Fork the contract; you don't have to fork the platform.
One-time secret reveal
The full secret is shown exactly once on creation — same pattern Stripe and GitHub use. We never store plaintext; lose it and you revoke + reissue.
Quickstart
- 1
Generate a key
Open /dashboard/developer in your workspace and click New API key. Pick scopes, name the key, hit Generate. Copy the secret immediately — you only see it once. - 2
Make your first call
Pass the key as a bearer token. Example:curl https://thebigclass.com/api/v1/courses \ -H "Authorization: Bearer tbc_YOUR_SECRET_HERE"
- 3
Read the rate-limit headers
Every response includesX-RateLimit-RemainingandX-RateLimit-Reset. Back off when you see < 5 remaining; otherwise you'll trip a 429 with aRetry-Afterheader. - 4
Production checklist
Store secrets in a real secret manager (1Password, Vault, AWS SM). Rotate every 90 days. Never embed a key in client-side bundles or mobile apps — those should proxy through your backend, which holds the key.
Endpoints
Every endpoint enforces its listed scope. Methods are case-sensitive.
| Method | Path | Scope | Status |
|---|---|---|---|
| GET | /api/v1/coursesList published courses with pagination. | read:courses | Live |
| GET | /api/v1/courses/{id}Fetch a single course, including modules + lessons metadata. | read:courses | Live |
| GET | /api/v1/studentsList students with progress + enrolment history. | read:students | Live |
| POST | /api/v1/studentsCreate a student. Used by external CRMs syncing leads. | write:students | Live |
| GET | /api/v1/ordersReceipt + entitlement history for analytics dashboards. | read:orders | Live |
| POST | /api/v1/enrollmentsEnrol a student in a course. Idempotent on (studentId, courseId). | write:enrollments | Live |
| GET | /api/v1/analytics/summaryAggregate revenue + completion metrics over a window. | read:analytics | Live |
Webhooks
We POST a signed JSON payload to your URL every time something happens in your workspace — student created, order paid, recording ready, etc. Subscribe in /dashboard/developer/webhooks.
Pick the events you care about, paste your URL, get a signing secret. Every delivery carries an X-TBC-Signature HMAC-SHA256 header we recommend you verify.
Events
student.createdstudent.updatedstudent.deletedenrollment.createdenrollment.revokedorder.paidorder.refundedcourse.publishedcourse.archivedlive_session.startedlive_session.endedrecording.readycertificate.issued
Delivery guarantees
- · At-least-once. Same event id may arrive twice — dedupe on the
idfield. - · Retries with exponential backoff (1m → 5m → 30m → 2h → 6h → 24h) for 5xx + network errors.
- · Delivery log retained for 30 days at /dashboard/developer/webhooks.
- · Endpoints failing for 7 consecutive days are auto-disabled; you get an email.
POST https://your-app.com/webhooks/tbc HTTP/1.1
Content-Type: application/json
X-TBC-Signature: t=1716102400,v1=8a92…
X-TBC-Event: order.paid
X-TBC-Delivery: evd_2k9f…
{
"id": "evt_01HXYZ…",
"type": "order.paid",
"created_at": "2026-05-19T14:23:14Z",
"workspace_id": "org_…",
"data": { /* order object */ }
}A few things creators build with these events:
- CRM sync. Subscribe to
student.createdandenrollment.created— every new student is auto-pushed to HubSpot / Zoho / a Google Sheet, with their course list tagged. - Slack / Discord pings. Subscribe to
order.paid— your team gets a Slack message every time someone buys, including the product name and customer email. - Accounting export. Subscribe to
order.paid+order.refunded— your bookkeeping tool (Tally / QuickBooks / Zoho Books) gets each transaction with gross / gateway-fee / net columns pre-split. - Auto-issue downloads. Subscribe to
order.paidfor a digital product — your serverless function generates a watermarked PDF and emails it to the buyer in seconds. - Recording archival. Subscribe to
recording.ready— when a live class finishes, your script copies the file to your own S3 bucket for long-term storage.
Webhooks are the right tool when you need to react in near-real-time. For batch / periodic sync, prefer the REST API above with cursor pagination.
Verifying our signature (Node.js example)
import crypto from 'crypto'
const SECRET = process.env.TBC_WEBHOOK_SECRET!
app.post('/webhooks/tbc', express.raw({ type: '*/*' }), (req, res) => {
const sig = req.header('X-TBC-Signature') || ''
// X-TBC-Signature: t=<unix>,v1=<hex>
const parts = Object.fromEntries(sig.split(',').map(p => p.split('=')))
const ts = Number(parts.t)
if (Math.abs(Date.now() / 1000 - ts) > 300) return res.status(400).end() // 5-min replay window
const expected = crypto
.createHmac('sha256', SECRET)
.update(`${ts}.${req.body.toString('utf8')}`)
.digest('hex')
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))) {
return res.status(401).end()
}
// Trust the body now — your job to dedupe on body.id
const event = JSON.parse(req.body.toString('utf8'))
/* … */
res.json({ ok: true })
})Use express.raw (or your framework's equivalent) so the body bytes match what we signed. Parsing JSON BEFORE verifying will silently change whitespace and break the HMAC.
Rate limits
Per key
60 / min
Resets at the top of each minute, aligned to clock minutes.
Per key
1,000 / day
Resets at 00:00 UTC. Need more? Enterprise plans get custom quotas.
Response headers (always present)
X-RateLimit-Limit— your per-minute cap.X-RateLimit-Remaining— calls left this minute.X-RateLimit-Reset— unix-seconds when the per-minute bucket resets.X-RateLimit-Daily-Limit,…-Daily-Remaining,…-Daily-Reset— same shape for the daily bucket.Retry-After— seconds to wait, only on 429 responses.
Errors
Every error response uses the same envelope so generic clients can branch on.error.code without parsing prose.
{
"error": {
"code": "rate_limited",
"message": "Per-minute rate limit reached. Retry after 23s.",
"retryAfterSeconds": 23
}
}unauthorized— 401 — missing or malformed bearer token.forbidden— 403 — token exists but lacks the required scope.not_found— 404 — id doesn't resolve in this workspace.rate_limited— 429 — per-minute or per-day bucket exhausted.invalid_request— 422 — body / params failed validation.internal_error— 500 — our fault. Retry with exponential backoff.
Ship something today.
Generate a key, hit your first endpoint in five minutes. If something feels missing or wrong, tell us — every endpoint here was built because a creator asked for it.