# IC Lueur Ai — API connection guide

> How to call IC Lueur Ai from code or from an AI tool. Written so you can hand this file to an AI assistant and ask it to wire up the integration.

Source of truth for model ids and prices is the live catalogue, not this file. Full docs: https://www.ic-lueur.ai/docs/

## Quick reference

- **Base URL:** `https://api.ic-lueur.ai/v1`
- **Authentication:** Send `Authorization: Bearer YOUR_API_KEY`. Create a key in the member portal under API keys. It is shown once; we store only a hash, so a lost key cannot be recovered — create a new one.
- **Model ids:** Do not guess a model id. Call `GET {BASE_URL}/models` with your key, or read the public catalogue at https://www.ic-lueur.ai/api/models (id, serving regions, THB price per million tokens).

## Endpoints

| Method and path | Purpose |
|---|---|
| `POST /chat/completions` | Chat Completions, OpenAI format. `stream: true` switches to server-sent events. |
| `GET /models` | List the model ids in the catalogue. Some may still be refused under your organisation’s routing policy. |
| `POST /embeddings` | Embeddings. |

All paths are relative to the base URL.

## Your first request

Create a key: In the member portal, under API keys. The key is shown once — we store only a hash of it, so we cannot show it to you again or recover it for you.

Point your client at us: Set the base URL to our endpoint and use your key as the API key. Model names come from `GET /v1/models`.

```bash
curl https://api.ic-lueur.ai/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "MODEL_ID_FROM_/models", "messages": [{"role": "user", "content": "Hello"}]}'
```

## Rules for an AI assistant

- Take the base URL and key from configuration or environment variables. Never hard-code a key in source or commit it.
- Read the model id from `GET /models`. Do not invent or abbreviate ids.
- Send model options as top-level request fields. `extra_body`, `kwargs`, `litellm_params` and `custom_llm_provider` are rejected with 400.
- Errors use OpenAI's shape, `{"error": {"message": "<message>"}}`, but `type` and `code` do not always match OpenAI's. Branch on the HTTP status and match on the message text when you must tell two 429s apart.
- On 429 wait for the `Retry-After` header, when present, before retrying, and read the message for the cause. A 429 is not charged.
- Do not retry a 402. Top up the balance instead.

## Streaming

Set `stream: true` and read the response as server-sent events, same shape as OpenAI's Chat Completions streaming.

- **Format:** Standard server-sent events — the same chunked `data:` format and termination OpenAI's streaming responses use. The `model` field in each chunk shows the model name you requested.
- **Disconnecting early:** Tokens already generated before you close the connection are still billed. An interrupted request is metered the same as a completed one.

## Errors

Errors use the same shape as OpenAI's, `{"error": {"message": "<message>"}}`, with the HTTP status. The `type` and `code` values do not always match OpenAI's, so branch on the HTTP status and the message text instead.

| Status | Name | Meaning |
|---|---|---|
| 400 | Bad Request | The requested model has no configured deployment (check the model name against GET /v1/models), or the request sets a field this gateway does not accept: extra_body, kwargs, litellm_params or custom_llm_provider. Send model options as top-level fields — the OpenAI SDKs already do this with their own extra_body. |
| 401 | Unauthorized | The key is missing, unknown, or has been revoked. |
| 402 | Insufficient Balance | Your account balance is too low to cover this request. The message states the balance in THB. |
| 403 | Forbidden | The organization has been suspended, the key is an operator/master key (which cannot be billed for inference), or the key’s creator has reached a daily or monthly spend limit set by the organization’s owner or admin. |
| 413 | Payload Too Large | The prompt is too large to qualify for a free-model promotion window (see Free-model promotions below). |
| 429 | Rate Limit | This key has exceeded its requests-per-minute limit. Wait for the Retry-After header, when present, and read the message before retrying. |
| 503 | Service Unavailable | Our internal key store is unreachable, or the model has no price configured yet. We fail closed rather than let an unverifiable key or an unpriced request through. |

429 covers several conditions. If your retry logic needs to tell them apart, match on how the message starts, not on the status code alone, and match case-sensitively: the key's own rate limit starts with `rate limit exceeded:` in lower case; a region that is temporarily unavailable starts with `no region available`; the three free-model-promotion limits below start with `QUOTA_EXCEEDED`, `REQUEST_LIMIT_EXCEEDED` or `RATE_LIMIT_EXCEEDED` in capitals.

## Rate limits

**Every key has a requests-per-minute limit.** Each API key enforces a requests-per-minute cap — either an override you set by editing the key in the member portal, or the gateway default of 60 requests per minute if you leave it unset. A request over the limit gets a 429 with a Retry-After header; it costs nothing and is not counted as usage.

