> ## Documentation Index
> Fetch the complete documentation index at: https://copilot-api.nick3.top/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure Copilot API with config.json

> Set API keys, model aliases, per-model prompts, reasoning efforts, custom providers, and logging verbosity through the config.json file.

Copilot API reads its settings from a single JSON file on startup. You can use this file to control authentication, model routing, upstream providers, and logging without touching command-line flags.

## File location

| Platform      | Default path                                         |
| ------------- | ---------------------------------------------------- |
| Linux / macOS | `~/.local/share/copilot-api/config.json`             |
| Windows       | `%USERPROFILE%\.local\share\copilot-api\config.json` |

To use a different directory, set the `COPILOT_API_HOME` environment variable or pass `--api-home=<path>` before your subcommand:

```bash theme={null}
npx @nick3/copilot-api@latest --api-home=/opt/copilot-data start
```

## Default config shape

If the file does not exist, Copilot API creates it automatically with the following defaults:

```json theme={null}
{
  "auth": {
    "apiKeys": []
  },
  "providers": {},
  "extraPrompts": {
    "gpt-5-mini": "<built-in exploration prompt>",
    "gpt-5.3-codex": "<built-in commentary prompt>",
    "gpt-5.4-mini": "<built-in commentary prompt>",
    "gpt-5.4": "<built-in commentary prompt>"
  },
  "smallModel": "gpt-5-mini",
  "accountAffinity": true,
  "responsesApiContextManagementModels": [],
  "modelReasoningEfforts": {
    "gpt-5-mini": "low",
    "gpt-5.3-codex": "xhigh",
    "gpt-5.4-mini": "xhigh",
    "gpt-5.4": "xhigh"
  },
  "allowOriginalModelNamesForAliases": false,
  "useFunctionApplyPatch": true,
  "forceAgent": false,
  "compactUseSmallModel": true,
  "messageStartInputTokensFallback": false,
  "modelRefreshIntervalHours": 24,
  "sessionAffinityRetentionDays": 7,
  "useMessagesApi": true,
  "useResponsesApiWebSearch": true,
  "logLevel": "info"
}
```

<Note>
  Missing default entries (extra prompts, reasoning efforts) are merged back automatically each time the server starts, without overwriting values you have customized.
</Note>

## Configuration options

