ArxDeck
Integrations

Authentication (app users)

Email-and-password app users, setup links, and sessions for static clients.

Authentication (app users)

Authentication lets static sites and client apps sign users in with email and password. Project admins enable it from Settings → Authentication, provision users, and manage suspend state.

Enablement

  1. Enable the Authentication capability on Settings → Authentication (checkbox + save), or use MCP propose_authentication_config with operation: enable.
  2. Leave Temporarily disable app-user sign-in unchecked when you are ready for login and setup endpoints to accept traffic. When sign-in is disabled, service keys and keyed content access still work.
  3. Set your auth page URL — the page on your static site where users set or reset their password. Provision and reset links use ?resetKey= on that URL. Use MCP propose_authentication_config with operation: set_auth_page_url and { "authPageUrl": "https://..." } (or null to clear).
  4. For browser sessions, call auth and session APIs on your site origin via the same-site path /_arxdeck/api/* (Publish-hosted static and dynamic sites). That keeps the content_session cookie first-party. Platform-managed CORS still applies when you call the content service directly from the server or from credentialed cross-origin fetches (see Content management CORS checklist).
  5. Provision users from the authentication settings page. To grant per-collection access rights to app users, enable both Authentication and Content management, then open the collection under Manage content.

Authentication does not require collections — you can run login and user management with no content.

Agents on ArxDeck MCP must call get_project_info for contentServiceUrl, projectRef, and capabilities.authentication before wiring login or session reads. Do not invent env-var configuration for static builds.

Self sign-up is optional per project. When enabled (Settings → Authentication or MCP set_signup_enabled), call GET /auth/config (public) to read { authEnabled, signupEnabled } before showing a registration form. POST /auth/register creates an active user and session in one step (blocked when sign-in is temporarily disabled or signup is off). Admins can still provision users manually.

Password setup and reset flow

When an admin provisions a user (or issues a reset), the dashboard generates a one-time setup token. Share it with the user as a link on your auth page:

  1. Configure auth page URL in Settings → Authentication (for example https://www.example.com/auth).
  2. Append the token as query parameter resetKey (same value as setupToken in the API):
    • If the URL has no query string: {authPageUrl}?resetKey={setupToken}
    • If the URL already has query parameters: {authPageUrl}&resetKey={setupToken}
  3. On your auth page, read resetKey from the query string and call POST /v1/auth/setup with body { "setupToken": "<resetKey>", "email", "password" }.
  4. Optional displayName may be set on setup.

If auth page URL is not configured, the dashboard shows the raw setup token for manual copy.

Successful setup clears the setup token, activates the user, and returns a 7-day session (content_session cookie).

API reference

App-user auth endpoints live on the content service. Browser clients on Publish-hosted sites should use the same-site base below so Chrome and other browsers store the session cookie. Server-side code may call the content service URL directly (unchanged).

Browser base URL (Publish)

https://{your-published-hostname}/_arxdeck/api

Example: POST https://my-app.app.arxdeck.ai/_arxdeck/api/auth/login with credentials: 'include'.

Direct content service base (server-side)

{content-service-base}/v1

Replace {content-service-base} with the HTTPS origin from Settings → Content management. Paths below are shown as /auth/...; prefix with /_arxdeck/api on the site origin or /v1 on the content service.

Headers

HeaderRequiredDescription
X-Project-RefYesProject ref from Settings → Content management.
OriginBrowser requestsMust match a platform-managed publish hostname or a manual allowed origin for CORS.
Content-TypeJSON bodiesapplication/json on POST / PUT.
CookieSession routescontent_session set by login/setup responses.

Sessions

  • Sessions last 7 days from creation (login or setup).
  • The service sets an HttpOnly content_session cookie (SameSite=Lax; Secure). Browsers do not treat it as a third-party cookie when you use the same-site /_arxdeck/api path on your publish hostname.
  • Cross-origin browser calls directly to {content-service-base} may not persist the cookie even when CORS allows credentials — prefer the same-site path for static and SPA clients.
  • POST /auth/logout (or /v1/auth/logout on the content service) clears the cookie.
  • Suspended users receive 403 on session-authenticated routes.

Common errors

StatusMeaning
400Invalid JSON or validation failed.
401Missing/invalid session or invalid login credentials.
403Auth disabled for project, invalid/expired setup token, setup not available, suspended user, or origin not allowed.
404Unknown project ref or user not found (GET /auth/me).
413User data document exceeds 64 KiB serialized JSON.
429Rate limit exceeded (see Content management rate limits).

Endpoints

POST /auth/setup

Set password for a provisioned user (first-time or after admin reset).

FieldTypeRequiredDescription
setupTokenstringYesToken from the setup link (resetKey query param).
emailstringYesUser email (must match provisioned user).
passwordstringYesNew password (8–200 characters).
displayNamestringNoOptional display name (max 120).

Response — 201 Created

{
  "user": {
    "id": "clx9usr00000000000000001",
    "email": "editor@example.com",
    "displayName": "Editor"
  }
}

Sets content_session cookie.

curl -X POST "{content-service-base}/v1/auth/setup" \
  -H "Content-Type: application/json" \
  -H "X-Project-Ref: YOUR_PROJECT_REF" \
  -H "Origin: https://www.example.com" \
  -d '{
    "setupToken": "TOKEN_FROM_RESET_KEY",
    "email": "editor@example.com",
    "password": "chosen-password"
  }'

GET /auth/config

Public check for whether sign-in and self sign-up are enabled. No session required.

Response — 200 OK — { "authEnabled": true, "signupEnabled": false }

curl "{content-service-base}/v1/auth/config" \
  -H "X-Project-Ref: YOUR_PROJECT_REF"

POST /auth/register

Available when signupEnabled is true and app-user sign-in is not temporarily disabled.

FieldTypeRequiredDescription
emailstringYesUser email.
passwordstringYesPassword (8–200 characters).
displayNamestringNoOptional display name.

Response — 201 Created — { "user": { "id", "email", "displayName" } }; sets content_session cookie. Duplicate email returns 409.

POST /auth/login

FieldTypeRequiredDescription
emailstringYesUser email.
passwordstringYesUser password.

Response — 200 OK — same user object as setup; sets content_session cookie.

curl -X POST "{content-service-base}/v1/auth/login" \
  -H "Content-Type: application/json" \
  -H "X-Project-Ref: YOUR_PROJECT_REF" \
  -d '{
    "email": "editor@example.com",
    "password": "user-password"
  }'

POST /auth/change-password

Requires active session.

FieldTypeRequiredDescription
currentPasswordstringYesExisting password.
newPasswordstringYesNew password (8–200 characters).

Response — 200 OK — { "ok": true }.

POST /auth/logout

Clears session cookie. Response — 200 OK — { "ok": true }.

GET /auth/me

Requires active session.

Response — 200 OK

{
  "user": {
    "id": "clx9usr00000000000000001",
    "email": "editor@example.com",
    "displayName": "Editor",
    "status": "active"
  },
  "projectRef": "YOUR_PROJECT_REF",
  "access": {
    "pages": "read",
    "blog": "write"
  }
}

access maps collection slug to the signed-in user's effective level: explicit per-user or group grants (highest wins) plus read for public-readable collections (public visibility, not collection-suspended, project public access not suspended). Collections the user cannot read are omitted. Service keys should use the per-row access field on GET /collections instead of this endpoint.

GET /auth/user-data

Requires active session and authEnabled on the project.

Response — 200 OK — { "data": { ... } } (empty object if never written).

Only the signed-in user can read their document. Service keys cannot access user data in v1.

PUT /auth/user-data

Replace the entire user data document (not a merge).

FieldTypeRequiredDescription
dataobjectYesFree-form JSON object, max 64 KiB serialized.

Response — 200 OK — { "data": { ... } } with stored document.

curl -X PUT "{content-service-base}/v1/auth/user-data" \
  -H "Content-Type: application/json" \
  -H "X-Project-Ref: YOUR_PROJECT_REF" \
  -H "Cookie: content_session=..." \
  -d '{ "data": { "onboardingComplete": true, "theme": "dark" } }'

Static client patterns

ApproachWhen to use
First user / resetOpen <auth-page-url>?resetKey=… or call POST /_arxdeck/api/auth/setup on your site origin with setupToken mapped from resetKey.
Session cookieAfter POST /_arxdeck/api/auth/login on your publish hostname, use fetch(..., { credentials: 'include' }) for /_arxdeck/api/auth/me, user-data, and private collection reads.
Service keyServer-side content API only. Never ship cbk_ keys in static JS bundles.

Custom hosting (not on Publish)

Host your own same-origin reverse proxy so browser traffic hits your domain first, then forwards to {content-service-base}/v1/.... Example (Next.js rewrites in next.config.js):

async rewrites() {
  return [
    {
      source: "/_arxdeck/api/:path*",
      destination: `${process.env.CONTENT_SERVICE_URL}/v1/:path*`,
    },
  ];
}

Use server-side fetch from API routes when you prefer service keys instead of forwarding cookies. Dynamic publish backends can implement the same proxy in-app or call the content service with service keys without app-user sessions.

Per-user private data

Each app user has one JSON object (profile, preferences, onboarding state, settings, and so on). The document is free-form JSON with a 64 KiB serialized size cap. Only that user can read or write it over their session.

Isolation: a session can only access the caller's own document. Suspended users and logged-out callers receive errors; another user's id is not accepted on session routes.

What agents can change (MCP)

  • get_authentication_config — capability, authEnabled, and authPageUrl
  • propose_authentication_config — enable/disable capability, toggle app-user sign-in, set auth page URL (set_auth_page_url)