## Free-model promotions

Any model can carry a temporary free window — same request, no charge, while it lasts.

| Limit | Value | Note |
|---|---|---|
| Rate limit | 15 requests / min per key | Separate from your key's own rate limit, and usually tighter |
| Weekly quota | 1,000,000 tokens or 1,000 requests | Per organisation, whichever is hit first |
| Quota resets | Every Monday | 00:00, Asia/Bangkok time |
| Max prompt size | 32,000 tokens | Over this, the request is refused outright — never billed instead |
| Max output size | 16,000 tokens | Capped automatically; a smaller max_tokens you set is still honoured |
| When the quota runs out | Blocked until Monday | Unless you turn on auto-fallback in the member portal (Top-up settings) |

## Where requests run

**Where requests run today.** Most requests are served from Singapore (ap-southeast-1) and Tokyo (ap-northeast-1). Some models are only offered in a provider’s global region, which can be outside Asia, for example the United States, and organisations on the available policy can also reach providers in mainland China. Your account data, balance, billing ledger and tax invoices are stored on AWS in Thailand regardless of which region served the request.

- **strict:** Bangkok only, never another region. No model is served from Bangkok yet, so requests under strict are currently refused with a 400.
- **regional:** The default. The nearest region is tried first — Bangkok, then Singapore, then Tokyo — and a model not served in any of them goes to the provider’s global region, which can be outside Asia.
- **available:** Only for organisations that ask for it in writing. Reaches everything regional does plus providers in mainland China, and is required for image and video models served outside Bangkok, Singapore and Tokyo.

## Connect your tools

Use a Base URL and API key to connect any tool that supports the OpenAI API — set up in just a few steps and start right away.

- **Base URL:** `https://api.ic-lueur.ai/v1`
- **API Key:** `YOUR_API_KEY`

### Code Editors & IDE Extensions

Connect your AI coding tools with one Base URL and API Key

#### Roo Code (VS Code Extension)

1. Install Roo Code from the VS Code Marketplace (RooVeterinaryInc.roo-cline)
2. Click the Roo Code icon in the Activity Bar
3. Open Settings → set API Provider to OpenAI Compatible
4. Paste the Base URL and your API key
5. Type a model name (e.g. claude-sonnet-4-6) and click Save

Tip: Roo Code also works inside Windsurf and VSCodium — same install flow.

#### Cline (VS Code Extension)

1. Install Cline from the VS Code Marketplace (saoudrizwan.claude-dev)
2. Click the Cline icon in the Activity Bar
3. Open the Settings gear → set API Provider to OpenAI Compatible
4. Paste the Base URL and your API key
5. Type a model name and click Save

Tip: Cline also works inside Windsurf and VSCodium — same install flow.

#### Continue.dev (VS Code + JetBrains)

1. Install the Continue extension (continue.continue)
2. Open ~/.continue/config.json (created automatically on first launch)
3. Add a new model block under models with the provider and API settings below
4. Save the file — Continue reloads automatically

```jsonc
// ~/.continue/config.json  (add inside "models": [...])
{
  "title": "IC Lueur Ai",
  "provider": "openai",
  "model": "claude-sonnet-4-6",
  "apiBase": "https://api.ic-lueur.ai/v1",
  "apiKey": "YOUR_API_KEY"
}
```

#### VS Code (Custom Provider)

1. Open VS Code and press ⌘⇧P (or Ctrl+Shift+P)
2. Search for Preferences: Open User Settings (JSON)
3. Add the custom endpoint block shown below
4. Save — VS Code will use this endpoint for any AI feature that respects the setting

```jsonc
// settings.json
{
  "github.copilot.advanced": {},
  "languageModels": {
    "openAI": {
      "baseURL": "https://api.ic-lueur.ai/v1",
      "apiKey": "YOUR_API_KEY"
    }
  }
}
```

### AI Chat Clients

Connect AI chat clients that support the OpenAI API

#### Cherry Studio (Desktop App)

1. Open Cherry Studio and go to Settings → Providers
2. Click + Add Provider
3. Set Type to OpenAI Compatible
4. Paste the Base URL and your API key
5. Click Check to fetch the model list, then Save

#### NextChat (Web + Self-host)

1. Open NextChat and click the Settings icon (bottom-left)
2. Scroll to API Settings
3. Enable Custom Endpoint and paste the Base URL
4. Enter your API key and click Save

Tip: Self-hosting? Set OPENAI_API_URL in your .env file instead of using the UI.

#### LibreChat (Self-hosted)

1. Open your LibreChat .env file
2. Set OPENAI_REVERSE_PROXY to the Base URL
3. Set OPENAI_API_KEY to your API key
4. Restart your LibreChat container (docker compose restart)

