API Documentation
OpenAI-compatible API. Base URL: https://api.genon.ai/v1
openai/gpt-5.6-solopenai/gpt-5.6-terraopenai/gpt-5.5minimaxai/minimax-m3google/gemma-4-26b-a4b-itmeta/muse-spark-1.3-contributoropenai/gpt-5.6-lunaopenai/whisper-large-v3boogu/boogu-image-0.1-baseboogu/boogu-image-0.1-editbaai/bge-m3z-ai/glm-5.3-flashanthropic/claude-opus-5qwen/qwen3.8-flashqwen/qwen3.8-27bqwen/qwen3.6-35b-a3bzai-org/glm-5.2moonshotai/kimi-k2.6qwen/qwen3.5-397b-a17b-fp8minimax/minimax-m3microsoft/phi-4openai/gpt-oss-20bEndpoint: https://api.genon.ai/v1/audio/transcriptions · Model: openai/whisper-large-v3
curl https://api.genon.ai/v1/audio/transcriptions \ -H "Authorization: Bearer sk-svp-YOUR_KEY" \ -F "model=openai/whisper-large-v3" \ -F "file=@audio.mp3" \ -F "language=ko" \ -F "response_format=verbose_json" \ -F "diarize=true" \ -F "num_speakers=3" # known headcount → exactly N speakers (omit to auto-detect)
from openai import OpenAI
client = OpenAI(api_key="sk-svp-YOUR_KEY", base_url="https://api.genon.ai/v1")
with open("audio.mp3", "rb") as f:
r = client.audio.transcriptions.create(
model="openai/whisper-large-v3",
file=f,
language="ko", # optional — blank auto-detects
response_format="verbose_json", # json | verbose_json | srt | vtt
extra_body={
"diarize": True, # ours: speaker labels per segment
"num_speakers": 3, # known headcount → pin to exactly N (omit to auto-detect)
},
)
print(r.text)
# r.segments[i].speaker present when diarize=Trueimport fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({ apiKey: "sk-svp-YOUR_KEY", baseURL: "https://api.genon.ai/v1" });
const r = await client.audio.transcriptions.create({
model: "openai/whisper-large-v3",
file: fs.createReadStream("audio.mp3"),
language: "ko",
response_format: "verbose_json",
// @ts-expect-error non-standard field (ours): speaker labels per segment
diarize: true,
// @ts-expect-error non-standard field (ours): pin to exactly N speakers (omit to auto-detect)
num_speakers: 3,
});
console.log(r.text);
// r.segments[i].speaker present when diarize=trueMultipart upload (file + model). The response shape follows response_format.
language— optional; blank auto-detects (slightly slower). e.g.ko,en.response_format—json(text only) ·verbose_json(segments + timestamps + speakers) ·srt·vtt.timestamp_granularities[]=word— word-level timestamps (withverbose_json).diarize=true— speaker diarization; eachverbose_jsonsegment gets aspeakerlabel. If you know the headcount, passnum_speakers=Nto pin diarization to exactly N speakers — strongly recommended for meetings. If unsure, bound it withmin_speakers/max_speakers(e.g.min_speakers=2as a floor). Omit all to auto-detect (which can under-count and merge two voices into one).prompt— optional decoding bias (domain terms, names).
Voice-activity detection (VAD) is always applied server-side — silent / non-speech spans return empty text instead of hallucinated phrases. There is no per-request flag to disable it.
Max input length: 4 hours per request (longer audio → 413; split into chunks). The API has no file-size cap — only the 4-hour duration limit. The console Playground caps uploads at 200 MiB (it buffers in memory); for larger or uncompressed files, call the API directly.
// response_format=verbose_json, diarize=true
{
"task": "transcribe",
"language": "ko",
"duration": 8160.885, // 오디오 길이(초)
"text": "이게 온프레미스로 전달될 때 ...", // 전체 평문 전사
"segments": [
{ "id": 0, "start": 3.17, "end": 23.99,
"text": "이게 온프레미스로 전달될 때 ...", "speaker": "SPEAKER_06" },
{ "id": 1, "start": 24.03, "end": 30.93,
"text": "그래서 반자동, 자동화되는 형태라고 보시겠습니다.", "speaker": "SPEAKER_01" }
],
"usage": { "type": "duration", "seconds": 8160.885,
"billing_units": { "audio_seconds": 8160.885, "audio_minutes": 136.01 } },
"request_id": "01KVDK1XWDGTCHYY56G0KQ6AJN"
}
// 화자 라벨(segments[].speaker, "SPEAKER_00"..)은 diarize=true 일 때만 채워집니다.
// response_format=json → { "text": "..." } 만 반환(segments 없음).
// response_format=srt|vtt → 자막 텍스트(본문이 자막 문자열).
// timestamp_granularities[]=word → 최상위 "words": [{ "word", "start", "end" }] 추가.| Model | Type | Context | Input / 1M | Output / 1M | $/image |
|---|---|---|---|---|---|
| openai/gpt-5.6-sol | Chat | 1,048,576 | $5.00 | $30.00 | — |
| openai/gpt-5.6-terra | Chat | 1,048,576 | $2.50 | $15.00 | — |
| openai/gpt-5.5 | Chat | 1,048,576 | $5.00 | $30.00 | — |
| minimaxai/minimax-m3 | Chat | 1,048,576 | $0.30 | $1.20 | — |
| google/gemma-4-26b-a4b-it | Chat | 262,144 | $0.07 | $0.34 | — |
| meta/muse-spark-1.3-contributor | Chat | 1,048,576 | $0.10 | $0.20 | — |
| openai/gpt-5.6-luna | Chat | 1,050,000 | $0.20 | $1.20 | — |
| openai/whisper-large-v3 | Speech to text | — | — | — | $0.0060 / audio min |
| boogu/boogu-image-0.1-base | Image generation | — | — | — | $0.020 |
| boogu/boogu-image-0.1-edit | Image edit | — | — | — | $0.040 |
| baai/bge-m3 | Embedding | 8,192 | $0.01 | — | — |
| z-ai/glm-5.3-flash | Chat | 1,310,720 | $0.07 | $0.25 | — |
| anthropic/claude-opus-5 | Chat | 1,000,000 | $5.00 | $25.00 | — |
| qwen/qwen3.8-flash | Chat | 1,000,000 | $0.16 | $0.47 | — |
| qwen/qwen3.8-27b | Chat | 1,000,000 | $0.42 | $2.55 | — |
| qwen/qwen3.6-35b-a3b | Chat | 262,144 | $0.14 | $1.00 | — |
| zai-org/glm-5.2 | Chat | 1,048,576 | $1.19 | $3.74 | — |
| moonshotai/kimi-k2.6 | Chat | 262,144 | $0.95 | $4.00 | — |
| qwen/qwen3.5-397b-a17b-fp8 | Chat | 262,144 | $0.50 | $3.60 | — |
| minimax/minimax-m3 | Chat | 1,048,576 | $0.30 | $1.20 | — |
| microsoft/phi-4 | Chat | 16,384 | $0.07 | $0.14 | — |
| openai/gpt-oss-20b | Chat | 131,072 | $0.03 | $0.13 | — |
OpenRouter-compatible introspection endpoints. Both /v1/* and /api/v1/* prefixes work.
GET /v1/auth/keyReturns the calling key's label, monthly usage, budget cap, remaining credit, and rate limit. Mirrors OpenRouter's key-introspection shape.
curl https://api.genon.ai/v1/auth/key -H "Authorization: Bearer sk-svp-YOUR_KEY"
# 200 OK
{
"data": {
"label": "prod-bot",
"usage": 12.34, # USD spent this month
"limit": 50.0, # USD cap (null if inherited)
"limit_remaining": 37.66, # org credit balance, USD
"is_free_tier": false,
"is_provisioning_key": false,
"rate_limit": { "requests": 60, "interval": "1m" }
}
}GET /v1/creditsOrg-level credit balance and total usage. Use for dashboards that don't need per-key detail.
curl https://api.genon.ai/v1/credits -H "Authorization: Bearer sk-svp-YOUR_KEY"
# 200 OK
{ "data": { "total_credits": 999.50, "total_usage": 12.34 } }GET /v1/generation?id=<request_id>After a streamed completion, fetch the final token counts, cost, and latency by the request_id returned in the x-request-id response header. Requires your API key, and only returns generations belonging to your organisation. The billing row is written asynchronously, so a just-finished request may 404 for a few seconds.
curl "https://api.genon.ai/v1/generation?id=01HFAKEULID01" \
-H "Authorization: Bearer $GENON_API_KEY"
# 200 OK
{
"data": {
"id": "gen-01HFAKEULID01",
"request_id": "01HFAKEULID01",
"model": "google/gemma-4-26b-a4b-it",
"created_at": "2026-07-30T03:28:47.519000+00:00",
"provider_name": "genon-nhn",
"tokens_prompt": 1000,
"tokens_completion": 500,
"native_tokens_cached": 0,
"total_cost": 0.000295, # USD dollars, not cents
"usage": 0.000295,
"latency": 2300, # ms
"generation_time": 2300,
"status": "ok"
}
}total_cost is USD dollars — here 1000 input + 500 output tokens at gemma-4's $0.12/$0.35 per 1M.
Non-streaming /v1/chat/completions responses now include usage.cost (USD float). Tools like Aider and Continue render this directly without an extra /generation round-trip.
{
"id": "chatcmpl-...",
"choices": [...],
"usage": {
"prompt_tokens": 1000,
"completion_tokens": 500,
"total_tokens": 1500,
"prompt_tokens_details": { "cached_tokens": 0 },
"cost": 0.000750 # USD, computed from per-model pricing
},
"provider": "genon-nhn"
}Set stream: true on /v1/chat/completions to receive incremental tokens. Each SSE frame is a JSON delta; the last frame before [DONE] contains the final usage block when stream_options.include_usage: true.
# Python
from openai import OpenAI
client = OpenAI(api_key="sk-svp-...", base_url="https://api.genon.ai/v1")
stream = client.chat.completions.create(
model="zai-org/glm-5.2",
messages=[{"role": "user", "content": "Tell me a story"}],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
delta = chunk.choices[0].delta.content if chunk.choices else None
if delta:
print(delta, end="", flush=True)
if chunk.usage:
print(f"\ntokens: in={chunk.usage.prompt_tokens} out={chunk.usage.completion_tokens}")All chat models advertise the tools feature. Pass an OpenAI-style tools array and tool_choice ("auto" / "required" / {type:"function",function:{name}}). The selected model picks tools and emits tool_calls[] in choices[0].message; reply with a role:"tool" message to feed execution results back.
r = client.chat.completions.create(
model="zai-org/glm-5.2",
messages=[{"role": "user", "content": "What's the weather in Seoul?"}],
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
},
}],
tool_choice="auto",
)
call = r.choices[0].message.tool_calls[0]
print(call.function.name, call.function.arguments)GLM-5.2, Qwen3.5, and Kimi-K2.6 emit chain-of-thought tokens separately as message.reasoning_content (and mirrored under provider_specific_fields.reasoning). They are billed as completion tokens. Toggle thinking off via chat_template_kwargs when the model accepts it (Kimi-K2.6 supported, qwen3.5 ignores the flag).
r = client.chat.completions.create(
model="moonshotai/kimi-k2.6",
messages=[{"role": "user", "content": "Explain prime factorisation"}],
extra_body={"chat_template_kwargs": {"thinking": False}},
)
msg = r.choices[0].message
print("answer:", msg.content)
print("thinking:", msg.reasoning_content) # may be None when disabledqwen/qwen3.5-397b-a17b-fp8 accepts text + image input. Send the OpenAI multimodal content array; image URLs may be http(s):// or data:image/...;base64,....
r = client.chat.completions.create(
model="qwen/qwen3.5-397b-a17b-fp8",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/cat.png"}},
],
}],
)
print(r.choices[0].message.content)The serving API is OpenAI-compatible — point any OpenAI SDK at our base URL.
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="zai-org/glm-5.2",
openai_api_key="sk-svp-...",
openai_api_base="https://api.genon.ai/v1",
)
print(llm.invoke("hi")){
"models": [{
"title": "GenOn GLM-5.2",
"provider": "openai",
"model": "zai-org/glm-5.2",
"apiBase": "https://api.genon.ai/v1",
"apiKey": "sk-svp-..."
}]
}OPENAI_API_BASE=https://api.genon.ai/v1 \ OPENAI_API_KEY=sk-svp-... \ aider --model openai/zai-org/glm-5.2
Aider reads usage.cost from each completion to render running spend — populated for all our chat models since #135.
# Both /v1/messages and /v1/chat/completions work — see the Chat tab above # for the Anthropic shape (#123/#147).
insufficient_creditsTop up at Credits pagerate_limitedReduce RPM or contact usmodel_not_foundCheck /v1/models for available modelscontext_length_exceededReduce input lengthinvalid_sizeImage size must be one of the supported presets