Identity API
The real, currently-deployed routes behind Phocod's identity domain — the same ones this app itself and every other Phocod app use. Every response is a stable envelope: { ok: true, data } on success, { ok: false, error: { code, message } } on failure.
This documents what exists today, not a public developer platform — there's no API key issuance or third-party app registration yet.
/api/auth/signupCreate a Phocod account. Hashes the password (scrypt) and starts a session.
Request body
{
"email": "you@example.com",
"password": "at least 8 characters",
"name": "Optional display name"
}Response
// 201 Created, sets the identity_session cookie (httpOnly, 30-day)
{ "ok": true, "data": { "userId": "…", "email": "you@example.com" } }
// 400 Bad Request (invalid email/password, duplicate email, rate-limited)
{ "ok": false, "error": { "code": "VALIDATION_ERROR", "message": "…" } }/api/auth/loginVerify email + password, start a session.
Request body
{ "email": "you@example.com", "password": "…" }Response
// 200 OK, sets the identity_session cookie
{ "ok": true, "data": { "userId": "…", "email": "you@example.com" } }
// 400 Bad Request (wrong credentials or rate-limited)
{ "ok": false, "error": { "code": "VALIDATION_ERROR", "message": "Incorrect email or password." } }/api/auth/logoutDestroy the current session. Called via a plain HTML form, not fetch — it redirects rather than returning JSON.
Response
302 redirect to /
/api/auth/mint?app=chat|professional|marketplace|entertainment|intelligentMint a short-lived, single-use identity token bound to one target app for cross-app SSO. This is what a Phocod app's own /api/auth/exchange route consumes to establish its own session. `app` is required — the token's `aud` claim is set to it, so a token minted for one app is rejected by every other app even before its single-use jti is checked.
Response
// 200 OK — token is single-use (rejected on replay) with a 120-second expiry
{ "ok": true, "data": { "identityToken": "eyJhbGciOi..." } }
// 400 Validation (missing or unrecognized app)
{ "ok": false, "error": { "code": "VALIDATION", "message": "app must be one of: chat, professional, ..." } }
// 401 Unauthorized (no session)
{ "ok": false, "error": { "code": "UNAUTHORIZED", "message": "Sign in required." } }/api/auth/redirect?app=chat|professional|marketplace|entertainment|intelligentMints a fresh identity token bound to that app and redirects straight to its /login/callback with it attached. Used by the dashboard's "Open" links.
Response
302 redirect to {appUrl}/login/callback?identity_token=…/api/sessionsInternal data-product placeholder for this domain's session count — not an authenticated user-data endpoint, just a scaffold contract other domains could consume later.
Response
{ "domain": "identity", "model": "session", "count": 0 }How cross-app SSO actually works
GET /api/auth/mint (or /api/auth/redirect) issues an HS256 JWT signed with a shared secret, carrying sub, email, and a unique jti. The receiving app verifies it via @phocod/platform's shared verifyIdentityToken, claims the jti exactly once (rejecting replay), and mints its own long-lived session cookie — it never re-verifies the identity token again after that.