Skip to main content

API Reference

All API endpoints are served under /api/. Requests and responses use JSON. Admin routes use cookie-based sessions; project auth routes use public key + bearer tokens.

Base URL

EnvironmentURLNotes
Kyqu Cloudhttps://api.kyqu.devSet this as baseUrl in the SDK
Self-hostedhttps://auth.example.comSet API_BASE_URL to match

Project auth routes return 403 when the project is suspended or auth is disabled.

Admin Routes

Authentication

GET /api/admin/me

Restore admin session from cookie. Sets CSRF cookie.

Response: 200 { admin } or 401 { error }

POST /api/admin/signup

Create admin account. First signup becomes superadmin. Returns 403 when ADMIN_REGISTRATION_OPEN=false.

Request: { email, password, name } Response: 201 { admin } + Set-Cookie session + CSRF

POST /api/admin/login

Authenticate admin.

Request: { email, password } Response: 200 { admin } + Set-Cookie session + CSRF

POST /api/admin/logout

Revoke admin session. Requires CSRF token.

Response: 200 { ok } + Clear-Cookie

MFA (Admin 2FA)

POST /api/admin/mfa/enroll

Start TOTP enrollment for admin.

Response: 200 { enrollmentUrl }

POST /api/admin/mfa/verify

Verify TOTP code during login (after email/password step).

Request: { code } Response: 200 { admin } + Set-Cookie session

POST /api/admin/mfa/confirm

Confirm TOTP enrollment with code from authenticator app.

Request: { code } Response: 200 { ok, backupCodes: [...] }

POST /api/admin/mfa/disable

Disable TOTP for admin.

Request: { code } Response: 200 { ok: true }

Overview

GET /api/admin/overview

Cross-project platform statistics.

Response: 200 { totalProjects, totalUsers, totalSessions, recentSignups, recentLogins }

Projects

GET /api/admin/projects

List projects for the authenticated admin.

Response: 200 { projects: [...] }

POST /api/admin/projects

Create a new project.

Request: { name, productType, domain } Response: 201 { project } (includes publicKey and secretKey, shown once)

GET /api/admin/projects/:id

Get project details.

Response: 200 { project } or 404

PATCH /api/admin/projects/:id

Update project settings.

Request: { name?, domain?, productType?, authSettings?, redirectUrls? } Response: 200 { project }

GET /api/admin/projects/:id/onboarding

Get project onboarding status.

Response: 200 { onboarding }

PATCH /api/admin/projects/:id/onboarding

Update project onboarding step.

Request: { step?: string, completed?: boolean, data?: object } Response: 200 { onboarding }

Project Users

GET /api/admin/projects/:id/users

List users for a project.

Response: 200 { users: [...] }

POST /api/admin/projects/:id/users

Create a user in a project.

Request: { email, password?, name?, metadata?, skipVerification? } Response: 201 { user }

PATCH /api/admin/projects/:id/users/:userId/metadata

Update user metadata.

Request: { metadata: { ... } } Response: 200 { user }

POST /api/admin/projects/:id/users/:userId/resend-verification

Resend verification email.

Response: 200 { ok: true }

POST /api/admin/projects/:id/users/:userId/force-password-reset

Force password reset.

Response: 200 { ok: true }

POST /api/admin/projects/:id/users/:userId/reset-2fa

Reset TOTP 2FA for user.

Response: 200 { ok: true }

POST /api/admin/projects/:id/users/:userId/unlock

Unlock a locked user account.

Response: 200 { ok: true }

POST /api/admin/projects/:id/users/:userId/suspend

Suspend a user.

Request: { reason?: string } Response: 200 { ok: true }

POST /api/admin/projects/:id/users/:userId/reactivate

Reactivate a suspended user.

Response: 200 { ok: true }

DELETE /api/admin/projects/:id/users/:userId

Delete a project user (admin).

Response: 200 { ok: true }

Auth Settings

PATCH /api/admin/projects/:id/auth/settings

Update project auth settings.

Request: Partial auth settings object (see Configuration Reference)

Response: 200 { project }

API Keys