```bash
# .env
OPENAI_REVERSE_PROXY=https://api.ic-lueur.ai/v1
OPENAI_API_KEY=YOUR_API_KEY
```

#### LobeChat (Web + Desktop)

1. Open LobeChat and go to Settings → Provider
2. Select OpenAI
3. Enter your Base URL and API Key
4. Click Check to automatically fetch the available models

Tip: If the model dropdown is empty after saving, click Check again — it fetches from the live /v1/models list.

### CLI & SDKs

Configure CLI tools and SDKs to use models through IC Lueur Ai

#### Claude Code (CLI)

1. Export the two environment variables below in your shell profile (~/.zshrc or ~/.bashrc)
2. Reload your shell or open a new terminal window
3. Run claude — it now routes through IC Lueur Ai

```bash
export ANTHROPIC_BASE_URL="https://api.ic-lueur.ai/v1"
export ANTHROPIC_API_KEY="YOUR_API_KEY"

claude
```

Tip: Claude Code uses the Anthropic API format, so ANTHROPIC_BASE_URL points directly at our gateway.

#### cURL (Terminal)

1. Run the command below — replace YOUR_API_KEY with your key from the Member Portal
2. The response is a standard OpenAI-format JSON object

```bash
curl https://api.ic-lueur.ai/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

#### OpenAI SDK (Python / Node.js)

1. Install the openai package (pip install openai or npm install openai)
2. Create the client with the two parameters highlighted below
3. Use the client as you would with OpenAI for chat completions and embeddings — same calls, same response shape

```python
from openai import OpenAI

client = OpenAI(
    base_url="https://api.ic-lueur.ai/v1",  # ← change this
    api_key="YOUR_API_KEY",  # ← and this
)

response = client.chat.completions.create(
    model="claude-sonnet-4-6",
    messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.ic-lueur.ai/v1",  // ← change this
  apiKey: "YOUR_API_KEY",  // ← and this
});

const res = await client.chat.completions.create({
  model: "claude-sonnet-4-6",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(res.choices[0].message.content);
```

### Automation & no-code

Connect IC Lueur Ai to your workflows and no-code tools

#### Make (No-code)

1. In Make, create a scenario, add the HTTP module and choose Make a request
2. Set URL to https://api.ic-lueur.ai/v1/chat/completions, Method to POST and Authentication type to No authentication
3. In Headers add Authorization with the value Bearer YOUR_API_KEY
4. Set Body content type to application/JSON, Body input method to JSON string, paste the body shown here, and set Parse response to Yes
5. Click Run once: the answer is at data → choices → 1 → message → content

```json
{
  "model": "app/your-assistant-name",
  "messages": [{ "role": "user", "content": "{{escapeJSON(1.text)}}" }]
}
```

Tip: escapeJSON keeps a message with quotes or line breaks from breaking the request. The full guide, with troubleshooting, is in the member portal under AI assistants → your assistant → Connect.

#### n8n (No-code)

1. In n8n add an HTTP Request node: Method POST, URL https://api.ic-lueur.ai/v1/chat/completions
2. Keep the key in a Header Auth credential: Name Authorization, Value Bearer YOUR_API_KEY
3. Set Body to JSON and paste the body shown here (replace $json.text with the field that holds your message)
4. Click Execute step: the answer is at choices[0].message.content

```json
{
  "model": "app/your-assistant-name",
  "messages": [{ "role": "user", "content": {{ JSON.stringify($json.text) }} }]
}
```

Tip: Do not put quotes around {{ JSON.stringify(...) }}: it is what lets a message with quotes or line breaks through. For an assistant that answers in JSON, add an Edit Fields node in JSON mode with {{ JSON.parse($json.choices[0].message.content) }}.

#### Google Sheets (Apps Script)

1. In the member portal create an AI assistant, then open it and go to the Connect tab → Google Sheets
2. Make a copy of the ready-made sheet (or paste the script into a new sheet, steps are in the same place)
3. In the sheet run the menu “ผู้ช่วย AI by IC Lueur → 1. ตั้งค่าและเริ่มใช้งาน” and enter the three values below
4. Paste text into column A: the status and the answer are filled in by themselves

```text
Base URL:  https://api.ic-lueur.ai/v1
Assistant: app/your-assistant-name
API key:   YOUR_API_KEY   (a key made just for this sheet)
```

Tip: The sheet menus are in Thai. The first run asks Google for permission once, and Google may say it has not verified the app: the guide in the portal shows each screen.

## Help

Email support-d@ic-lueur.ai or use the message form at https://www.ic-lueur.ai/contact/. Support is in Thai and English during Thai business hours.
