API reference

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.

POST/api/auth/signup

Create a Phocod account. Hashes the password (scrypt) and starts a session.

Auth: NoneRate limit: 5 attempts / hour, per email

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": "…" } }
POST/api/auth/login

Verify email + password, start a session.

Auth: NoneRate limit: 10 attempts / 15 min, per email

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." } }
POST/api/auth/logout

Destroy the current session. Called via a plain HTML form, not fetch — it redirects rather than returning JSON.

Auth: identity_session cookie

Response

302 redirect to /
GET/api/auth/mint?app=chat|professional|marketplace|entertainment|intelligent

Mint 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.

Auth: identity_session cookie

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." } }
GET/api/auth/redirect?app=chat|professional|marketplace|entertainment|intelligent

Mints 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.

Auth: identity_session cookie

Response

302 redirect to {appUrl}/login/callback?identity_token=…
GET/api/sessions

Internal data-product placeholder for this domain's session count — not an authenticated user-data endpoint, just a scaffold contract other domains could consume later.

Auth: None

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.

Back to the home page