# How to Configure Custom Model Endpoints for OpenDeepWiki: A Complete Guide

> Easily configure custom model endpoints for OpenDeepWiki. Learn to set global environment variables or use the Admin API for specific model configurations. Get started now.

- Repository: [AIDotNet/OpenDeepWiki](https://github.com/aidotnet/opendeepwiki)
- Tags: how-to-guide
- Published: 2026-02-19

---

**You can configure custom model endpoints for OpenDeepWiki by setting the global `ENDPOINT` environment variable for default behavior or creating per-model configurations via the Admin API at `/admin/tools/models`, where the `ModelConfig` entity stores custom URLs that override global settings during chat requests.**

OpenDeepWiki is an AI-driven wiki generation platform that routes LLM requests through a flexible endpoint configuration system. Understanding how to configure custom model endpoints for OpenDeepWiki enables you to integrate private inference servers, corporate proxies, or multiple cloud providers within a single deployment. The architecture implements a hierarchical resolution strategy where per-model settings in the `ModelConfig` entity take precedence over global fallback values defined in `AiRequestOptions`.

## Global Endpoint Configuration via Environment Variables

The system defines baseline connectivity parameters through the `AiRequestOptions` class bound during application startup. In [`src/OpenDeepWiki/Program.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/src/OpenDeepWiki/Program.cs), the configuration pipeline registers these options and implements a fallback mechanism that checks the `ENDPOINT` environment variable when no explicit value exists in [`appsettings.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.json).

The registration logic appears at lines 31-40:

```csharp
builder.Services.AddOptions<AiRequestOptions>()
    .Bind(builder.Configuration.GetSection("AI"))
    .PostConfigure(options => {
        if (string.IsNullOrWhiteSpace(options.Endpoint)) {
            // Fallback to ENV var ENDPOINT if not set in appsettings
            options.Endpoint = builder.Configuration["ENDPOINT"];
        }
    });

```

When a model configuration lacks a specific endpoint, the chat service automatically resolves to this global value. This approach suits homogeneous environments where all models route through a single gateway or API proxy.

## Per-Model Endpoint Configuration via Admin API

For heterogeneous deployments requiring different endpoints per provider, OpenDeepWiki stores custom configurations in the `ModelConfig` entity defined in [`src/OpenDeepWiki.Entities/Tools/ModelConfig.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/src/OpenDeepWiki.Entities/Tools/ModelConfig.cs). This entity includes nullable fields for `Endpoint` and `ApiKey`, allowing granular overrides at the individual model level.

The entity structure at lines 34-42 specifies:

```csharp
public class ModelConfig : AggregateRoot<string>
{
    public string? Endpoint { get; set; }      // Custom API endpoint
    public string? ApiKey { get; set; }       // Optional per-model key
    // Additional properties omitted for brevity
}

```

### Creating a Custom Model Configuration

Administrators manage these records through the REST API exposed in [`src/OpenDeepWiki/Endpoints/Admin/AdminToolsEndpoints.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/src/OpenDeepWiki/Endpoints/Admin/AdminToolsEndpoints.cs). The `POST /admin/tools/models` endpoint accepts a `ModelConfigRequest` payload and persists the configuration via `AdminToolsService.CreateModelConfigAsync`.

The endpoint registration at lines 78-84 handles incoming requests:

```csharp
modelGroup.MapPost("/", async (
    [FromBody] ModelConfigRequest request,
    [FromServices] IAdminToolsService toolsService) =>
{
    var result = await toolsService.CreateModelConfigAsync(request);
    return Results.Ok(new { success = true, data = result });
});

```

The service implementation in [`src/OpenDeepWiki/Services/Admin/AdminToolsService.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/src/OpenDeepWiki/Services/Admin/AdminToolsService.cs) (lines 301-310) maps the request to the entity:

```csharp
public async Task<ModelConfigDto> CreateModelConfigAsync(ModelConfigRequest request)
{
    var config = new ModelConfig {
        Id = Guid.NewGuid().ToString(),
        Name = request.Name,
        Provider = request.Provider,
        ModelId = request.ModelId,
        Endpoint = request.Endpoint,   // Custom endpoint stored here
        ApiKey = request.ApiKey,
        // ...
    };
    _context.ModelConfigs.Add(config);
    await _context.SaveChangesAsync();
    // ...
}

```

### How the Chat Service Resolves Endpoints

During request processing, `ChatAssistantService` located in [`src/OpenDeepWiki/Services/Chat/ChatAssistantService.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/src/OpenDeepWiki/Services/Chat/ChatAssistantService.cs) retrieves the appropriate configuration and constructs `AiRequestOptions`. The resolution logic at lines 432-435 demonstrates the priority system:

```csharp
var modelConfig = await GetModelConfigAsync(request.ModelId, config, cancellationToken);

var requestOptions = new AiRequestOptions {
    ApiKey = modelConfig.ApiKey,           // Falls back to global if null
    Endpoint = modelConfig.Endpoint,       // Falls back to global if null
    RequestType = ParseRequestType(modelConfig.Provider)
};

```

If `modelConfig.Endpoint` contains a non-null value, the system routes the request to that specific URL rather than the global default.

## Configuration Verification Checklist

Before deploying custom endpoints to production, verify the following:

- **Global fallback**: Confirm the `ENDPOINT` environment variable or [`appsettings.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.json) section `AI:Endpoint` contains a valid URL if relying on default behavior
- **Database record**: Query the `ModelConfigs` table to ensure the `Endpoint` field is populated for the specific model ID
- **API response**: Verify that `POST /admin/tools/models` returns HTTP 200 with a success flag and the generated `Id`
- **Request payload**: Ensure chat requests include the correct `ModelId` corresponding to your custom configuration
- **Runtime logs**: Inspect logs for entries showing the resolved endpoint URL during chat stream initialization

## Practical Configuration Examples

### Setting a Global Fallback Endpoint

Configure the environment variable before launching the application:

```bash
export ENDPOINT="https://api.openai.com/v1/chat/completions"
export CHAT_API_KEY="sk-XXXXXXXXXXXXXXXX"
dotnet run --project src/OpenDeepWiki/OpenDeepWiki.csproj

```

Alternatively, add the configuration to [`appsettings.Development.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.Development.json):

```json
{
  "AI": {
    "Endpoint": "https://api.openai.com/v1/chat/completions",
    "ApiKey": "sk-XXXXXXXXXXXXXXXX"
  }
}

```

### Creating a Model with Custom Endpoint via API

Use the administrative endpoint to register a model routing through a private proxy:

```bash
curl -X POST http://localhost:5000/admin/tools/models \
  -H "Content-Type: application/json" \
  -d '{
        "Name": "MyCustomClaude",
        "Provider": "Anthropic",
        "ModelId": "claude-3-5-sonnet-20240620",
        "Endpoint": "https://my-proxy.example.com/v1/claude",
        "ApiKey": "my-proxy-key",
        "IsDefault": false,
        "IsActive": true,
        "Description": "Claude via internal proxy"
      }'

```

The API returns the persisted configuration including the generated identifier:

```json
{
  "success": true,
  "data": {
    "Id": "c9e5a7b5-2f8d-4a1e-9f4c-7e2f6d3a1b9c",
    "Name": "MyCustomClaude",
    "Endpoint": "https://my-proxy.example.com/v1/claude",
    "HasApiKey": true,
    "IsActive": true
  }
}

```

### Sending Chat Requests to Custom Endpoints

Reference the custom model by its `Id` in chat requests:

```json
POST http://localhost:5000/chat/assistant/stream
Content-Type: application/json

{
  "ModelId": "c9e5a7b5-2f8d-4a1e-9f4c-7e2f6d3a1b9c",
  "Messages": [
    { "Role": "user", "Content": "Summarize the repository structure." }
  ]
}

```

The service resolves the custom endpoint from the database and routes the request accordingly.

## Summary

- **Global configuration** uses the `ENDPOINT` environment variable or `AI` configuration section in [`appsettings.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.json), registered via `AddOptions<AiRequestOptions>()` in [`Program.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/Program.cs)
- **Per-model configuration** overrides globals through the `ModelConfig` entity stored in the database, manageable via `POST /admin/tools/models`
- **Resolution priority** follows a hierarchy: per-model `Endpoint` property → global `AiRequestOptions.Endpoint` → null (error condition)
- **Administrative functions** are implemented in [`AdminToolsService.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/AdminToolsService.cs) with CRUD operations for `ModelConfig` records
- **Runtime resolution** occurs in [`ChatAssistantService.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ChatAssistantService.cs), which builds `AiRequestOptions` using the resolved endpoint and API key

## Frequently Asked Questions

### Can I configure different endpoints for different models in OpenDeepWiki?

Yes. Create separate `ModelConfig` records via the Admin API at `/admin/tools/models`, each specifying a unique `Endpoint` URL. The `ChatAssistantService` resolves the appropriate endpoint based on the `ModelId` provided in the chat request, allowing you to route individual models to different providers or proxies within the same instance.

### What happens if a model configuration has no endpoint specified?

When the `Endpoint` property of a `ModelConfig` entity is null or empty, the system falls back to the global `AiRequestOptions.Endpoint` value configured during startup. This fallback is established in [`Program.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/Program.cs) through the `PostConfigure` delegate, which checks the `ENDPOINT` environment variable if no explicit value exists in configuration files.

### How do I update an existing model's endpoint?

Send a PUT request to `/admin/tools/models/{id}` with the updated `Endpoint` value in the JSON payload. The `AdminToolsService.UpdateModelConfigAsync` method handles the persistence, updating the `ModelConfig` entity in the database. Subsequent chat requests using that `ModelId` will immediately use the new endpoint without requiring application restart.

### Is the API key also configurable per model or only globally?

Both. The `ModelConfig` entity includes an `ApiKey` property that, when populated, overrides the global API key for that specific model. If left null, the system uses the global key from `AiRequestOptions`. This dual-layer approach supports scenarios where different models require different authentication credentials or where some models use unauthenticated local endpoints while others use cloud APIs.