# How to Implement Custom API Keys and Base URLs for AI Models in Next AI Draw.io

> Implement custom API keys & base URLs for AI models in Next AI Draw.io using apiKeyEnv and baseUrlEnv. Enable multi-tenancy and self-hosted endpoints without core code changes.

- Repository: [Dayuan Jiang/next-ai-draw-io](https://github.com/DayuanJiang/next-ai-draw-io)
- Tags: how-to-guide
- Published: 2026-07-13

---

**Next AI Draw.io supports custom environment variable names for API keys and base URLs through the `apiKeyEnv` and `baseUrlEnv` fields in `ServerProviderSchema`, enabling multi-tenant deployments and self-hosted endpoints without modifying core SDK code.**

The open-source repository `DayuanJiang/next-ai-draw-io` provides a flexible architecture for managing multiple AI providers. You can implement custom API keys and base URLs for AI models in Next AI Draw.io by configuring the [`ai-models.json`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/ai-models.json) file and leveraging the resolution logic in [`lib/ai-providers.ts`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/lib/ai-providers.ts). This approach allows teams to rotate credentials, support multiple teams with separate keys, or route traffic to private endpoints.

## Configure Custom Environment Variables in ai-models.json

The server-side model configuration uses **`ServerProviderSchema`** defined in [`lib/server-model-config.ts`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/lib/server-model-config.ts) to validate custom environment variable mappings. Each provider entry can specify `apiKeyEnv` (string or array of strings) and `baseUrlEnv` (string) to override default SDK behavior.

Create or edit [`ai-models.json`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/ai-models.json) at the project root:

```json
{
  "providers": [
    {
      "name": "OpenAI Production",
      "provider": "openai",
      "models": ["gpt-4o", "gpt-4o-mini"],
      "apiKeyEnv": ["OPENAI_API_KEY_TEAM_A", "OPENAI_API_KEY_TEAM_B"],
      "baseUrlEnv": "OPENAI_CUSTOM_BASE_URL",
      "default": true
    }
  ]
}

```

Alternatively, set the `AI_MODELS_CONFIG` environment variable to a JSON string with the same shape. The `loadFlattenedServerModels()` function in [`lib/server-model-config.ts`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/lib/server-model-config.ts) reads this configuration and flattens each model entry while preserving the custom environment variable names:

```ts
flattened.push({
  id,
  modelId,
  provider: p.provider,
  providerLabel,
  isDefault,
  apiKeyEnv: p.apiKeyEnv,
  baseUrlEnv: p.baseUrlEnv,
})

```

Add the corresponding secrets to your `.env.local`:

```ini
OPENAI_API_KEY_TEAM_A=sk-****************************
OPENAI_API_KEY_TEAM_B=sk-****************************
OPENAI_CUSTOM_BASE_URL=https://my.private-openai.example.com/v1

```

When `apiKeyEnv` is an array, the system randomly selects a defined key for load balancing.

## Resolution Logic for API Keys and Base URLs

The core credential resolution happens in [`lib/ai-providers.ts`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/lib/ai-providers.ts) through three key functions that determine which values take precedence.

### The resolveApiKey Function

The **`resolveApiKey`** function implements a fallback chain:

1. User-provided `overrides.apiKey` (highest priority)
2. Custom environment variable(s) from `overrides.apiKeyEnv`
3. Default environment variable (e.g., `OPENAI_API_KEY`)

When multiple keys are configured, the function randomly selects one to distribute load:

```ts
function resolveApiKey(overrides, defaultEnvVar) {
  if (overrides?.apiKey) return overrides.apiKey;
  if (overrides?.apiKeyEnv) {
    if (Array.isArray(overrides.apiKeyEnv)) {
      const valid = overrides.apiKeyEnv.filter(v => process.env[v]);
      if (valid.length) return process.env[valid[Math.random() * valid.length | 0]];
    } else {
      return process.env[overrides.apiKeyEnv];
    }
  }
  return process.env[defaultEnvVar];
}

```

### The resolveBaseURL Function

The **`resolveBaseURL`** function determines the endpoint based on credential ownership. If a user supplies their own API key, only their `baseUrl` or the provider default is used. Otherwise, the server-side `serverBaseUrl` from `baseUrlEnv` is applied.

The **`resolveBaseUrlEnv`** wrapper reads the value of a custom base URL environment variable, falling back to the default if not specified.

## Enabling User Overrides in the UI

The frontend can expose custom credentials through the **`ClientOverrides`** interface defined in [`lib/ai-providers.ts`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/lib/ai-providers.ts):

```ts
export interface ClientOverrides {
  provider?: string | null;
  baseUrl?: string | null;
  apiKey?: string | null;
  modelId?: string | null;
  apiKeyEnv?: string | string[];
  baseUrlEnv?: string;
}

```

The **[`components/provider-credentials-fields.tsx`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/components/provider-credentials-fields.tsx)** component renders input fields that map user entries to these override properties:

```tsx
<TextInput
  label="API Key"
  placeholder={model.apiKeyEnv?.join(', ') || 'API key'}
  value={overrides.apiKey ?? ''}
  onChange={e => setOverrides({ ...overrides, apiKey: e.target.value })}
/>

<TextInput
  label="Base URL"
  placeholder={model.baseUrlEnv || 'https://…'}
  value={overrides.baseUrl ?? ''}
  onChange={e => setOverrides({ ...overrides, baseUrl: e.target.value })}
/>

```

When the user selects a model, the application calls `validateProviderCredentials(provider, overrides?.apiKeyEnv)` to ensure at least one of the supplied environment variables is present before instantiation.

## Practical Implementation Example

To use a custom provider configuration in your application code, call `getAIModel` with overrides referencing your custom environment variables:

```ts
// src/lib/custom-openai-example.ts
import { getAIModel } from '@/lib/ai-providers';

export async function generateDiagram(prompt: string) {
  const overrides = {
    modelId: 'gpt-4o',
    apiKeyEnv: ['OPENAI_API_KEY_TEAM_A', 'OPENAI_API_KEY_TEAM_B'],
    baseUrlEnv: 'OPENAI_CUSTOM_BASE_URL',
  };

  const { model } = getAIModel(overrides);

  const response = await model.generate({
    messages: [{ role: 'user', content: prompt }],
  });

  return response;
}

```

This configuration instructs the factory to:
- Randomly select either `OPENAI_API_KEY_TEAM_A` or `OPENAI_API_KEY_TEAM_B`
- Route requests to `https://my.private-openai.example.com/v1`
- Return a ready-to-use AI SDK model instance

## Summary

- **Declare custom environment variables** using `apiKeyEnv` and `baseUrlEnv` in [`ai-models.json`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/ai-models.json) or the `AI_MODELS_CONFIG` environment variable
- **Load-balance multiple keys** by providing an array of environment variable names, which `resolveApiKey` selects from randomly
- **Validate credentials** automatically through `validateProviderCredentials` before model instantiation
- **Override at runtime** via `ClientOverrides` in [`components/provider-credentials-fields.tsx`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/components/provider-credentials-fields.tsx) for user-specific credentials
- **Route to private endpoints** by specifying custom `baseUrlEnv` values that resolve through `resolveBaseURL`

## Frequently Asked Questions

### Can I specify multiple API keys for load balancing?

Yes. Set `apiKeyEnv` to an array of environment variable names in your provider configuration. The `resolveApiKey` function in [`lib/ai-providers.ts`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/lib/ai-providers.ts) filters for defined variables and randomly selects one, distributing requests across multiple keys automatically.

### What happens if both custom and default environment variables are set?

The resolution logic follows strict precedence: user-provided `apiKey` overrides everything, then custom `apiKeyEnv` values are checked, and finally the default SDK environment variable (like `OPENAI_API_KEY`) is used as fallback. This ensures explicit overrides always take priority.

### How do I configure a self-hosted OpenAI-compatible endpoint?

Define a `baseUrlEnv` field in your [`ai-models.json`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/ai-models.json) provider entry pointing to your custom environment variable. Set that variable to your self-hosted URL (e.g., `https://localhost:3000/v1`). The `resolveBaseURL` function will route requests there while still using the OpenAI SDK provider implementation.

### Is it possible to override the base URL on the client side?

Yes. Users can input custom base URLs through the [`components/provider-credentials-fields.tsx`](https://github.com/DayuanJiang/next-ai-draw-io/blob/main/components/provider-credentials-fields.tsx) interface, which populates `ClientOverrides.baseUrl`. When a user provides their own API key, the `resolveBaseURL` logic respects their custom base URL over the server-side `baseUrlEnv` configuration.