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

> Learn to configure a custom OpenAI-compatible endpoint for Meetily AI summaries. This guide explains how to pass the endpoint URL at runtime for seamless integration with your Rust backend.

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

---

**Meetily routes AI summary requests to a custom OpenAI-compatible endpoint by passing the URL at runtime to the `builtin_ai_generate_summary` Tauri command, which concatenates the endpoint with `/chat/completions` in the Rust backend.**

Meetily's architecture supports any OpenAI-compatible API—including private hosted models, Azure OpenAI, or third-party proxies—without hard-coding URLs. The endpoint configuration flows from the React frontend through a Tauri command to the LLM client, where the request URL is constructed dynamically. This guide walks through the implementation details in the Zackriya-Solutions/meetily repository.

## How the Custom Endpoint Flow Works

When you trigger an AI summary with a custom provider, the request follows a three-stage pipeline:

1. **Frontend invocation**: The React UI calls the Tauri command `builtin_ai_generate_summary` with the `customOpenAIEndpoint` parameter.
2. **Command routing**: The Rust command 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. **URL construction**: In [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs), the `generate_summary` function validates the `LLMProvider::CustomOpenAI` variant and builds the final request URL by appending `/chat/completions` to your custom endpoint.

The endpoint is never stored as a compile-time constant; it is always supplied at runtime through the `custom_openai_endpoint` argument.

## Backend Implementation: The LLM Client

The core logic resides in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs). When the provider is set to `CustomOpenAI`, the `generate_summary` function constructs the API URL by trimming trailing slashes and appending the chat completions path:

```rust
// Lines 173-179 of llm_client.rs
let url = format!("{}/chat/completions", endpoint.trim_end_matches('/'));

```

This ensures compatibility with endpoints that may or may not include a trailing slash. The function then uses `reqwest` to POST the JSON payload to this constructed URL, passing the `api_key` in the Authorization header exactly as it would for the standard OpenAI API.

The Tauri command that exposes this functionality to the frontend is defined 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):

```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();

    summary::llm_client::generate_summary(
        &client,
        &provider,
        &model_name,
        &api_key,
        &system_prompt,
        &user_prompt,
        None,                       // ollama_endpoint
        custom_openai_endpoint.as_deref(), // <-- custom endpoint passed here
        max_tokens,
        temperature,
        top_p,
        None,                       // app_data_dir
        None,                       // cancellation token
    )
    .await
}

```

## Frontend Integration: Calling the Tauri Command

From the React frontend, you invoke the command using `@tauri-apps/api/tauri`. You must specify the provider as `"custom-openai"` (which maps to `LLMProvider::CustomOpenAI`) and include the `customOpenAIEndpoint` parameter:

```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: string = 'gpt-4',
  endpoint: string = 'https://my-openai-proxy.example.com'
): Promise<string> {
  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,      // Your custom endpoint URL
    maxTokens: 1024,
    temperature: 0.7,
    topP: 0.9,
  });

  return result;
}

```

The `customOpenAIEndpoint` value is passed directly to the Rust command as the `custom_openai_endpoint` parameter, which then flows into the LLM client.

## Persisting the Configuration

To avoid passing the endpoint manually each time, Meetily stores user-defined settings in a JSON file within the application data directory. The settings structure includes a `summary` object with a `customOpenAIEndpoint` field:

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

```

When the settings UI updates this value, the frontend reads from this store before invoking the Tauri command. The configuration constants and file paths are defined in [`src-tauri/src/config.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/config.rs), while the UI implementation resides in the React components under `frontend/src/app`.

## Summary

- **Runtime configuration**: The custom OpenAI-compatible endpoint is supplied at runtime via the `custom_openai_endpoint` parameter, not hard-coded.
- **URL construction**: In [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs), Meetily builds the final URL as `{endpoint}/chat/completions` after trimming trailing slashes.
- **Command interface**: Use the `builtin_ai_generate_summary` Tauri command with `provider: 'custom-openai'` to trigger the custom endpoint logic.
- **Persistence**: Store the endpoint in Meetily's internal JSON settings to automatically include it in future summary requests.

## Frequently Asked Questions

### What format should the custom endpoint URL follow?

The endpoint should point to the base URL of your OpenAI-compatible API without the `/chat/completions` path. For example, use `https://api.my-company.com/v1` rather than `https://api.my-company.com/v1/chat/completions`. Meetily automatically appends the completions path in [`llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/llm_client.rs).

### Can I use Azure OpenAI with this configuration?

Yes. Azure OpenAI Service is compatible with this approach as long as you provide the full Azure endpoint URL (including the deployment path) and the appropriate API key. The `generate_summary` function treats all `CustomOpenAI` providers identically, sending standard OpenAI-formatted JSON payloads.

### Where does Meetily store my custom endpoint settings?

Meetily persists settings in a JSON file located in the application data directory, managed through the configuration layer in [`src-tauri/src/config.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/config.rs). The specific field `customOpenAIEndpoint` under the `summary` key holds your custom URL, which the frontend reads before invoking the Tauri command.

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

The API key is passed as a string parameter to the Tauri command and included in the Authorization header (`Bearer {api_key}`) by 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). Ensure your custom endpoint uses HTTPS to encrypt the key in transit, as Meetily does not modify or encrypt the key beyond standard HTTP TLS.