<AccordionGroup>
  <Accordion title="auth.apiKeys">
    An array of strings. Requests to protected routes must include one of these keys as `x-api-key: <key>` or `Authorization: Bearer <key>`. Supports multiple keys so you can rotate credentials without downtime.

    ```json theme={null}
    {
      "auth": {
        "apiKeys": ["key-abc123", "key-def456"]
      }
    }
    ```

    If the array is empty or the field is omitted, authentication is disabled and all requests are accepted.

    <Warning>
      The legacy `apiKey` top-level field and `COPILOT_API_KEY` environment variable are still accepted for migration but are deprecated. Prefer `auth.apiKeys` for new setups.
    </Warning>
  </Accordion>

  <Accordion title="extraPrompts">
    A map of `model → prompt string`. The prompt is appended to the first system message when the proxy translates an Anthropic-style request for Copilot. Use this to inject per-model guardrails, coding style rules, or behavioral guidance.

    ```json theme={null}
    {
      "extraPrompts": {
        "gpt-5.4": "Always respond in English.",
        "gpt-5-mini": "Be concise."
      }
    }
    ```

    The built-in prompts for `gpt-5.3-codex`, `gpt-5.4-mini`, and `gpt-5.4` enable phase-aware commentary (short progress updates before tools or deeper reasoning). If you supply your own entry for one of these models, it replaces the built-in prompt for that model only.
  </Accordion>

  <Accordion title="smallModel">
    The model used for tool-less warmup probes, compact/background requests, and other housekeeping turns so they do not consume premium quota. Defaults to `"gpt-5-mini"`.

    ```json theme={null}
    {
      "smallModel": "gpt-5-mini"
    }
    ```

    If the value points to an aliased target and original names are blocked, the proxy resolves it to the preferred alias automatically.
  </Accordion>

  <Accordion title="accountAffinity">
    When `true` (default), requests from the same session for the same model are routed back to the account that last handled them successfully. This applies to both free and premium models and helps preserve context continuity across turns.

    ```json theme={null}
    {
      "accountAffinity": false
    }
    ```

    Set to `false` to use sequential routing for all models instead. See [Manage multiple Copilot accounts](/configuration/multi-account) for more detail.
  </Accordion>

  <Accordion title="modelReasoningEfforts">
    A map of `model → effort level`. Controls the `reasoning.effort` parameter forwarded to the Copilot Responses API. Allowed values: `"none"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`. Models not listed default to `"high"`.

    ```json theme={null}
    {
      "modelReasoningEfforts": {
        "gpt-5.4": "xhigh",
        "gpt-5-mini": "low"
      }
    }
    ```
  </Accordion>

  <Accordion title="modelAliases">
    A map of `alias → { target, allowOriginal? }` that lets downstream clients use custom model names. Alias keys are normalized (trimmed, lowercased). The optional `allowOriginal` field overrides the global `allowOriginalModelNamesForAliases` default for that specific alias.

    ```json theme={null}
    {
      "modelAliases": {
        "fast": { "target": "gpt-5-mini" },
        "smart": { "target": "gpt-5.4", "allowOriginal": true }
      }
    }
    ```

    * Aliases cannot map to themselves (case-insensitive).
    * Conflicting normalized aliases are rejected.
    * Reserved keys (`__proto__`, `constructor`, `prototype`) are blocked by the Admin API.
  </Accordion>

  <Accordion title="allowOriginalModelNamesForAliases">
    Global default for whether aliased target model names can be called directly. When `false` (default), a client requesting `gpt-5.4` is rejected if that model is an alias target and no alias explicitly sets `allowOriginal: true`. When `true`, targets are reachable by their original names unless all their aliases explicitly block them.

    ```json theme={null}
    {
      "allowOriginalModelNamesForAliases": false
    }
    ```
  </Accordion>

  <Accordion title="responsesApiContextManagementModels">
    A list of model IDs that should receive Responses API `context_management` compaction instructions. When a model in this list is used, the proxy keeps only the latest compaction carrier on follow-up turns, reducing unnecessary context re-sending.

    ```json theme={null}
    {
      "responsesApiContextManagementModels": ["gpt-5.4", "gpt-5.4-mini"]
    }
    ```
  </Accordion>

  <Accordion title="useFunctionApplyPatch">
    When `true` (default), `POST /v1/responses` automatically converts a tools entry with `{ "type": "custom", "name": "apply_patch" }` into an OpenAI-style `function` tool with a parameter schema, for upstream compatibility. Set to `false` to leave custom tools unchanged.

    ```json theme={null}
    {
      "useFunctionApplyPatch": false
    }
    ```
  </Accordion>

  <Accordion title="compactUseSmallModel">
    When `true` (default), detected compact requests (from Claude Code or opencode compact mode) are routed to `smallModel` automatically, avoiding premium usage for short background tasks.

    ```json theme={null}
    {
      "compactUseSmallModel": false
    }
    ```
  </Accordion>

  <Accordion title="useMessagesApi">
    When `true` (default), Claude-family models that support Copilot's native `/v1/messages` endpoint use the Messages API path. This preserves Anthropic-native behavior including `interleaved-thinking`, `advanced-tool-use`, and `context-management` betas. Set to `false` to skip the Messages API path and fall back to `/responses` or `/chat/completions`.

    ```json theme={null}
    {
      "useMessagesApi": false
    }
    ```
  </Accordion>

  <Accordion title="useResponsesApiWebSearch">
    When `true` (default), `POST /v1/responses` keeps tools with `type: "web_search"` and forwards them upstream. Set to `false` to strip web search tools before the Copilot request is sent.

    ```json theme={null}
    {
      "useResponsesApiWebSearch": false
    }
    ```
  </Accordion>

  <Accordion title="logLevel">
    Controls verbosity for handler file logs written to `logs/*.log`. Allowed values: `"error"`, `"warn"`, `"info"` (default), `"debug"`. Use `"debug"` when you need payload-level or stream-level diagnostics.

    ```json theme={null}
    {
      "logLevel": "debug"
    }
    ```

    <Note>
      `--verbose` no longer enables debug-level file logging. Set `"logLevel": "debug"` explicitly in `config.json` when you need detailed handler logs.
    </Note>
  </Accordion>

  <Accordion title="anthropicApiKey">
    An optional Anthropic API key used to forward Claude token counting requests to Anthropic's real `/v1/messages/count_tokens` endpoint instead of using GPT tokenizer estimation. This produces exact counts, which prevents tools like Claude Code from compacting too late.

    ```json theme={null}
    {
      "anthropicApiKey": "sk-ant-..."
    }
    ```

    You can also set this via the `ANTHROPIC_API_KEY` environment variable. The token counting endpoint is free; the \$5 minimum balance is only required to activate API access.
  </Accordion>

  <Accordion title="modelRefreshIntervalHours">
    The interval, in hours, at which the proxy refreshes the model list for each account in the background. Set to `0` to disable refresh entirely. Defaults to `24`.

    ```json theme={null}
    {
      "modelRefreshIntervalHours": 12
    }
    ```
  </Accordion>

  <Accordion title="sessionAffinityRetentionDays">
    Number of days to retain session affinity bindings before they are cleaned up. Defaults to `7`.

    ```json theme={null}
    {
      "sessionAffinityRetentionDays": 14
    }
    ```
  </Accordion>

  <Accordion title="providers">
    A map of named upstream providers. Each key becomes a route prefix. See [Custom providers](#custom-providers) below for full details.
  </Accordion>
</AccordionGroup>

## Custom providers

The `providers` field lets you proxy requests to external Anthropic-compatible APIs through Copilot API. Each key you define (for example `"custom"`) becomes a URL prefix:

* `POST /custom/v1/messages`
* `GET /custom/v1/models`
* `POST /custom/v1/messages/count_tokens`

Only `type: "anthropic"` is supported currently.

### Provider fields

| Field               | Required | Description                                                                                                                                             |
| ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`              | No       | Provider type. Only `"anthropic"` is supported. Defaults to `"anthropic"`.                                                                              |
| `enabled`           | No       | Set to `false` to disable the provider without removing it. Defaults to `true`.                                                                         |
| `baseUrl`           | Yes      | Base URL of the upstream API, without a trailing `/v1/messages`.                                                                                        |
| `apiKey`            | Yes      | Credential forwarded upstream.                                                                                                                          |
| `authType`          | No       | How `apiKey` is sent. `"x-api-key"` (default) sends an `x-api-key` header; `"authorization"` sends `Authorization: Bearer <apiKey>`.                    |
| `adjustInputTokens` | No       | When `true`, subtracts `cache_read_input_tokens` and `cache_creation_input_tokens` from `input_tokens` in the usage response.                           |
| `models`            | No       | Per-model defaults. Each key is a model ID; value supports `temperature`, `topP`, and `topK`. These are applied when the request does not specify them. |

### Example

```json theme={null}
{
  "providers": {
    "custom": {
      "type": "anthropic",
      "enabled": true,
      "baseUrl": "https://your-provider.example",
      "apiKey": "sk-your-provider-key",
      "authType": "x-api-key",
      "adjustInputTokens": false,
      "models": {
        "kimi-k2.5": {
          "temperature": 1,
          "topP": 0.95
        }
      }
    }
  }
}
```

With this config, you can call the provider at `http://localhost:4141/custom/v1/messages`.

## Applying config changes

Changes you make through the Admin UI or Admin API are validated, written to disk, and applied immediately — no restart needed.

If you edit `config.json` manually in a text editor, restart the server to pick up the changes. Alternatively, the Admin API's `GET /api/admin/config` endpoint refreshes the cached config without a full restart:

```bash theme={null}
curl http://localhost:4141/api/admin/config
```

<Tip>
  Unknown keys in `config.json` are rejected by the Admin API. If you add a field through the UI, the change is validated before being written.
</Tip>
