Skip to main content
ManticScore uses Clerk for identity. Rather than sending your Clerk JWT on every request, you exchange it once for a lightweight session token that the API validates in microseconds. Session tokens expire after 30 minutes, so you’ll refresh them periodically. For zero-friction onboarding, the API also supports anonymous sessions — mint a session from a device id, let users try the product, and rebind their work to a Clerk account when they sign in. This page explains the full authentication lifecycle from login to logout.

How authentication works

Every protected endpoint requires an Authorization header with a Bearer token:
The API accepts two token types, checked in this order:
  1. Session token — an opaque string returned by POST /auth/session or POST /auth/anonymous. Validated via an O(1) lookup, making it the fastest path. Use this for all normal requests.
  2. Clerk JWT — an RS256-signed JWT from Clerk, verified against the Clerk JWKS. Used only when exchanging for a session token.
Sessions come in two flavors:
  • Authenticated sessions are tied to a Clerk user id (e.g. user_3AtP...) and mint tokens from a Clerk JWT.
  • Anonymous sessions are tied to a device id, require no sign-in, and mint tokens from POST /auth/anonymous. When the user later signs in, call POST /auth/rebind once to re-own every anonymous artifact to the authenticated user.
Streaming endpoints (GET /research/{id}/events, WebSocket /ws, and similar) use the same bearer token. The session TTL is extended automatically when you connect to a stream.

Step 1: Get your Clerk JWT

ManticScore uses Clerk as its identity provider. You get a Clerk JWT from the Clerk dashboard or your Clerk client SDK — not from the ManticScore API directly.
  1. Log in to the Clerk dashboard.
  2. Open your ManticScore application.
  3. Navigate to Users, select your account, and copy a short-lived JWT from the Sessions panel.
Use dashboard JWTs for testing and development. For production applications, generate JWTs programmatically using the Clerk SDK.

Step 2: Exchange the JWT for a session token

Send your Clerk JWT to POST /auth/session. The request body is empty — the JWT goes in the Authorization header.
curl
Response:
POST /auth/session only accepts a Clerk JWT. Passing an already-issued session token returns a 401. Always authenticate with your original Clerk JWT when requesting a new session.

Step 3: Make authenticated requests

Include the session token as a Bearer token in every request:
curl
python

Anonymous sessions (zero-friction onboarding)

You can skip the Clerk exchange entirely on first launch and let users try the product without signing in. Call POST /auth/anonymous with a stable device_id and you’ll get back a session token that behaves like any other — attach it on subsequent requests and the API will authorize writes under an anonymous principal.
curl
Response:
The call is idempotent on device_id — repeated calls for the same device reuse the same anonymous principal, so their work is preserved across launches.
Use a stable, per-device identifier. On iOS, identifierForVendor backed by the Keychain is a good choice. Don’t regenerate a new device_id on every launch or users will see an empty account each time.

Rebind on sign-in

When the user signs in with Clerk, call POST /auth/rebind once with the original device_id and the authenticated session token (or Clerk JWT) in the Authorization header. Every row written under the anonymous principal is re-owned by the Clerk user inside a single database transaction:
curl
Response:
Rebind is safe to call defensively after every sign-in:
  • If the device never used an anonymous session, the call is a no-op and returns {"rebound": false}.
  • If the same device and user have already been rebound, the call is also a no-op.
  • If the device was previously rebound to a different Clerk user, the call returns 409 Conflict.
Rebind requires an authenticated token. Calling it with an anonymous session token returns 401 "Rebind requires an authenticated user token; got anonymous session". Always sign the user in first, then call rebind with the authenticated token.
For the full parameter and error reference, see POST /auth/anonymous and POST /auth/rebind in the API reference.
After getting a session token, call GET /auth/bootstrap as your first request. This endpoint returns your full profile, subscription details, and connected secret status in one call — saving you multiple round trips.
curl
Response:
The bootstrap endpoint also auto-creates your ManticScore profile on first access, so you don’t need a separate account setup step.

Session token TTL and refreshing

Session tokens expire after 30 minutes. Plan to refresh proactively rather than waiting for a 401.
Session tokens use a sliding TTL — connecting to a streaming endpoint extends the TTL automatically. For non-streaming usage, re-authenticate by calling POST /auth/session again with your Clerk JWT before the token expires:
curl
python

Logging out

To revoke the current session token, send a DELETE /auth/session request:
curl
Response:
The token is immediately invalidated. Any subsequent requests using that token will receive a 401.

Error responses

All auth errors return 4xx JSON responses with a detail field. Example error response:
Handle 401 responses by re-authenticating with your Clerk JWT and retrying the original request. A 503 is transient — retry with backoff.
python

Summary

1

Get a Clerk JWT

Retrieve your JWT from the Clerk dashboard or your Clerk client SDK.
2

Exchange for a session token

POST /auth/session with your Clerk JWT in the Authorization header. Save the returned token.
3

Call bootstrap

GET /auth/bootstrap to load your profile and verify the token works end-to-end.
4

Make requests

Pass Authorization: Bearer <session_token> on every subsequent API call.
5

Refresh before expiry

Session tokens last 30 minutes. Re-authenticate with your Clerk JWT before they expire.
6

Logout when done

DELETE /auth/session to revoke the token immediately.