> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ccs.kaitran.ca/llms.txt
> Use this file to discover all available pages before exploring further.

# Settings & Auth API

> REST API endpoints for managing profile settings, presets, and authentication tokens

# Settings & Auth API

Manage profile settings, create presets for quick configuration switching, and control global authentication tokens for CLIProxy.

## Overview

Settings endpoints provide:

* Profile settings CRUD (Create, Read, Update, Delete)
* Preset management for model configurations
* Global auth token management (API key, management secret)
* Token regeneration and reset
* Conflict detection with optimistic locking

## Authentication

All endpoints are available on localhost only ([http://localhost:3000](http://localhost:3000)). No authentication required.

## Profile Settings

### GET /api/settings/:profile

Get settings for a profile with masked API keys.

**Path Parameters:**

* `profile`: Profile name or variant (e.g., `gemini`, `glm`, `agy`)

<CodeGroup>
  ```bash Request theme={null}
  curl http://localhost:3000/api/settings/gemini
  ```

  ```json Response theme={null}
  {
    "profile": "gemini",
    "settings": {
      "env": {
        "ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/gemini",
        "ANTHROPIC_AUTH_TOKEN": "********",
        "ANTHROPIC_MODEL": "gemini-3-flash-preview"
      }
    },
    "mtime": 1704467400000,
    "path": "/home/user/.ccs/gemini.settings.json"
  }
  ```

  ```json Error (Not Found) theme={null}
  {
    "error": "Settings not found"
  }
  ```
</CodeGroup>

**Note:** Sensitive keys (API tokens, secrets) are automatically masked with `********`.

***

### GET /api/settings/:profile/raw

Get full unmasked settings for editing.

<Warning>
  Sensitive endpoint - returns unmasked API keys. Use for editing only.
</Warning>

<CodeGroup>
  ```bash Request theme={null}
  curl http://localhost:3000/api/settings/gemini/raw
  ```

  ```json Response theme={null}
  {
    "profile": "gemini",
    "settings": {
      "env": {
        "ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/gemini",
        "ANTHROPIC_AUTH_TOKEN": "actual-token-here",
        "ANTHROPIC_MODEL": "gemini-3-flash-preview"
      }
    },
    "mtime": 1704467400000,
    "path": "/home/user/.ccs/gemini.settings.json"
  }
  ```
</CodeGroup>

***

### PUT /api/settings/:profile

Update settings with conflict detection and automatic backup.

**Path Parameters:**

* `profile`: Profile name or variant

**Request Body:**

* `settings` (required): Settings object with `env` field
* `expectedMtime` (optional): Timestamp for optimistic locking

<CodeGroup>
  ```bash Request theme={null}
  curl -X PUT http://localhost:3000/api/settings/gemini \
    -H "Content-Type: application/json" \
    -d '{
      "settings": {
        "env": {
          "ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/gemini",
          "ANTHROPIC_AUTH_TOKEN": "new-token",
          "ANTHROPIC_MODEL": "gemini-3-pro-preview"
        }
      },
      "expectedMtime": 1704467400000
    }'
  ```

  ```json Response (Success) theme={null}
  {
    "profile": "gemini",
    "mtime": 1704467500000,
    "backupPath": "/home/user/.ccs/backups/gemini.2026-01-05T14-30-00.settings.json",
    "created": false
  }
  ```

  ```json Response (New File) theme={null}
  {
    "profile": "glm",
    "mtime": 1704467500000,
    "created": true,
    "warning": "Missing fields will use defaults: ANTHROPIC_BASE_URL",
    "missingFields": ["ANTHROPIC_BASE_URL"]
  }
  ```

  ```json Error (Conflict) theme={null}
  {
    "error": "File modified externally",
    "currentMtime": 1704467450000
  }
  ```
</CodeGroup>

**Features:**

* **Optimistic Locking**: Uses `expectedMtime` to detect concurrent edits
* **Automatic Backup**: Creates backup before modification in `~/.ccs/backups/`
* **Atomic Write**: Temp file + rename for crash safety
* **Validation Warning**: Alerts if required fields missing (non-blocking)

## Presets

### GET /api/settings/:profile/presets

Get saved presets for a profile.

<CodeGroup>
  ```bash Request theme={null}
  curl http://localhost:3000/api/settings/gemini/presets
  ```

  ```json Response theme={null}
  {
    "presets": [
      {
        "name": "Opus Thinking",
        "default": "gemini-claude-opus-4-5-thinking",
        "opus": "gemini-claude-opus-4-5-thinking",
        "sonnet": "gemini-claude-opus-4-5-thinking",
        "haiku": "gemini-3-flash-preview"
      },
      {
        "name": "Balanced",
        "default": "gemini-claude-sonnet-4",
        "opus": "gemini-claude-opus-4-5",
        "sonnet": "gemini-claude-sonnet-4",
        "haiku": "gemini-claude-haiku-4"
      }
    ]
  }
  ```
</CodeGroup>

***

### POST /api/settings/:profile/presets

Create a new preset configuration.

**Request Body:**

* `name` (required): Preset name
* `default` (required): Default model
* `opus` (optional): Opus tier model
* `sonnet` (optional): Sonnet tier model
* `haiku` (optional): Haiku tier model

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST http://localhost:3000/api/settings/gemini/presets \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Custom Mix",
      "default": "gemini-claude-sonnet-4",
      "opus": "gemini-claude-opus-4-5",
      "sonnet": "gemini-claude-sonnet-4",
      "haiku": "gemini-3-flash-preview"
    }'
  ```

  ```json Response (Created) theme={null}
  {
    "preset": {
      "name": "Custom Mix",
      "default": "gemini-claude-sonnet-4",
      "opus": "gemini-claude-opus-4-5",
      "sonnet": "gemini-claude-sonnet-4",
      "haiku": "gemini-3-flash-preview"
    }
  }
  ```

  ```json Error (Duplicate) theme={null}
  {
    "error": "Preset with this name already exists"
  }
  ```
</CodeGroup>

***

### DELETE /api/settings/:profile/presets/:name

Delete a preset by name.

<CodeGroup>
  ```bash Request theme={null}
  curl -X DELETE http://localhost:3000/api/settings/gemini/presets/Custom%20Mix
  ```

  ```json Response theme={null}
  {
    "success": true
  }
  ```

  ```json Error (Not Found) theme={null}
  {
    "error": "Preset not found"
  }
  ```
</CodeGroup>

## Global Auth Tokens

### GET /api/settings/auth/tokens

Get current auth token status with masked values.

<CodeGroup>
  ```bash Request theme={null}
  curl http://localhost:3000/api/settings/auth/tokens
  ```

  ```json Response theme={null}
  {
    "apiKey": {
      "value": "ccs_********************************",
      "isCustom": false
    },
    "managementSecret": {
      "value": "********",
      "isCustom": true
    }
  }
  ```
</CodeGroup>

**Fields:**

* `isCustom`: `true` if user-provided, `false` if default

***

### GET /api/settings/auth/tokens/raw

Get unmasked auth tokens.

<Warning>
  Sensitive endpoint - returns unmasked secrets. No caching headers applied.
</Warning>

<CodeGroup>
  ```bash Request theme={null}
  curl http://localhost:3000/api/settings/auth/tokens/raw
  ```

  ```json Response theme={null}
  {
    "apiKey": {
      "value": "ccs_1234567890abcdef1234567890abcdef",
      "isCustom": false
    },
    "managementSecret": {
      "value": "my-secret-key-12345",
      "isCustom": true
    }
  }
  ```
</CodeGroup>

***

### PUT /api/settings/auth/tokens

Update global auth tokens and regenerate CLIProxy config.

**Request Body:**

* `apiKey` (optional): New API key (empty string to reset to default)
* `managementSecret` (optional): New management secret

<CodeGroup>
  ```bash Request theme={null}
  curl -X PUT http://localhost:3000/api/settings/auth/tokens \
    -H "Content-Type: application/json" \
    -d '{
      "apiKey": "ccs_new-api-key-here",
      "managementSecret": "new-secret-123"
    }'
  ```

  ```json Response theme={null}
  {
    "success": true,
    "apiKey": {
      "value": "ccs_********************************",
      "isCustom": true
    },
    "managementSecret": {
      "value": "********",
      "isCustom": true
    },
    "message": "Restart CLIProxy to apply changes"
  }
  ```
</CodeGroup>

<Info>
  Changes require CLIProxy restart to take effect. Config is regenerated automatically.
</Info>

***

### POST /api/settings/auth/tokens/regenerate-secret

Generate a new 32-character management secret.

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST http://localhost:3000/api/settings/auth/tokens/regenerate-secret
  ```

  ```json Response theme={null}
  {
    "success": true,
    "managementSecret": {
      "value": "********",
      "isCustom": true
    },
    "message": "Restart CLIProxy to apply changes"
  }
  ```
