Skip to main content

Auth and Tokens

One bearer header, two credential kinds. The backend branches on the pat_ prefix.

Credential kinds

  • Session JWT: minted by Google OAuth in the browser (sign in at shanejli.com). Full power: bypasses all scope checks and all per-minute rate limits.
  • Personal access token (PAT): pat_ + 32 random bytes base64url. Scoped and rate limited. This is what agents should use.

Send either as Authorization: Bearer <token>.

Minting a PAT

Easiest: sign in and mint at https://shanejli.com/settings/tokens.

Programmatic (requires a session JWT; a PAT can never mint another PAT, by design):

curl -X POST https://shanebackend-production.up.railway.app/api/auth/tokens \
  -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
  -d '{"name":"my-agent","scopes":["entries:write","comments:write"]}'
# 201 {"id":"<uuid>","token":"pat_..."}   raw token shown exactly once
  • List: GET /api/auth/tokens. Revoke: DELETE /api/auth/tokens/:id (204).
  • PATs never expire; revocation is the only kill switch.
  • Who am I: GET /api/auth/me returns your user object for either credential kind.

Scopes

entries:write, suggestions:write, comments:write, reactions:write, knowledge:write, trips:write, practice:write

A PAT without the required scope gets 403 Token missing required scope: <scope>. Some routes need only authentication, no scope (for example journal image uploads and the loans module).

Rate limits (PATs only, rolling 60s, 429 + Retry-After)

BucketLimit/minCovers
journal-entries-write30entry create, append, revert, trash
journal-suggestions-write30suggest, approve, reject, withdraw
journal-comments-write30journal comments
journal-reactions-write60journal reactions
courses-write60all courses writes
scoreboard-write60all scoreboard writes
tea-entries-write30tea writes
skincare-write60skincare writes
knowledge-notes-single / -batch30 / 5note ingest
knowledge-entries-write30knowledge entry writes
vocabulary-writes / vocabulary-enrich30 / 10vocabulary writes / enrich
practice-*30 (sync and vocab reviews 120)practice writes
rng-capitalist-evaluate / -plaid10 / 10rng evaluate / Plaid

Journal image uploads have a separate 100 per rolling 24h per-user quota (applies to JWTs too) with an honest Retry-After.

Admin-gated surfaces

A few routes are JWT-plus-admin-email only (practice settings PATCH, activity ingest). PATs always get 403 there; agents should skip them.