Users & System

Base URL http://localhost:3333/api/ · Authentication · Conventions

User Routes

Base path: /api/users

Health Check

GET /health

  • Authentication: None
  • Description: Check if the user service is running
  • Response:
{
  "status": "OK"
}

Get User Stats

GET /user-stats

  • Authentication: Required
  • Description: Get user statistics
  • Response:
{
  "agents": 5,
  "workflows": 10,
  "tools": 3,
  "goals": 2,
  "executions": 100,
  "storageUsed": "1.2GB"
}

Get User Settings

GET /settings

  • Authentication: Required
  • Description: Get user settings
  • Response:
{
  "theme": "dark",
  "language": "en",
  "notifications": {
    "email": true,
    "push": false
  },
  "preferences": {}
}

Update User Settings

PUT /settings

  • Authentication: Required
  • Body:
{
  "theme": "light",
  "language": "es",
  "notifications": {
    "email": false,
    "push": true
  }
}
  • Response:
{
  "success": true,
  "settings": {
    "theme": "light",
    "language": "es",
    "notifications": {
      "email": false,
      "push": true
    }
  }
}

Get User Preferences

GET /preferences

  • Authentication: Required
  • Description: Cross-device UI preferences (theme, font, panel geometry). Distinct from /settings, which holds account-level AI configuration and is replace-on-write.
  • Query params:
    • deviceId (optional) — 1-64 chars of [A-Za-z0-9_-]. When supplied, that device's geometry is resolved into preferences.device. When omitted the response shape is unchanged: device is {} and deviceId is null, while global and knownDevices are still returned in full. knownDevices is deliberately not gated on deviceId — a caller listing a user's devices has no device of its own to name.
  • Response:
{
  "success": true,
  "preferences": {
    "global": { "currentTheme": "dark", "fontFamily": "sans", "bgOpacity": 90 },
    "device": { "uiScale": 100, "leftPanelWidth": 384 },
    "deviceId": "dev-abc123",
    "updatedAt": 1786029683945,
    "knownDevices": [
      { "deviceId": "dev-abc123", "label": "iMac", "updatedAt": 1786029683945, "current": true }
    ]
  }
}

Update User Preferences

PUT /preferences

  • Authentication: Required
  • Description: Merges a patch into the stored preferences. Send only the keys that changed; unsent keys are preserved, so an older client cannot erase a key it does not know about. An explicit null deletes a key.
  • Scopes: global keys (theme, font, background treatment) sync everywhere. device keys (panel widths, UI scale, collapse state) are stored per deviceId, because pixel geometry chosen on a 27-inch display is wrong on a laptop.
  • Conflict resolution: global is last-write-wins on updatedAt; a patch older than the stored state is ignored and reported as result.global.staleIgnored. device writes always apply, being uncontended by construction.
  • Body:
{
  "global": { "currentTheme": "cyberpunk", "fontFamily": null },
  "device": { "leftPanelWidth": 420 },
  "deviceId": "dev-abc123",
  "deviceLabel": "iMac",
  "updatedAt": 1786029683945
}
  • Notes:
    • updatedAt (epoch ms) should be the moment the user acted, not the moment the request was built. Defaults to server time when omitted.
    • deviceId is required whenever device is present (400 otherwise).
    • Unknown or malformed keys are dropped, not stored, and are listed in result.*.rejected so a client can see the write was refused.
    • Custom background media is not synced — it lives in browser IndexedDB. Only the useCustomBackground / bgOpacity / bgBlur treatment flags cross devices.
  • Response:
{
  "success": true,
  "preferences": {
    "global": { "currentTheme": "cyberpunk" },
    "device": { "leftPanelWidth": 420 },
    "deviceId": "dev-abc123",
    "updatedAt": 1786029683945,
    "knownDevices": []
  },
  "result": {
    "global": { "applied": ["currentTheme"], "deleted": ["fontFamily"], "rejected": [], "staleIgnored": false },
    "device": { "applied": ["leftPanelWidth"], "deleted": [], "rejected": [], "deviceId": "dev-abc123" },
    "evictedDevices": []
  }
}
  • Errors: 400 malformed body / missing deviceId / non-numeric updatedAt; 404 user not found; 413 payload exceeds 64 KB.