</CodeGroup>

***

### POST /api/settings/auth/tokens/reset

Reset auth tokens to defaults.

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST http://localhost:3000/api/settings/auth/tokens/reset
  ```

  ```json Response theme={null}
  {
    "success": true,
    "apiKey": {
      "value": "ccs_********************************",
      "isCustom": false
    },
    "managementSecret": {
      "value": "********",
      "isCustom": false
    },
    "message": "Tokens reset to defaults. Restart CLIProxy to apply."
  }
  ```
</CodeGroup>

## Account Management

### DELETE /api/accounts/reset-default

Reset default account to CCS default.

<CodeGroup>
  ```bash Request theme={null}
  curl -X DELETE http://localhost:3000/api/accounts/reset-default
  ```

  ```json Response theme={null}
  {
    "success": true,
    "message": "Default account reset to CCS"
  }
  ```
</CodeGroup>

## Error Responses

<CodeGroup>
  ```json 400 Bad Request theme={null}
  {
    "error": "settings object is required in request body"
  }
  ```

  ```json 404 Not Found theme={null}
  {
    "error": "Settings not found"
  }
  ```

  ```json 409 Conflict theme={null}
  {
    "error": "File modified externally",
    "currentMtime": 1704467450000
  }
  ```

  ```json 500 Server Error theme={null}
  {
    "error": "Failed to write settings file",
    "message": "Detailed error message"
  }
  ```
</CodeGroup>

## Shared Data Endpoints

<Note>Available since v7.48.0</Note>

### GET /api/shared/commands

List all shared commands with descriptions.

### GET /api/shared/skills

List all shared skills with descriptions.

### GET /api/shared/agents

List all shared agents with descriptions.

### GET /api/shared/content

Load full markdown content for a shared item.

**Query Parameters:**

* `type`: `commands` | `skills` | `agents`
* `path`: Item path

### GET /api/shared/summary

Get counts and symlink status for all shared data types.

```json theme={null}
{
  "commands": 5,
  "skills": 3,
  "agents": 2,
  "total": 10,
  "symlinkStatus": "ok"
}
```

## Droid Endpoints

<Note>Available since v7.48.0</Note>

### GET /api/droid/diagnostics

Get Factory Droid binary detection and configuration status.

### GET /api/droid/settings

Read `~/.factory/settings.json` with diagnostics.

### PUT /api/droid/settings

Write to `~/.factory/settings.json` with atomic write and mtime conflict detection.

**Request Body:**

* `content`: JSON string of settings
* `expectedMtime` (optional): Optimistic locking timestamp

## Config Endpoints

<Note>Available since v7.49.0</Note>

### GET /api/config

Get current CCS config.yaml as JSON.

### PUT /api/config

Update config.yaml with validation and conflict detection.

## Security Features

* **API Key Masking**: Automatic masking for display endpoints
* **Optimistic Locking**: `mtime`-based conflict detection prevents data loss
* **Atomic Writes**: Temp file + rename ensures crash safety
* **Automatic Backups**: Previous settings saved before updates
* **No Cache Headers**: Sensitive endpoints (`/raw`, `/auth/tokens/raw`) prevent caching
* **Localhost Only**: API only accessible on 127.0.0.1
