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

> Learn to add a custom OpenAI-compatible endpoint for AI summaries in Meetily. Configure the `customOpenAIEndpoint` Tauri command for seamless integration with your LLM.

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

---

**Set a custom OpenAI-compatible endpoint by passing `customOpenAIEndpoint` to the `builtin_ai_generate_summary` Tauri command, which routes requests to `{endpoint}/chat/completions` via the LLM client in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs).**

Meetily's summarization system is designed to work with any OpenAI-compatible API, including private proxies, Azure OpenAI deployments, or self-hosted models like vLLM. The backend does not hard-code provider URLs; instead, it accepts a dynamic endpoint parameter at runtime. This guide walks through the complete flow—from frontend invocation to request construction—so you can integrate your own AI infrastructure.

## Understanding the Architecture

Meetily uses a three-layer architecture for summary generation:

1. **Frontend (React/TypeScript)** – Gathers user input and settings, then invokes the Tauri command.
2. **Tauri command layer** – Receives arguments, validates the provider type, and delegates to the LLM client.
3. **LLM client ([`llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/llm_client.rs))** – Constructs the HTTP request using the provided endpoint.

The critical integration point is the **`custom_openai_endpoint`** parameter, which the LLM client appends to `/chat/completions` when `provider` is `"custom-openai"`.

## Calling the Tauri Command from the Frontend

The frontend triggers summary generation via Tauri's `invoke` API. Pass the provider name `"custom-openai"` and your endpoint URL as arguments.

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

/**
 * Generate a meeting summary through a private OpenAI-compatible service.
 */
async function summarizeWithCustomEndpoint(
  transcript: string,
  apiKey: string,
  customEndpoint: string,
  model = 'gpt-4'
): Promise<string> {
  const summary = await invoke<string>('builtin_ai_generate_summary', {
    provider: 'custom-openai',
    modelName: model,
    apiKey,
    systemPrompt: 'Summarize this meeting transcript concisely.',
    userPrompt: transcript,
    customOpenAIEndpoint: customEndpoint,
    maxTokens: 1024,
    temperature: 0.7,
    topP: 0.9,
  });

  return summary;
}

// Example usage
const result = await summarizeWithCustomEndpoint(
  meetingTranscript,
  'sk-your-api-key',
  'https://my-internal-openai.example.com'
);

```

**Key parameters:**
- **`provider: 'custom-openai'`** – Required to trigger the `LLMProvider::CustomOpenAI` branch in Rust.
- **`customOpenAIEndpoint`** – The base URL of your OpenAI-compatible service (no trailing `/chat/completions` needed).

## How the Rust Backend Processes the Request

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 frontend arguments and forwards them to the core generator.

```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>,
    // ...additional optional parameters
) -> 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(),  // <-- passed here
        // ...remaining parameters
    )
    .await
}

```

The `custom_openai_endpoint` is passed as `Option<&str>` to the generator, allowing `None` for non-custom providers.

## URL Construction in the LLM Client

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), the client builds the complete request URL:

```rust
let url = format!(
    "{}/chat/completions",
    endpoint.trim_end_matches('/')
);

```

This means your endpoint should be the **base URL only**. For example:

| Your Input | Constructed URL |
|-----------|-----------------|
| `https://api.internal.com` | `https://api.internal.com/chat/completions` |
| `https://api.internal.com/` | `https://api.internal.com/chat/completions` |
| `https://api.internal.com/v1` | `https://api.internal.com/v1/chat/completions` |

The `trim_end_matches('/')` ensures consistent URL construction regardless of whether you include a trailing slash.

## Persisting the Endpoint in Settings

To avoid passing the endpoint on every call, Meetily stores user preferences in JSON within the app-data directory. The settings structure includes:

```json
{
  "summary": {
    "aiProvider": "custom-openai",
    "customOpenAIEndpoint": "https://my-openai-proxy.example.com",
    "customOpenAIModel": "gpt-4",
    "customOpenAIApiKey": "sk-..."
  }
}

```

When the settings UI updates this configuration, subsequent summary requests automatically read `customOpenAIEndpoint` and include it in the `builtin_ai_generate_summary` invocation.

## Validating Your Custom Endpoint

Before integrating, verify your endpoint implements the OpenAI chat completions API:

- **HTTP method:** `POST`
- **Path:** `/chat/completions` (appended by Meetily)
- **Headers:** `Authorization: Bearer {apiKey}`, `Content-Type: application/json`
- **Request body:** Standard OpenAI chat format with `model`, `messages`, `max_tokens`, `temperature`, `top_p`
- **Response:** JSON with `choices[0].message.content`

Test with `curl` before configuring Meetily:

```bash
curl -X POST https://your-endpoint.com/chat/completions \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 50
  }'

```

## Summary

- Meetily supports custom OpenAI-compatible endpoints through the **`custom-openai`** provider type.
- Pass your endpoint URL as **`customOpenAIEndpoint`** to the **`builtin_ai_generate_summary`** Tauri command.
- The LLM client in **[`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs)** constructs the full URL by appending `/chat/completions` to your base endpoint.
- Store persistent configuration in Meetily's settings JSON to avoid manual parameter passing.
- No backend rebuild is required—the endpoint is resolved at runtime per request.

## Frequently Asked Questions

### What provider name should I use for a custom OpenAI-compatible endpoint?

Use **`custom-openai`** as the `provider` value. This maps to `LLMProvider::CustomOpenAI` in the Rust code, which activates the custom endpoint logic. Other valid providers include `"openai"`, `"ollama"`, and `"anthropic"`, but only `"custom-openai"` respects the `customOpenAIEndpoint` parameter.

### Does Meetily support Azure OpenAI with this method?

Yes. Azure OpenAI Service exposes an OpenAI-compatible REST API. Set `customOpenAIEndpoint` to your Azure endpoint (e.g., `https://your-resource.openai.azure.com/openai/deployments/your-deployment-name`) and include your Azure API key in the `apiKey` parameter. Ensure your deployment name matches the `modelName` you specify.

### Can I use a local model like vLLM or llama.cpp-server?

Absolutely. Self-hosted OpenAI-compatible servers work identically to remote ones. Use `http://localhost:8000` or your local server address as `customOpenAIEndpoint`. For servers without authentication, pass any non-empty string as `apiKey`—Meetily requires the parameter but your server may ignore it.

### Where does Meetily store the custom endpoint configuration?

Meetily persists settings in a JSON file within the platform-specific app-data directory, managed through [`src-tauri/src/config.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/config.rs). The settings UI writes to this store, and frontend components read the `customOpenAIEndpoint` value when calling `builtin_ai_generate_summary`. You can also modify this file directly when Meetily is not running.