Sign-in
Password login, the token pair it returns, and how to verify the access token against the public JWKS on your server.
Password sign-in exchanges an email + password for a token pair. There's no publishable key and no opaque session cookie to decode — Qeet ID issues an ES256 access JWT your services verify offline.
Log in
/v1/auth/loginPassword login → token paircurl -X POST https://api.qeetid.com/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"alex@acme.com","password":"a-strong-passphrase"}'{
"access_token": "eyJhbGciOiJFUzI1Ni…",
"token_type": "Bearer",
"expires_at": "2026-06-04T12:15:00Z",
"refresh_token": "…",
"session_id": "…",
"user_id": "…",
"tenant_id": "…"
}MFA-gated accounts
If the tenant or user requires MFA, complete the appropriate factor before the session is fully privileged. See MFA for the factor and step-up flows.
Verify the access token on your server
Send the access token to your backend as a bearer header, then verify it locally against the cached JWKS — signature, expiry, issuer, audience. No network call per request.
import { qeetid } from "@/lib/qeetid";
const claims = await qeetid.sessions.verify(accessToken);
// claims.userId, claims.tenantId, claims.sessionIdclaims, err := qeetid.Sessions.Verify(ctx, accessToken)claims = qeetid.sessions.verify(access_token)Bearer = the JWT, not the API key
User access tokens use Authorization: Bearer <jwt>. Server-side
API keys use Authorization: ApiKey qk_…. They are different schemes —
don't put an API key behind Bearer or vice versa.
Failure modes
| Failure | HTTP | Notes |
|---|---|---|
| Wrong email/password | 401 | Generic — never reveal which field. |
| Too many attempts | 429 | Per-account lockout + IP rate limit kicked in. See Sessions → Lockout. |
| Validation error | 422 | Malformed body. |
The error body always follows the { "error": { "code", "message" } } envelope —
see API → Errors.
Hosted login
To avoid building login UI at all, run the OAuth Authorization Code + PKCE flow
against Qeet ID's hosted login with @qeetid/nextjs. The SDK handles the token pair,
stores an encrypted HttpOnly cookie, and refreshes silently. See
SDKs → TypeScript & Next.js.