POST /api/admin/projects/:id/api-keys/rotate

Rotate project API key pair.

Response: 200 { project } (includes new publicKey and secretKey)

User Fields

GET /api/admin/projects/:id/user-fields

List custom field definitions.

Response: 200 { fields: [...] }

POST /api/admin/projects/:id/user-fields

Create a custom field definition.

Request: { name, label, fieldType, required?, defaultValue?, sortOrder? } Response: 201 { field }

DELETE /api/admin/projects/:id/user-fields/:fieldId

Delete a custom field definition.

Response: 200 { ok: true }

Impersonation

POST /api/admin/projects/:id/users/:userId/impersonate

Impersonate a project user (superadmin only).

Response: 200 { session: { token, expiresAt }, user }

POST /api/admin/projects/:id/impersonation/end

End active impersonation session.

Response: 200 { ok: true }

OAuth Providers

GET /api/admin/projects/:id/oauth-providers

List OAuth provider configurations.

Response: 200 { providers: [...] }

POST /api/admin/projects/:id/oauth-providers

Upsert OAuth provider configuration.

Request: { provider: "google" | "github", clientId, clientSecret, enabled? } Response: 200 { provider }

DELETE /api/admin/projects/:id/oauth-providers/:provider

Remove OAuth provider configuration.

Response: 200 { ok: true }

Audit

GET /api/admin/projects/:id/logs

Get audit logs. Supports ?limit=N&offset=N query params.

Response: 200 { logs: [...], total: N }

GET /api/admin/projects/:id/stats

Get project statistics.

Response: 200 { stats: { totalUsers, activeSessions, authEvents, ... } }

GET /api/admin/projects/:id/email-outbox

List sent/stored email records.

Response: 200 { messages: [...] }

Webhooks

GET /api/admin/projects/:id/webhooks

List webhook endpoints. Also returns availableEvents.

Response: 200 { webhooks: [...], availableEvents: [...] }

POST /api/admin/projects/:id/webhooks

Create a webhook endpoint.

Request: { url, events?: string[] } Response: 201 { webhook } (includes secret, shown once)

PATCH /api/admin/projects/:id/webhooks/:webhookId

Update a webhook.

Request: { url?, events?, enabled? } Response: 200 { webhook }

DELETE /api/admin/projects/:id/webhooks/:webhookId

Delete a webhook.

Response: 200 { ok: true }

GET /api/admin/projects/:id/webhooks/:webhookId/deliveries

List recent webhook delivery records.

Response: 200 { deliveries: [...] }

GET /api/admin/webhook-events

List all available webhook event types.

Response: 200 { events: [...] }

Email Templates

GET /api/admin/projects/:id/email-templates

List email templates with purposes.

Response: 200 { templates: [...], purposes: [...] }

PUT /api/admin/projects/:id/email-templates/:purpose

Save custom email template.

Request: { subject, htmlBody, textBody } Response: 200 { template }

DELETE /api/admin/projects/:id/email-templates/:purpose

Reset template to default.

Response: 200 { ok: true }

Superadmin Routes

All superadmin routes require the authenticated admin to have isSuperadmin: true.

GET /api/admin/superadmin/projects

List all projects across the platform.

Response: 200 { projects: [...] }

GET /api/admin/superadmin/users

List all project users across the platform.

Response: 200 { users: [...] }

POST /api/admin/superadmin/projects/:id/suspend

Suspend a project.

Response: 200 { ok: true }

POST /api/admin/superadmin/projects/:id/reactivate

Reactivate a project.

Response: 200 { ok: true }

POST /api/admin/superadmin/projects/:projectId/users/:userId/{action}

Superadmin user actions:

  • suspend — requires body { reason: string }
  • reactivate
  • unlock
  • reset-2fa
  • resend-verification
  • force-password-reset

Response: 200 { result }

GET /api/admin/superadmin/email-templates

List all custom email templates across all projects.

Response: 200 { templates: [...], purposes: [...] }

GET /api/admin/superadmin/default-templates

List platform-wide default templates.

Response: 200 { templates: [...], purposes: [...] }

