Get started

Authentication

Bearer tokens, scoped per integration. Versioning is explicit, rate limits are generous, errors are machine-readable.

Bearer tokens

Every request must include an Authorization header carrying a Lectern API token. Tokens look like sk_live_lectern_followed by a 32-character identifier - the prefix tells you whether it’s a live (sk_live_) or test (sk_test_) token.

HTTPHeader format
Copy
Authorization: Bearer sk_live_lectern_8aJ4F2pYxQRk0ZqMnVbT9HwLcXKp

Scopes

Tokens are scoped at creation time. A scope is a verb plus a resource: read:learners, write:finance, read:audit. The least-privilege principle applies - mint a token with only the scopes the integration needs.

  • read:<resource> - list and read single records
  • write:<resource> - create, update, archive
  • delete:<resource> - permanent deletion (rare; most resources soft-archive)
  • admin:tenant - settings, integrations, permissions

If a token attempts an operation outside its scopes, the API returns 403 forbidden with an insufficient_scope error code.

Rotation & revocation

Rotate tokens on a regular cadence - quarterly is a sensible default, monthly for production systems. To rotate without downtime: mint a new token with the same scopes, deploy it, then revoke the old one in Settings → API.

Revoked tokens are rejected immediately. Rotation events are written to the audit log with the token’s identifier (never the secret).

Versioning

The API is versioned by date. Send Lectern-Version: 2026-01-01on every request to pin the schema. If you don’t pass a version, Lectern uses the version your tenant was created under - safe by default, but we recommend pinning explicitly.

Breaking changes get a new version. Additive changes (new fields, new endpoints) ship continuously. The changelog documents every version.

Rate limits

Default limits per token: 200 requests per minute for reads, 60 per minute for writes. Bulk endpoints have their own ceiling - see Data import & export.

Every response includes rate-limit headers so clients can self-pace:

HTTPResponse headers
Copy
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 187
X-RateLimit-Reset: 2026-05-07T13:24:00Z

Hitting the limit returns 429 Too Many Requests. The Retry-After header tells you how long to wait. If you need a higher limit for an integration, write to dev@lectern.school.

Errors

Errors return a stable JSON envelope with a machine-readable code and a human-readable message. Always switch on code, not the message.

Response401 Unauthorized
application/json
{
  "error": {
    "code": "invalid_token",
    "message": "The API token provided was not recognized.",
    "request_id": "req_2pYxQRk0ZqMnVbT"
  }
}

Common error codes:

  • invalid_token - token missing, malformed, or revoked
  • insufficient_scope - token lacks the required scope for the operation
  • not_found - the resource does not exist or your tenant cannot see it
  • validation_failed - payload failed schema validation; details in error.details[]
  • rate_limited- you’re over your limit; wait Retry-After seconds
  • internal_error - we broke something; quote the request_id when reporting