# How to Configure Custom OpenAI-Compatible Endpoints in Meetily

> Configure custom OpenAI-compatible endpoints in Meetily easily. Connect to self-hosted LLMs or third-party services using the Custom Open AI provider for flexible API integration.

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

---

**Meetily supports custom OpenAI-compatible endpoints through a dedicated "Custom Open AI" provider that enables connection to any server implementing the OpenAI chat-completions API, including self-hosted LLMs and third-party inference services.**

Meetily, the open-source meeting assistant from Zackriya-Solutions, provides native support for custom OpenAI-compatible endpoints to power its AI summarization engine. This feature allows you to route meeting transcriptions to private infrastructure, local models via Ollama, or alternative API providers without modifying the core Rust codebase.

## Understanding the Configuration Architecture

### The CustomOpenAIConfig Struct

At the core of this feature is the `CustomOpenAIConfig` struct defined in [`src-tauri/src/summary/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/mod.rs) (lines 12-31). This serializable structure stores all necessary connection parameters:

```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomOpenAIConfig {
    /// Base URL of the OpenAI‑compatible API endpoint (e.g. "http://localhost:8000/v1")
    pub endpoint: String,
    /// API key for authentication (optional)
    #[serde(rename = "apiKey")]
    pub api_key: Option<String>,
    /// Model identifier to use (e.g. "gpt‑4", "llama‑3‑70b")
    pub model: String,
    /// Maximum tokens for completion (optional)
    #[serde(rename = "maxTokens")]
    pub max_tokens: Option<i32>,
    /// Temperature (0.0‑2.0, optional)
    pub temperature: Option<f32>,
    /// Top‑P (0.0‑1.0, optional)
    #[serde(rename = "topP")]
    pub top_p: Option<f32>,
}

```

The struct uses **Serde** attributes for JSON compatibility, ensuring seamless serialization between the Rust backend and TypeScript frontend.

## Configuration Management Commands

Meetily exposes three Tauri commands in [`src-tauri/src/api/api.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/api/api.rs) to manage the complete lifecycle of custom endpoint configurations.

### Saving and Retrieving Settings

To persist a configuration, the `api_save_custom_openai_config` command (lines 1172-1220) validates input fields and upserts the JSON representation into the SQLite `settings` table:

```rust
#[tauri::command]
pub async fn api_save_custom_openai_config<R: Runtime>(
    pool: State<'_, SqlitePool>,
    endpoint: String,
    api_key: Option<String>,
    model: String,
    max_tokens: Option<i32>,
    temperature: Option<f32>,
    top_p: Option<f32>,
) -> Result<serde_json::Value, String> {
    let config = CustomOpenAIConfig {
        endpoint,
        api_key,
        model,
        max_tokens,
        temperature,
        top_p,
    };
    SettingsRepository::save_custom_openai_config(pool, &config).await?;
    Ok(json!({ "status": "success", "message": "Custom OpenAI configuration saved successfully" }))
}

```

Retrieval is handled by `api_get_custom_openai_config` (lines 1244-1265), which returns the stored configuration or `None` if unset:

```rust
#[tauri::command]
pub async fn api_get_custom_openai_config<R: Runtime>(
    pool: State<'_, SqlitePool>,
) -> Result<Option<CustomOpenAIConfig>, String> {
    SettingsRepository::get_custom_openai_config(pool).await.map_err(|e| e.to_string())
}

```

### Testing Endpoint Connectivity

Before activating a custom endpoint, you can verify network reachability and API compatibility using `api_test_custom_openai_connection` (lines 1270-1350). This command sends a minimal chat request (`"Hi"` with `max_tokens: 5`) to the specified endpoint and validates the response structure:

```rust
#[tauri::command]
pub async fn api_test_custom_openai_connection<R: Runtime>(
    endpoint: String,
    api_key: Option<String>,
    model: String,
) -> Result<serde_json::Value, String> {
    let url = format!("{}/chat/completions", endpoint.trim_end_matches('/'));
    // Builds test request, sends HTTP POST, validates status code 200,
    // and checks for valid choices[0].message.content in JSON response
}

```

## Runtime Integration in the LLM Client

When generating meeting summaries, the system dynamically routes requests to your custom endpoint based on the stored configuration.

### URL Construction and Provider Routing