PUT /api/admin/superadmin/default-templates/:purpose

Save platform-wide default template.

Request: { subject, htmlBody, textBody } Response: 200 { template }

DELETE /api/admin/superadmin/default-templates/:purpose

Reset platform default to built-in.

Response: 200 { ok: true }

GET /api/admin/superadmin/ip-allowlist

List IP allowlist entries.

Response: 200 { entries: [...] }

POST /api/admin/superadmin/ip-allowlist

Add IP to allowlist.

Request: { ipAddress, description?, expiresAt? } Response: 201 { entry }

DELETE /api/admin/superadmin/ip-allowlist/:entryId

Remove IP from allowlist.

Response: 200 { ok: true }

Project Auth Routes

All project routes require x-kyqu-public-key header (or publicKey in body).

Authentication

POST /api/projects/:id/auth/signup

Register a new project user.

Request: { email, password, name?, ...customFields } Response: 201 { user, session?, verificationRequired, verificationQueued? }

POST /api/projects/:id/auth/login

Authenticate a project user.

Request: { email, password, totpCode?, backupCode? } Response: 200 { user, session } or 403 { error: "TOTP_REQUIRED" }

GET /api/projects/:id/auth/me

Get current user from bearer token.

Headers: Authorization: Bearer <token> Response: 200 { user } or 401

DELETE /api/projects/:id/auth/me

Permanently delete the authenticated user's account.

Headers: Authorization: Bearer <token> Request: { password: string } Response: 200 { ok: true } or 401/403/400

POST /api/projects/:id/auth/logout

Revoke session token.

Headers: Authorization: Bearer <token> Response: 200 { ok: true }

Email Verification

POST /api/projects/:id/auth/verify-email/request

Send verification email.

Request: { email } Response: 200 { ok: true }

POST /api/projects/:id/auth/verify-email/confirm

Confirm email verification with token.

Request: { token } Response: 200 { user }

GET /api/projects/:id/auth/verify-email/confirm?token=...

Browser redirect handler for email link clicks.

Success: 302 → email_verified_url?verified=1 Failure: 302 → login_url?error=...

Password Reset

POST /api/projects/:id/auth/password-reset/request

Request password reset email.

Request: { email } Response: 200 { ok: true }

POST /api/projects/:id/auth/password-reset/confirm

Confirm password reset.

Request: { token, password } Response: 200 { user, session }

GET /api/projects/:id/auth/password-reset/confirm?token=...

Browser redirect handler.

Redirect: 302 → password_reset_url?token=...

Change Password

POST /api/projects/:id/auth/password/change

Change password (authenticated).

Headers: Authorization: Bearer <token> Request: { currentPassword, newPassword } Response: 200 { ok: true }

POST /api/projects/:id/auth/magic-link/request

Request magic link email.

Request: { email } Response: 200 { ok: true }

POST /api/projects/:id/auth/magic-link/confirm

Confirm magic link token (API / server-side).

Request: { token } Response: 200 { user, session }

GET /api/projects/:id/auth/magic-link/confirm?token=...

Browser redirect handler for email link clicks.

Success: 302 → login_url?session_code={oneTimeCode} (5-minute TTL) Failure: 302 → login_url?error=...

The redirect does not include the bearer session token. Exchange the code server-side or from your app:

POST /api/projects/:id/auth/session/exchange

Exchange a browser session_code for a bearer session.

Request: { sessionCode } (or { code }) Response: 200 { user, session }

TOTP 2FA

POST /api/projects/:id/auth/totp/enroll

Start TOTP enrollment (authenticated).

Headers: Authorization: Bearer <token> Response: 200 { enrollmentUrl }

POST /api/projects/:id/auth/totp/confirm

Confirm TOTP enrollment.

Headers: Authorization: Bearer <token> Request: { code } Response: 200 { ok, backupCodes: [...] }

POST /api/projects/:id/auth/totp/disable

Disable TOTP.

Headers: Authorization: Bearer <token> Request: { code } Response: 200 { ok: true }

Sessions

GET /api/projects/:id/auth/sessions