Sync Token

POST /sync-token

  • Authentication: Required
  • Description: Sync user token across services
  • Response:
{
  "success": true,
  "message": "Token synced successfully"
}

Get Token Status

GET /token-status

  • Authentication: None
  • Description: Get current token status
  • Response:
{
  "valid": true,
  "expiresIn": 3600,
  "refreshRequired": false
}

Get Connection Health

GET /connection-health

  • Authentication: Required
  • Description: Get health status of all provider connections
  • Response:
{
  "success": true,
  "data": {
    "overall": "healthy|degraded",
    "healthyConnections": 51,
    "totalConnections": 52,
    "timestamp": "2026-01-01T15:42:40.838Z",
    "providers": [
      {
        "provider": "openai",
        "status": "healthy",
        "lastChecked": "2026-01-01T15:42:39.786Z",
        "details": {}
      },
      {
        "provider": "anthropic",
        "status": "healthy",
        "lastChecked": "2026-01-01T15:42:37.303Z",
        "details": {}
      },
      {
        "provider": "twitter",
        "status": "error",
        "lastChecked": "2026-01-01T15:42:40.643Z",
        "error": "Failed to retrieve access token from remote auth service."
      }
    ]
  }
}

Important:

  • The response wraps data in a data object, not at the root level.
  • Provider status values are "healthy" or "error" (not "connected").
  • Each provider object has a provider field (lowercase provider name), not name or id.
  • Failed providers include an error field instead of details.

Get Single Provider Health

GET /connection-health/:providerId

  • Authentication: Required
  • Parameters:
    • providerId (path): Provider ID
  • Description: Get health status of a specific provider
  • Response:
{
  "id": "openai",
  "name": "OpenAI",
  "status": "connected",
  "lastCheck": "2024-01-01T00:00:00Z",
  "latency": 150,
  "details": {}
}

Get Connection Health Stream

GET /connection-health-stream

  • Authentication: Required (via token query parameter)
  • Parameters:
    • token (query): JWT token
  • Description: Get real-time connection health updates via SSE
  • Response: Server-sent events stream

Get Security Policy

GET /security-policy

  • Authentication: Required
  • Description: The current user's security policy
  • Response: Security policy object

Update Security Policy

PUT /security-policy

  • Authentication: Required
  • Description: Update the current user's security policy
  • Response: Updated security policy object

Reset Security Policy

DELETE /security-policy

  • Authentication: Required
  • Description: Reset the current user's security policy to defaults
  • Response: Confirmation object

Get Security Audit

GET /security-audit

  • Authentication: Required
  • Description: Security audit information for the current user
  • Response: Security audit object

System Routes

Base path: /api/system

System-level operations: status and restart.

Get System Status

GET /status

  • Authentication: None — intentionally unauthenticated: the frontend polls this while the backend drains/reboots, and the Electron supervisor may check it too. Exposes nothing sensitive (state/pid/uptime).
  • Response: RestartManager status object (state, pid, uptime)

Restart Backend

POST /restart

  • Authentication: Required
  • Description: Initiates a backend restart. Responds 202 first, then starts the drain — the 2s grace period guarantees the response flushes before the socket dies. Backend is back in ~10–20 seconds. 409 if a restart is already in progress.
  • Body:
{
  "reason": "optional reason string"
}
  • Response (202):
{
  "success": true,
  "message": "Restart initiated. Backend will be back in ~10-20 seconds.",
  "gracePeriodMs": 2000
}

Admin Routes

Base path: /api/admin

Administrative operations.

Get Client Versions

GET /client-versions

  • Authentication: None
  • Description: Inspected CLI/client versions for supported providers
  • Response:
{
  "success": true,
  "providers": {}
}

Refresh Client Versions

POST /client-versions/refresh

  • Authentication: None
  • Description: Re-inspects all client versions
  • Response:
{
  "success": true,
  "refreshed": {}
}

The AGNT briefing

Stay in the loop.

New agents, workflows and field notes. Sign up for AGNT updates.

By subscribing, you agree to receive AGNT updates. Unsubscribe any time. Privacy policy.