In [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs) (lines 66-89), the provider parsing logic identifies the `custom-openai` variant. During request construction (lines 173-180), the client builds the target URL by appending `/chat/completions` to the configured base endpoint:

```rust
LLMProvider::CustomOpenAI => {
    let endpoint = custom_openai_endpoint
        .ok_or_else(|| "Custom OpenAI endpoint not configured".to_string())?;
    (
        format!("{}/chat/completions", endpoint.trim_end_matches('/')),
        HeaderMap::new()
    )
}

```

The `trim_end_matches('/')` call ensures proper URL path joining regardless of whether the user includes a trailing slash.

### Dynamic Parameter Injection

The request payload construction (lines 22-27 of [`llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/llm_client.rs)) conditionally includes generation parameters only when using the custom provider. This allows the system to pass `max_tokens`, `temperature`, and `top_p` values directly to compatible endpoints that support these OpenAI-style parameters.

## Frontend Integration Examples

### Configuring a Custom Endpoint

From the TypeScript frontend, invoke the save command to register a local Ollama server or compatible proxy:

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

await invoke('api_save_custom_openai_config', {
  endpoint: 'http://localhost:11434/v1',
  api_key: null,                 // Optional for local servers
  model: 'llama3.1:8b',
  max_tokens: 1024,
  temperature: 0.7,
  top_p: 0.9
});

```

### Validating and Using the Connection

Test connectivity before trusting the endpoint for production summaries:

```typescript
const testResult = await invoke('api_test_custom_openai_connection', {
  endpoint: 'http://localhost:11434/v1',
  api_key: null,
  model: 'llama3.1:8b'
});
console.log(testResult); 
// → { status: 'success', message: 'Connection successful …' }

```

Trigger summary generation by specifying the custom provider:

```typescript
const summary = await invoke('api_get_summary', {
  provider: 'custom-openai',
  meeting_id: 'uuid-here',
  transcript: 'Meeting transcript text...'
});

```

## Summary

- **Meetily** implements custom OpenAI-compatible endpoint support through the `CustomOpenAIConfig` struct in [`src-tauri/src/summary/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/mod.rs), enabling connections to any server following the OpenAI chat-completions API specification.
- **Three Tauri commands**—`api_save_custom_openai_config`, `api_get_custom_openai_config`, and `api_test_custom_openai_connection`—manage configuration persistence and validation.
- **Dynamic 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) (lines 173-180) routes requests to `{endpoint}/chat/completions` with automatic trailing slash handling.
- **Optional parameters** including `max_tokens`, `temperature`, and `top_p` are conditionally injected into requests only for the custom provider case.
- **No core code modifications** are required to use self-hosted models, LocalAI instances, Azure OpenAI, or other compatible endpoints.

## Frequently Asked Questions

### Which self-hosted LLM servers work with Meetily's custom endpoint feature?

Any server implementing the OpenAI chat-completions API specification works with Meetily's custom OpenAI-compatible endpoint support. This includes Ollama with its OpenAI compatibility layer, LocalAI, LiteLLM Proxy, vLLM, and cloud alternatives like Azure OpenAI Service. The system expects standard `/chat/completions` endpoints returning JSON with a `choices` array containing `message.content` fields.

### Is an API key required when configuring a custom OpenAI-compatible endpoint?

No, the **API key is optional**. The `CustomOpenAIConfig` struct defines `api_key` as `Option<String>`, making authentication unnecessary for local networks or unsecured development servers. However, production deployments using cloud-based compatible endpoints should provide valid authentication tokens through this field.

### How does Meetily validate that a custom endpoint is working correctly?

The `api_test_custom_openai_connection` command performs live validation by sending a minimal POST request to `{endpoint}/chat/completions` with a test prompt and `max_tokens: 5`. It verifies HTTP 200 status, valid JSON parsing, and the presence of a non-empty `choices[0].message.content` field in the response, ensuring the endpoint conforms to expected OpenAI API behavior patterns.

### Can I use different generation parameters like temperature for custom endpoints?

Yes, Meetily supports passing **dynamic generation parameters** including `max_tokens`, `temperature` (0.0-2.0), and `top_p` (0.0-1.0) to custom OpenAI-compatible endpoints. These values are stored in `CustomOpenAIConfig` and conditionally injected into the request payload only when using the custom provider, allowing fine-grained control over output generation without affecting other LLM providers.