List active sessions.

Headers: Authorization: Bearer <token> Response: 200 { sessions: [...] }

DELETE /api/projects/:id/auth/sessions/:sessionId

Revoke a specific session.

Headers: Authorization: Bearer <token> Response: 200 { ok: true }

Custom Fields

GET /api/projects/:id/auth/fields

Get custom field definitions.

Response: 200 { fields: [...] }

Update Metadata

PATCH /api/projects/:id/auth/me/metadata

Update the authenticated user's metadata.

Headers: Authorization: Bearer <token> Request: { metadata: { ... } } Response: 200 { user }

ID Token (OIDC)

POST /api/projects/:id/auth/token

Issue an RS256-signed OIDC ID token for the authenticated user.

Headers: Authorization: Bearer <token> Response: 200 { idToken, tokenType: "Bearer", expiresIn }

Event Logs

GET /api/projects/:id/auth/logs

List auth event logs for the authenticated user.

Headers: Authorization: Bearer <token> Query: ?limit=N&offset=N&event=type Response: 200 { logs: [...], total: N }

Email Tracking

GET /api/projects/:id/email/track/open/:token

1×1 transparent GIF tracking pixel. Logs email open events.

Response: 200 (image/gif)

POST /api/projects/:id/email/bounce

Receive bounce notifications from SMTP.

Request: { email, reason?, type? } Response: 200 { ok: true }

Passkeys (WebAuthn)

GET /api/projects/:id/auth/passkey/register/options

Get WebAuthn registration options (authenticated).

Headers: Authorization: Bearer <token> Response: 200 { challenge, rp, user, pubKeyCredParams, authenticatorSelection }

POST /api/projects/:id/auth/passkey/register/verify

Verify and store a new passkey credential (authenticated).

Headers: Authorization: Bearer <token> Request: { credential, name? } Response: 201 { credential }

GET /api/projects/:id/auth/passkey/authenticate/options

Get WebAuthn authentication options (public, no auth required).

Query: ?userId=... Response: 200 { challenge, allowCredentials?, rpId, userVerification }

POST /api/projects/:id/auth/passkey/authenticate/verify

Verify WebAuthn assertion and issue session.

Request: { assertion } Response: 200 { user, session }

GET /api/projects/:id/auth/passkeys

List passkey credentials (authenticated).

Headers: Authorization: Bearer <token> Response: 200 { passkeys: [...] }

DELETE /api/projects/:id/auth/passkeys/:credentialId

Delete a passkey credential (authenticated).

Headers: Authorization: Bearer <token> Response: 200 { ok: true }

OAuth (Social Login)

GET /api/projects/:id/auth/oauth/:provider/authorize

Initiate OAuth authorization redirect.

Query: ?redirectUrl=... Response: 302 redirect to provider's OAuth consent screen

GET /api/projects/:id/auth/oauth/:provider/callback

Handle OAuth callback from provider.

Query: ?code=...&state=... Response: 302 redirect with session (or error query param)

OIDC / JWKS

GET /api/projects/:id/.well-known/openid-configuration

OpenID Connect Discovery document.

Response: 200 { issuer, authorization_endpoint, token_endpoint, jwks_uri, ... }

GET /api/projects/:id/.well-known/jwks.json

JSON Web Key Set for RS256 ID token verification.

Response: 200 { keys: [...] }

Server Admin Routes

These endpoints are called from your application server using the project's secret key (x-kyqu-secret-key header).

User Management

DELETE /api/projects/:id/admin/users/:userId

Delete a project user (server-to-server).

Headers: x-kyqu-secret-key: <project-secret> Response: 200 { ok: true }

PATCH /api/projects/:id/admin/users/:userId/status

Update a user's status (server-to-server).

Headers: x-kyqu-secret-key: <project-secret> Request: { status: "active" | "suspended", reason?: string } Response: 200 { ok: true }

System

GET /api/health

Basic health check.

Response: 200 { ok: true }

GET /api/ready

Readiness check with subsystem status.

Response: 200 { ok: true, database: "ok", email: "...", rateLimitStore: "..." }