# How to Configure Custom OpenAI-Compatible Endpoints for AI Summaries in Meetily

> Configure custom OpenAI-compatible endpoints for AI summaries in Meetily. Learn how to route summary requests to any compatible service using a custom endpoint URL.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: how-to-guide
- Published: 2026-07-20

---

**Meetily routes summary requests to any OpenAI-compatible service by accepting a custom endpoint URL at runtime, which the Rust backend validates and appends with `/chat/completions` to generate meeting summaries.**

The open-source meeting assistant Meetily (Zackriya-Solutions/meetily) decouples its summary engine from specific AI providers through a dynamic configuration system. When you configure custom OpenAI-compatible endpoints for summaries, the application forwards your requests to private LLMs, Azure OpenAI, or proxy services while maintaining the standard OpenAI API contract.

## How the Custom Endpoint Integration Works

Meetily uses a three-layer architecture to process summary requests with configurable endpoints:

1. **Frontend invocation** – TypeScript code calls the Tauri command `builtin_ai_generate_summary` with the `customOpenAIEndpoint` parameter.
2. **Command routing** – The Rust handler in [`src-tauri/src/summary/summary_engine/commands.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/summary_engine/commands.rs) forwards the endpoint to the LLM client.
3. **Request construction** – The `generate_summary` function in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs) builds the final URL by trimming trailing slashes and appending `/chat/completions`.

The endpoint is not hard-coded. The `LLMProvider::CustomOpenAI` variant expects the URL at runtime, allowing you to switch between OpenAI, self-hosted models, or compatible proxies without rebuilding the application.

## Frontend Implementation: Calling the Tauri Command

To trigger a summary with a custom endpoint, invoke the `builtin_ai_generate_summary` command from your React or TypeScript frontend. Pass the provider identifier `custom-openai` and the full URL to your compatible API.

```typescript
import { invoke } from '@tauri-apps/api/tauri';

/**
 * Generate a summary using a private OpenAI-compatible service.
 */
async function generateSummaryViaCustomOpenAI(
  transcript: string,
  apiKey: string,
  model = 'gpt-4',
  endpoint = 'https://my-openai-proxy.example.com'
) {
  const result = await invoke<string>('builtin_ai_generate_summary', {
    provider: 'custom-openai',           // Maps to LLMProvider::CustomOpenAI
    modelName: model,
    apiKey,
    systemPrompt: 'You are a concise meeting-summary assistant.',
    userPrompt: transcript,
    customOpenAIEndpoint: endpoint,      // The custom endpoint URL
    maxTokens: 1024,
    temperature: 0.7,
    topP: 0.9,
  });

  return result; // Returns the generated summary text
}

```

The `customOpenAIEndpoint` value is passed as an optional string to the Rust backend, where it becomes the base URL for all subsequent API calls.

## Backend Handler: Routing to the LLM Client

On the Rust side, the `builtin_ai_generate_summary` command in [`src-tauri/src/summary/summary_engine/commands.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/summary_engine/commands.rs) receives the endpoint and forwards it to the core generation logic. The command signature accepts `custom_openai_endpoint` as an `Option<String>` and passes it directly to the LLM client without modification.

```rust
#[tauri::command]
pub async fn builtin_ai_generate_summary(
    provider: String,
    model_name: String,
    api_key: String,
    system_prompt: String,
    user_prompt: String,
    custom_openai_endpoint: Option<String>,
    // ... other optional args ...
) -> Result<String, String> {
    let provider = LLMProvider::from_str(&provider)?;
    let client = reqwest::Client::new();

    // Forward the optional endpoint to the core generator
    summary::llm_client::generate_summary(
        &client,
        &provider,
        &model_name,
        &api_key,
        &system_prompt,
        &user_prompt,
        None,                       // ollama_endpoint – not used here
        custom_openai_endpoint.as_deref(),
        max_tokens,
        temperature,
        top_p,
        None,                       // app_data_dir – not needed for remote service
        None,                       // cancellation token
    )
    .await
}

```

This handler ensures that when the `LLMProvider` is `CustomOpenAI`, the optional endpoint URL propagates to the HTTP client logic.

## LLM Client URL Construction

The actual HTTP request construction happens in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs). Lines 173-179 handle the URL formatting for custom endpoints by trimming any trailing slashes and appending the standard OpenAI chat completions path.

```rust
// From src-tauri/src/summary/llm_client.rs
let url = format!(
    "{}/chat/completions",
    endpoint.trim_end_matches('/')
);

```

This implementation guarantees that whether you provide `https://api.example.com`, `https://api.example.com/`, or `https://api.example.com/v1`, the resulting request targets `https://api.example.com/chat/completions` (or `https://api.example.com/v1/chat/completions` respectively).

## Persisting Settings Between Sessions

Meetily stores user-defined configuration in JSON format within the application data directory. When you update the "Custom OpenAI endpoint" field in the settings UI, the application writes the value to the internal config store (managed in [`src-tauri/src/config.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/config.rs)).

The persisted JSON structure follows this pattern:

```json
{
  "summary": {
    "customOpenAIEndpoint": "https://my-openai-proxy.example.com"
  }
}

```

On subsequent summary requests, the frontend reads this stored value and passes it as the `customOpenAIEndpoint` argument to the Tauri command, ensuring your custom endpoint persists across application restarts.

## Summary

- **Dynamic routing**: Meetily accepts custom OpenAI-compatible endpoints at runtime via the `customOpenAIEndpoint` parameter in `builtin_ai_generate_summary`.
- **URL handling**: The backend automatically formats the endpoint by trimming trailing slashes and appending `/chat/completions` in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs).
- **Provider selection**: Use the provider string `custom-openai` to trigger the custom endpoint logic in the `LLMProvider` enum.
- **Persistence**: Endpoint settings are stored in JSON configuration files within the app data directory and retrieved automatically for each summary generation request.

## Frequently Asked Questions

### What URL format should I use for the custom endpoint?

Provide the base URL of your OpenAI-compatible service without the `/chat/completions` path. According to the source code in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs), the backend automatically handles trailing slashes. For example, use `https://api.example.com/v1` or `https://api.example.com`—both resolve correctly to `{endpoint}/chat/completions`.

### Is the API key sent directly to the custom endpoint?

Yes. The `api_key` parameter you pass to `builtin_ai_generate_summary` is included in the `Authorization` header of the HTTP request sent to your custom endpoint. The backend does not filter or modify the key, so ensure your endpoint implements standard OpenAI authentication expectations.

### Can I use Azure OpenAI or other OpenAI-compatible services?

Absolutely. Meetily's `LLMProvider::CustomOpenAI` variant works with any service implementing the OpenAI chat completions API schema, including Azure OpenAI, Ollama with OpenAI compatibility mode, or custom proxies. Simply provide the appropriate endpoint URL and model name when calling the summary command.

### Where are the custom endpoint settings stored?

User settings are persisted in JSON files within the application's data directory, managed through [`src-tauri/src/config.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/config.rs). The specific key `summary.customOpenAIEndpoint` stores your custom URL, which the frontend retrieves and passes to the Rust backend during each summary generation request.