Authentication
How to authenticate to the CiteFoundry REST API. Bearer JWTs, session lifecycle, and the dashboard's session model.
All API requests use a Bearer JWT passed in the Authorization
header:
GET /v1/projects/proj_01J... HTTP/1.1Host: api.citefoundry.comAuthorization: Bearer eyJhbGciOiJI...Accept: application/jsonThe same scheme works from the dashboard (which has a session cookie backing the JWT) and from external integrations using a personal access token.
Getting a token
For programmatic access, mint a personal access token under Settings → API tokens in the dashboard. Tokens are scoped to your user and inherit your organization-level role.
The /v1/me endpoint
Test that your token works by calling
GET /v1/me . It returns the
authenticated user, their organization, and their role:
curl https://api.citefoundry.com/v1/me \ -H "Authorization: Bearer $CITEFOUNDRY_TOKEN"A successful response is 200 with a JSON body. An expired or invalid
token returns 401 with an RFC 7807 problem whose
type is https://citefoundry.com/problems/unauthorized.
Session model (dashboard)
The Next.js dashboard uses WorkOS AuthKit for sign-in and stores the resulting session in an HTTP-only cookie. The backend exchanges that cookie for a short-lived JWT on every request. You don’t need to do anything special to support this from the API side — the same Bearer scheme works.
Token expiry and refresh
Personal access tokens are long-lived (default 90 days, configurable).
The dashboard session refreshes silently. If your client gets a 401
from a previously-working token:
- Mint a new token in the dashboard.
- Update your secret store.
- Retry.
For automated environments, schedule a rotation before the configured
expiry — a 401 halfway through a batch is a worse experience than a
calendar reminder.
CORS and origins
The API allows requests from the dashboard’s origin and from the configured custom origins on your plan. If you’re building a public client-side integration, contact us to allow-list your origin — shipping the token to a browser is rarely what you want; consider a server-side proxy instead.
Related
- Error format — RFC 7807 problem responses.
- TypeScript SDK — handles the Bearer header for you.