The whole API is four endpoints.
Base URL https://lazarus-th.duckdns.org/v1. Authenticate with Authorization: Bearer sk-.... Anything that speaks OpenAI speaks this.
| Method | Path | Returns |
|---|---|---|
| POST | /v1/chat/completions | Completion, or an SSE stream when stream:true |
| GET | /v1/models | Every model the key can reach |
| GET | /api/status | Public instance status, no auth |
| GET | /api/user/self | Balance and quota for the calling key |
Chat completions
Request body is the OpenAI shape. model is the only field that selects a route.
curl https://lazarus-th.duckdns.org/v1/chat/completions \ -H "Authorization: Bearer sk-..." \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-ai/DeepSeek-V4-Flash-0731", "messages": [{"role": "user", "content": "hello"}], "max_tokens": 256, "stream": false }'
Response carries a usage block on every call: prompt_tokens, completion_tokens, total_tokens, and reasoning_tokens where the model reports it.
Streaming
Set stream:true and the response becomes text/event-stream. Each frame is a data: line holding a delta; the last one is data: [DONE].
Errors
Errors are JSON with a stable shape, so a client can branch on message without parsing prose.
{"error": {"message": "Invalid token", "type": "new_api_error"}}
Python
from openai import OpenAI client = OpenAI( base_url="https://lazarus-th.duckdns.org/v1", api_key="sk-...", ) r = client.chat.completions.create( model="zai-org/GLM-5.3-Flash", messages=[{"role": "user", "content": "hello"}], ) print(r.choices[0].message.content)
Node
import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://lazarus-th.duckdns.org/v1", apiKey: "sk-...", }); const r = await client.chat.completions.create({ model: "MiniMaxAI/MiniMax-M2.7", messages: [{ role: "user", content: "hello" }], });
Keys
Keys are created in the console under Tokens. A key carries a quota, an optional model allow-list, and an optional IP allow-list. Revoking a key takes effect on the next request, no cache to wait out.
