Open‑source version of OpenRouter, managed through a unified gateway that handles all AI SaaS model calls. Core functions include:
- Aggregating chat, image, speech, TTS, embeddings, rerank and other capabilities.
- Aggregating multiple model providers such as OpenAI, Anthropic, Azure, Google Vertex, OpenRouter, DeepSeek, Replicate, AWS Bedrock, etc.
- Aggregating various upstream API request formats like Chat Completion, Response, Claude Messages.
- Supporting different request formats; users can issue requests via Chat Completion, Response, or Claude Messages, which are automatically and transparently converted to the native request format of the upstream model. Even if the client sends a mismatched request format to wrong api endpoint, it will still be correctly processed.
- Supporting multi‑tenant management, allowing each tenant to set distinct quotas and permissions.
- Supporting generation of sub‑API Keys; each tenant can create multiple sub‑API Keys, each of which can be bound to different models and quotas.
Also welcome to register and use my deployed one-api gateway, which supports various mainstream models. For usage instructions, please refer to https://wiki.laisky.com/projects/gpt/pay/.
Try it at https://oneapi.laisky.com, login with test / 12345678. 🚀
=== One-API Compatibility Matrix 2025-11-28T22:05:53Z ===
Request Format gpt-4o-mini gpt-5-mini claude-haiku-4-5 gemini-2.5-flash openai/gpt-oss-20b deepseek-chat grok-4-fast-non-reasoning azure-gpt-5-nano
Chat (stream=false) PASS 8.81s PASS 11.41s PASS 14.27s PASS 2.96s PASS 1.74s PASS 9.25s PASS 5.25s PASS 14.29s
Chat (stream=true) PASS 9.44s PASS 13.27s PASS 4.45s PASS 6.05s PASS 2.10s PASS 9.62s PASS 3.23s PASS 10.47s
Chat Tools (stream=false) PASS 9.74s PASS 13.85s PASS 3.84s SKIP PASS 7.01s SKIP PASS 10.56s SKIP
Chat Tools (stream=true) PASS 13.58s PASS 9.00s PASS 5.12s PASS 5.34s PASS 5.57s PASS 9.61s PASS 6.12s PASS 13.95s
Chat Tools History (stream=false) PASS 7.37s PASS 12.49s PASS 9.84s PASS 13.12s SKIP PASS 16.89s PASS 5.01s SKIP
Chat Tools History (stream=true) PASS 4.60s SKIP PASS 4.14s PASS 6.80s PASS 7.81s PASS 11.95s PASS 2.57s SKIP
Chat Structured (stream=false) PASS 11.89s PASS 14.03s PASS 12.85s PASS 6.08s PASS 5.87s PASS 37.34s PASS 4.67s PASS 9.83s
Chat Structured (stream=true) PASS 9.58s PASS 11.36s PASS 4.04s PASS 3.33s PASS 9.00s PASS 28.40s PASS 6.62s PASS 12.56s
Response (stream=false) PASS 8.74s PASS 28.93s PASS 12.20s PASS 6.35s PASS 6.00s PASS 30.73s PASS 8.62s PASS 14.16s
Response (stream=true) PASS 9.53s PASS 14.59s PASS 7.80s PASS 7.36s PASS 10.23s PASS 8.24s PASS 9.50s PASS 15.41s
Response Vision (stream=false) PASS 9.62s PASS 14.01s PASS 12.02s PASS 8.84s SKIP SKIP PASS 8.20s PASS 13.97s
Response Vision (stream=true) PASS 8.34s PASS 8.34s PASS 3.70s PASS 6.76s SKIP SKIP PASS 8.07s PASS 13.52s
Response Tools (stream=false) PASS 11.71s PASS 8.18s PASS 6.16s PASS 10.37s PASS 4.78s PASS 6.71s PASS 9.13s PASS 9.52s
Response Tools (stream=true) PASS 4.41s PASS 13.48s PASS 11.03s PASS 4.17s PASS 2.68s PASS 19.58s PASS 10.05s PASS 5.58s
Response Tools History (stream=false) PASS 5.62s PASS 9.07s PASS 7.95s PASS 10.99s SKIP PASS 13.50s PASS 7.01s PASS 14.31s
Response Tools History (stream=true) PASS 6.36s PASS 13.52s PASS 11.05s PASS 13.25s PASS 5.65s PASS 9.96s PASS 6.15s PASS 7.99s
Response Structured (stream=false) PASS 7.83s PASS 15.24s PASS 3.85s PASS 8.89s PASS 8.67s PASS 13.38s PASS 5.70s PASS 12.46s
Response Structured (stream=true) PASS 4.98s PASS 18.41s PASS 6.76s PASS 3.28s PASS 9.46s PASS 20.16s PASS 4.76s PASS 13.72s
Claude (stream=false) PASS 3.88s PASS 9.11s PASS 9.77s PASS 3.33s PASS 4.74s PASS 6.78s PASS 3.88s PASS 7.76s
Claude (stream=true) PASS 6.26s PASS 9.35s PASS 14.09s PASS 6.76s PASS 3.67s PASS 6.44s PASS 5.83s PASS 6.60s
Claude Tools (stream=false) PASS 14.22s PASS 12.48s PASS 4.99s PASS 2.75s PASS 12.08s PASS 14.25s PASS 5.87s PASS 14.05s
Claude Tools (stream=true) PASS 6.03s PASS 8.23s PASS 8.53s SKIP PASS 4.89s PASS 7.33s PASS 4.16s PASS 13.13s
Claude Tools History (stream=false) PASS 8.90s FAIL response missing tool_use block … PASS 8.46s PASS 8.42s SKIP PASS 26.26s PASS 6.21s PASS 14.64s
Claude Tools History (stream=true) PASS 7.96s SKIP PASS 7.32s PASS 13.79s PASS 4.51s PASS 9.76s PASS 3.61s PASS 19.42s
Claude Structured (stream=false) PASS 10.04s SKIP PASS 13.38s PASS 6.82s PASS 5.23s PASS 13.79s PASS 9.52s SKIP
Claude Structured (stream=true) PASS 5.23s SKIP PASS 5.72s PASS 13.11s PASS 3.80s PASS 19.28s PASS 1.82s SKIP
Totals | Requests: 208 | Passed: 188 | Failed: 1 | Skipped: 19
Failures:
- gpt-5-mini - Claude Tools History (stream=false) -> response missing tool_use block or assistant text
Skipped (unsupported combinations):
- azure-gpt-5-nano - Chat Tools (stream=false) -> GPT-5 reasoning model inconsistently returns reasoning instead of tool calls
- azure-gpt-5-nano - Chat Tools History (stream=false) -> Model returns reasoning text instead of tool calls
- azure-gpt-5-nano - Chat Tools History (stream=true) -> Model returns reasoning text instead of tool calls when streaming
- azure-gpt-5-nano - Claude Structured (stream=false) -> Azure GPT-5 nano does not return structured JSON for Claude messages (empty content)
- azure-gpt-5-nano - Claude Structured (stream=true) -> Azure GPT-5 nano does not return structured JSON for Claude messages (empty content)
- deepseek-chat - Chat Tools (stream=false) -> Model times out on non-streaming tool invocation requests
- deepseek-chat - Response Vision (stream=false) -> vision input unsupported by model deepseek-chat
- deepseek-chat - Response Vision (stream=true) -> vision input unsupported by model deepseek-chat
- gemini-2.5-flash - Chat Tools (stream=false) -> Model returns text instead of tool invocations despite forced tool_choice
- gemini-2.5-flash - Claude Tools (stream=true) -> Model returns text instead of tool invocations despite forced tool_choice
- gpt-5-mini - Chat Tools History (stream=true) -> GPT-5 reasoning model inconsistently returns reasoning instead of tool calls when streaming
- gpt-5-mini - Claude Structured (stream=false) -> GPT-5 mini returns empty content for Claude structured requests
- gpt-5-mini - Claude Structured (stream=true) -> GPT-5 mini streams only usage deltas, never emitting structured JSON blocks
- gpt-5-mini - Claude Tools History (stream=true) -> GPT-5 reasoning model inconsistently returns reasoning instead of tool calls
- openai/gpt-oss-20b - Chat Tools History (stream=false) -> Model refuses forced tool_choice (upstream returns 400 tool_use_failed)
- openai/gpt-oss-20b - Claude Tools History (stream=false) -> Model refuses forced tool_choice (upstream returns 400 tool_use_failed)
- openai/gpt-oss-20b - Response Tools History (stream=false) -> Model refuses forced tool_choice (upstream returns 400 tool_use_failed)
- openai/gpt-oss-20b - Response Vision (stream=false) -> vision input unsupported by model openai/gpt-oss-20b
- openai/gpt-oss-20b - Response Vision (stream=true) -> vision input unsupported by model openai/gpt-oss-20b
The original author stopped maintaining the project, leaving critical PRs and new features unaddressed. As a long‑time contributor, I’ve forked the repository and rebuilt the core to keep the ecosystem alive and evolving.
- One API
- Synopsis
- Tutorial
- Contributors
- New Features
- Universal Features
- OpenAI Features
- Support whisper
- Support openai images edits
- Support OpenAI o1/o1-mini/o1-preview
- Support gpt-4o-audio
- Support OpenAI web search models
- Support gpt-image family for image generation & edits
- Support o3-mini & o3 & o4-mini & gpt-4.1 & o3-pro & reasoning content
- Support OpenAI Response API
- Support gpt-5 family
- Support o3-deep-research & o4-mini-deep-research
- Support Codex Cli
- Support Sora
- Anthropic (Claude) Features
- Support Claude 4.x Models
- Google (Gemini & Vertex) Features
- Support gemini-2.0-flash-exp
- Support gemini-2.0-flash
- Support gemini-2.0-flash-thinking-exp-01-21
- Support Vertex Imagen3
- Support gemini multimodal output #2197
- Support gemini-2.5-pro
- Support GCP Vertex gloabl region and gemini-2.5-pro-preview-06-05
- Support gemini-2.5-flash-image-preview & imagen-4 series
- Support gemini-3 family
- OpenCode Support
- AWS Features
- Replicate Features
- DeepSeek Features
- OpenRouter Features
- Cohere
- Coze Features
- Moonshot Features
- GLM Features
- XAI / Grok Features
- Black Forest Labs Features
- Bug Fixes & Enterprise-Grade Improvements (Including Security Enhancements)
Docker images available on Docker Hub:
ppcelery/one-api:latestppcelery/one-api:arm64-latest
The initial default account and password are root / 123456. Listening port can be configured via the PORT environment variable, default is 3000.
Run one-api using docker-compose:
All environment variables can be set via the
environmentsection in thedocker-compose.ymlfile, please refer to ./common/config/config.go for all available configuration options.
oneapi:
image: ppcelery/one-api:latest
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
volumes:
- /var/lib/oneapi:/data
ports:
- 3000:3000Tip
For production environments, consider using proper secret management solutions instead of hardcoding sensitive values in environment variables.
The Kubernetes deployment guide has been moved into a dedicated document:
Support internationalization (i18n) in the web frontend, including English, Chinese, French, Spanish, and Japanese.
All channels share a four-layer billing pipeline (channel overrides → adapter defaults → global fallback → safe default) with support for tiered token pricing, cached prompt buckets, and per-second/per-image media meters. Administrators can fetch defaults, override specific models, and audit every call via X-Oneapi-Request-Id; see docs/arch/billing.md for internals and docs/manuals/billing.md for the operational playbook.
Configure the price and whitelist for a channel’s built‑in tools.
You can update the used quota using the API key of any token, allowing other consumption to be aggregated into the one-api for centralized management.
curl -X POST https://oneapi.laisky.com/api/token/consume \
-H "Authorization: Bearer <TOKEN_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"add_reason": "async-transcode",
"add_used_quota": 150
}'Each chat completion request will include a X-Oneapi-Request-Id in the returned headers. You can use this request id to request GET /api/cost/request/:request_id to get the cost of this request.
The returned structure is:
type UserRequestCost struct {
Id int `json:"id"`
CreatedTime int64 `json:"created_time" gorm:"bigint"`
UserID int `json:"user_id"`
RequestID string `json:"request_id"`
Quota int64 `json:"quota"`
CostUSD float64 `json:"cost_usd" gorm:"-"`
}Now supports cached input, which can significantly reduce the cost.
Supports two URL parameters: thinking and reasoning_format.
thinking: Whether to enable thinking mode, disabled by default.reasoning_format: Specifies the format of the returned reasoning.reasoning_content: DeepSeek official API format, returned in thereasoning_contentfield.reasoning: OpenRouter format, returned in thereasoningfield.thinking: Claude format, returned in thethinkingfield.
curl --location 'https://oneapi.laisky.com/v1/chat/completions?thinking=true&reasoning_format=reasoning_content' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "gpt-5-mini",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "1+1=?"
}
]
}'Response:
{
"id": "resp_01282fbc2c1cd0a90069068d5ae43c819e93f5ca9ebacf4aaa",
"model": "gpt-5-mini",
"object": "chat.completion",
"created": 1762037082,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "2",
"reasoning_content": "**Calculating addition succinctly**\n\nI need to respond clearly. The user might be asking playfully, so I should keep it concise. The simplest answer is 1 + 1 = 2. It could be fun to mention that in binary, 1 + 1 equals 10, but that's not really necessary since the typical base is decimal. I'll stick with the straightforward response: \"2.\" Maybe I can add a brief note explaining it, like \"Adding one and one gives two,\" but I’ll keep it minimal.",
"reasoning": "**Calculating addition succinctly**\n\nI need to respond clearly. The user might be asking playfully, so I should keep it concise. The simplest answer is 1 + 1 = 2. It could be fun to mention that in binary, 1 + 1 equals 10, but that's not really necessary since the typical base is decimal. I'll stick with the straightforward response: \"2.\" Maybe I can add a brief note explaining it, like \"Adding one and one gives two,\" but I’ll keep it minimal."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 10,
"completion_tokens": 199,
"total_tokens": 209,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0,
"text_tokens": 0,
"image_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 192,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0,
"text_tokens": 0,
"cached_tokens": 0
}
}
}curl --location 'https://oneapi.laisky.com/v1/chat/completions?thinking=true&reasoning_format=reasoning' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "gpt-5-mini",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "1+1=?"
}
]
}'Response:
{
"id": "resp_0e6222cdcfeabbbf0069068da588b88194964340c1e33fbabb",
"model": "gpt-5-mini",
"object": "chat.completion",
"created": 1762037157,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "2",
"reasoning": "**Calculating a simple equation**\n\nThe user asked what 1 + 1 equals, which is a straightforward question. I can just respond with \"2.\" Although I could add a simple explanation that 1 plus 1 equals 2, I should keep it concise. So, I’ll stick with the answer \"2\" and perhaps mention \"1 + 1 = 2\" for clarity. It's clear, and there are no concerns here, so I'll give the final response of \"2.\""
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 10,
"completion_tokens": 71,
"total_tokens": 81,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0,
"text_tokens": 0,
"image_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 64,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0,
"text_tokens": 0,
"cached_tokens": 0
}
}
}curl --location 'https://oneapi.laisky.com/v1/chat/completions?thinking=true&reasoning_format=thinking' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "gpt-5-mini",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "1+1=?"
}
]
}'Response:
{
"id": "resp_099bd53deedec1a80069068dc160d88191a1d3ff4eb82c37bb",
"model": "gpt-5-mini",
"object": "chat.completion",
"created": 1762037185,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "2",
"thinking": "**Calculating simple arithmetic**\n\nThe user asked a really straightforward question: \"1+1=?\". I should definitely keep it concise, so the answer is simply 2. I could also mention that 1+1 equals 2 in terms of adding integers. But really, just saying \"2\" should suffice. If they're curious for more detail, I can provide a brief explanation. Still, keeping it minimal, I'll just go with \"2\". That's all they need!"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 10,
"completion_tokens": 71,
"total_tokens": 81,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0,
"text_tokens": 0,
"image_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 64,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0,
"text_tokens": 0,
"cached_tokens": 0
}
}
}curl --location 'https://oneapi.laisky.com/v1/audio/transcriptions' \
--header 'Authorization: Bearer laisky-xxxxxxx' \
--form 'file=@"postman-cloud:///1efcd71f-7206-4a70-94d1-7727d79d124b"' \
--form 'model="whisper-1"' \
--form 'response_format="verbose_json"'Response:
{
"task": "transcribe",
"language": "english",
"duration": 3.869999885559082,
"text": "Hello everyone, nice to see you today",
"segments": [
{
"id": 0,
"seek": 0,
"start": 0.0,
"end": 3.680000066757202,
"text": " Hello everyone, nice to see you today",
"tokens": [50364, 2425, 1518, 11, 1481, 281, 536, 291, 965, 50548],
"temperature": 0.0,
"avg_logprob": -0.44038617610931396,
"compression_ratio": 0.8604651093482971,
"no_speech_prob": 0.002639062935486436
}
],
"usage": {
"type": "duration",
"seconds": 4
}
}curl --location 'https://oneapi.laisky.com/v1/images/edits' \
--header 'Authorization: sk-xxxxxxx' \
--form 'image[]=@"postman-cloud:///1f020b33-1ca1-4f10-b6d2-7b12aa70111e"' \
--form 'image[]=@"postman-cloud:///1f020b33-22c6-4350-8314-063db53618a4"' \
--form 'prompt="put all items in references image into a gift busket"' \
--form 'model="gpt-image-1"'Response:
{
"created": 1762038453,
"data": [
{
"url": "https://xxxxxxx.png"
}
]
}curl --location 'https://oneapi.laisky.com/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "gpt-4o-audio-preview",
"max_tokens": 200,
"modalities": ["text", "audio"],
"audio": { "voice": "alloy", "format": "pcm16" },
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "what is in this recording"
},
{
"type": "input_audio",
"input_audio": {
"data": "<BASE64_ENCODED_AUDIO_DATA>",
"format": "mp3"
}
}
]
}
]
}'Response:
{
"id": "chatcmpl-CXEuXGd0MagiwenLiOtDhLNMHZs63",
"object": "chat.completion",
"created": 1762038177,
"model": "gpt-4o-audio-preview-2025-06-03",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"refusal": null,
"audio": {
"id": "audio_690691a2f0248191be5a199d7a49968b",
"data": "<BASE64_ENCODED_AUDIO_DATA>",
"expires_at": 1762041778,
"transcript": "The recording contains a greeting where someone is saying, \"Hello everyone, nice to see you today.\" It sounds like a friendly and casual greeting"
},
"annotations": []
},
"finish_reason": "length"
}
],
"usage": {
"prompt_tokens": 64,
"completion_tokens": 200,
"total_tokens": 264,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 38,
"text_tokens": 26,
"image_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 159,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0,
"text_tokens": 41
}
},
"service_tier": "default",
"system_fingerprint": "fp_363417d4a6"
}support gpt-4o-search-preview & gpt-4o-mini-search-preview
curl --location 'https://oneapi.laisky.com/v1/chat/completions?thinking=true&reasoning_format=thinking' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "gpt-4o-mini-search-preview",
"max_tokens": 1024,
"stream": false,
"messages": [
{
"role": "user",
"content": "what'\''s the weather in ottawa canada?"
}
]
}'Response:
{
"id": "resp_0a8e4f5c5f4e4b8f0069068d3f4bb88191f3e1e4b8f4c3faab",
"model": "gpt-4o-mini-search-preview",
"object": "chat.completion",
"created": 1762041234,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The current weather in Ottawa, Canada is partly cloudy with a temperature of 22°C (72°F). There is a light breeze coming from the northwest at 10 km/h (6 mph). Humidity is at 60%, and there is no precipitation expected today. For more detailed and up-to-date information, please check a reliable weather website or app.",
"thinking": "**Using web search to find current weather information**\n\nI searched for the latest weather updates for Ottawa, Canada. Based on the most recent data available, I found that the weather is partly cloudy with a temperature of 22°C (72°F). I also noted the wind speed and direction, humidity levels, and the absence of precipitation. This information should help the user understand the current weather conditions in Ottawa."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 15,
"completion_tokens": 150,
"total_tokens": 165,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0,
"text_tokens": 15,
"image_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 130,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0,
"text_tokens": 20,
"cached_tokens": 0
}
}
}Response:
{
"id": "chatcmpl-3ba4b046-577a-4cbd-8ebc-80b48607e6ee",
"object": "chat.completion",
"created": 1762038412,
"model": "gpt-4o-mini-search-preview-2025-03-11",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "As of 6:06 PM on Saturday, November 1, 2025, in Ottawa, Canada, the weather is mostly cloudy with a temperature of 38°F (4°C).\n\n## Weather for Ottawa, ON:\nCurrent Conditions: Mostly cloudy, 38°F (4°C)\n\nDaily Forecast:\n* Saturday, November 1: Low: 35°F (1°C), High: 43°F (6°C), Description: Cloudy and breezy with a shower in spots\n* Sunday, November 2: Low: 36°F (2°C), High: 46°F (8°C), Description: Cloudy in the morning, then times of clouds and sun in the afternoon\n* Monday, November 3: Low: 36°F (2°C), High: 51°F (11°C), Description: Cloudy and breezy with showers\n* Tuesday, November 4: Low: 34°F (1°C), High: 52°F (11°C), Description: Mostly sunny and breezy\n* Wednesday, November 5: Low: 36°F (2°C), High: 44°F (7°C), Description: Cloudy with a couple of showers, mainly later\n* Thursday, November 6: Low: 29°F (-1°C), High: 44°F (7°C), Description: A little morning rain; otherwise, cloudy most of the time\n* Friday, November 7: Low: 32°F (0°C), High: 45°F (7°C), Description: Mostly cloudy\n\n\nIn November, Ottawa typically experiences cool and damp conditions, with average high temperatures around 5°C (41°F) and lows near -2°C (28°F). The city usually receives about 84 mm (3.3 inches) of precipitation over 14 days during the month. ([weather2visit.com](https://www.weather2visit.com/north-america/canada/ottawa-november.htm?utm_source=openai)) ",
"refusal": null,
"annotations": [
{
"type": "url_citation",
"url_citation": {
"end_index": 1358,
"start_index": 1247,
"title": "Ottawa Weather in November 2025 | Canada Averages | Weather-2-Visit",
"url": "https://www.weather2visit.com/north-america/canada/ottawa-november.htm?utm_source=openai"
}
}
]
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 411,
"total_tokens": 420,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": ""
}Support gpt-image-1 & gpt-image-1-mini for image generation and editing.
Draw image:
curl --location 'https://oneapi.laisky.com/v1/images/generations' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "gpt-image-1-mini",
"prompt": "draw a goose",
"n": 1,
"size": "1024x1024",
"response_format": "b64_json"
}'Response:
{
"created": 1763152907,
"background": "opaque",
"data": [
{
"b64_json": "iVBORw0KGgoAAAANS..."
}
],
"output_format": "png",
"quality": "high",
"size": "1536x1024",
"usage": {
"input_tokens": 437,
"input_tokens_details": {
"image_tokens": 388,
"text_tokens": 49
},
"output_tokens": 6208,
"total_tokens": 6645
}
}Edit image:
curl --location 'https://oneapi.laisky.com/v1/images/edits' \
--header 'Authorization: sk-xxxxxxx' \
--form 'image[]=@"postman-cloud:///1f020b33-1ca1-4f10-b6d2-7b12aa70111e"' \
--form 'image[]=@"postman-cloud:///1f020b33-22c6-4350-8314-063db53618a4"' \
--form 'prompt="put all items in references image into a gift busket"' \
--form 'model="gpt-image-1-mini"'Response:
{
"created": 1763152907,
"background": "opaque",
"data": [
{
"b64_json": "iVBORw0KGgoAAAANS..."
}
],
"output_format": "png",
"quality": "high",
"size": "1536x1024",
"usage": {
"input_tokens": 437,
"input_tokens_details": {
"image_tokens": 388,
"text_tokens": 49
},
"output_tokens": 6208,
"total_tokens": 6645
}
}curl --location 'https://oneapi.laisky.com/v1/responses' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "gemini-2.5-flash",
"input": "Tell me a three sentence bedtime story about a unicorn."
}'Response:
{
"id": "resp-2025110123121283977003996295227",
"object": "response",
"created_at": 1762038734,
"status": "completed",
"model": "gemini-2.5-flash",
"output": [
{
"type": "message",
"status": "completed",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "Lily the unicorn lived in a meadow where rainbows touched the ground. Every evening, she would gallop beneath the starry sky, her horn glowing like a tiny lantern. When she finally nestled into her bed of soft moss, all the little forest creatures drifted off to sleep, feeling safe and warm."
}
]
}
],
"usage": {
"input_tokens": 12,
"output_tokens": 151,
"total_tokens": 163
},
"parallel_tool_calls": false
}gpt-5.1-chat-latest / gpt-5.1 / gpt-5.1-2025-11-13 / gpt-5.1-codex / gpt-5.1-codex-mini
gpt-5-chat-latest / gpt-5 / gpt-5-mini / gpt-5-nano / gpt-5-codex / gpt-5.1-codex-max/ gpt-5-pro
curl --location 'https://oneapi.laisky.com/v1/chat/completions?thinking=true&reasoning_format=thinking' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "o4-mini-deep-research",
"max_tokens": 9086,
"stream": false,
"messages": [
{
"role": "user",
"content": "what'\''s the weather in ottawa canada?"
}
]
}'Response:
Note
To run deep‑research successfully, you need to configure a comparatively large max_tokens value. This response was cut off due to the max_tokens limit you set.
{
"id": "resp_0457d54ec43cbbe2006906945811f081a28fce9f1839c1fa67",
"model": "o4-mini-deep-research",
"object": "chat.completion",
"created": 1762038872,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "",
"thinking": "**Finding current weather in Ottawa**\n\nThe user asked about the current weather in Ottawa, Canada, which means I need to retrieve up-to-date weather information. I can't rely on past knowledge here; I should search for current weather reports specifically for that location. It's November 1, 2025, so it's essential to consider both the time and place as I look for reliable sources, like local weather sites or official forecasts, to provide the user with accurate information.**Searching for current weather**\n\nThis looks like a weather query that requires me to retrieve the latest information. I need to remember that the instructions emphasize using searches for up-to-date data and not relying solely on past knowledge. Since the guidelines don't prohibit weather queries, I should feel safe in proceeding. I’ll look up the current weather for Ottawa, Canada, using a browser search to ensure I provide accurate and timely information for the user."
},
"finish_reason": "length"
}
],
"usage": {
"prompt_tokens": 31134,
"completion_tokens": 2608,
"total_tokens": 33742,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0,
"text_tokens": 0,
"image_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 2624,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0,
"text_tokens": 0,
"cached_tokens": 0
}
}
}# vi $HOME/.codex/config.toml
model = "gemini-2.5-flash"
model_provider = "laisky"
[model_providers.laisky]
# Name of the provider that will be displayed in the Codex UI.
name = "Laisky"
# The path `/chat/completions` will be amended to this URL to make the POST
# request for the chat completions.
base_url = "https://oneapi.laisky.com/v1"
# If `env_key` is set, identifies an environment variable that must be set when
# using Codex with this provider. The value of the environment variable must be
# non-empty and will be used in the `Bearer TOKEN` HTTP header for the POST request.
env_key = "sk-xxxxxxx"
# Valid values for wire_api are "chat" and "responses". Defaults to "chat" if omitted.
wire_api = "responses"
# If necessary, extra query params that need to be added to the URL.
# See the Azure example below.
query_params = {}
Create Video Task:
curl --location 'https://oneapi.laisky.com/v1/videos' \
--header 'Authorization: sk-xxxxxxx' \
--form 'prompt="aurora"' \
--form 'model="sora-2"' \
--form 'seconds="4"' \
--form 'size="1280x720"'Response:
{
"id": "video_691608967fe8819399e710799dae2ae708872b008b63ff61",
"object": "video",
"created_at": 1763051670,
"status": "queued",
"completed_at": null,
"error": null,
"expires_at": null,
"model": "sora-2",
"progress": 0,
"prompt": "aurora",
"remixed_from_video_id": null,
"seconds": "4",
"size": "1280x720"
}Get Video Task Status:
curl --location 'https://oneapi.laisky.com/v1/videos/video_691608967fe8819399e710799dae2ae708872b008b63ff61'
--header 'Authorization: sk-xxxxxxx'Response:
{
"id": "video_691611812ca88190bfb123716dcc953a089a232f54b02b21",
"object": "video",
"created_at": 1763053953,
"status": "completed",
"completed_at": 1763054021,
"error": null,
"expires_at": 1763057621,
"model": "sora-2",
"progress": 100,
"prompt": "aurora",
"remixed_from_video_id": null,
"seconds": "4",
"size": "1280x720"
}Download Video:
curl --location 'https://oneapi.laisky.com/v1/videos/video_691611812ca88190bfb123716dcc953a089a232f54b02b21/content'
--header 'Authorization: sk-xxxxxxx'By default, the thinking mode is not enabled. You need to manually pass the thinking field in the request body to enable it.
export ANTHROPIC_MODEL="openai/gpt-oss-120b"
export ANTHROPIC_BASE_URL="https://oneapi.laisky.com/"
export ANTHROPIC_AUTH_TOKEN="sk-xxxxxxx"You can use any model you like for Claude Code, even if the model doesn’t natively support the Claude Messages API.
claude-opus-4-0 / claude-opus-4-1 / claude-opus-4-5 / claude-sonnet-4-0 / claude-sonnet-4-5 / claude-haiku-4-5
Support gemini-3-pro-preview, gemini-3-pro-image-preview
opencode.ai is an AI coding agent built for the terminal. OpenCode is fully open source, giving you control and freedom to use any provider, any model, and any editor. It's available as both a CLI and TUI.
One‑API integrates seamlessly with OpenCode: you can connect any One‑API endpoint and use all your unified models through OpenCode's interface (both CLI and TUI).
To get started, create or edit ~/.config/opencode/opencode.json like this:
Using OpenAI SDK:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"one-api": {
"npm": "@ai-sdk/openai",
"name": "One API",
"options": {
"baseURL": "https://oneapi.laisky.com/v1",
"apiKey": "<ONEAPI_TOKEN_KEY>"
},
"models": {
"gpt-4.1-2025-04-14": {
"name": "GPT 4.1"
}
}
}
}
}Using Anthropic SDK:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"one-api-anthropic": {
"npm": "@ai-sdk/anthropic",
"name": "One API (Anthropic)",
"options": {
"baseURL": "https://oneapi.laisky.com/v1",
"apiKey": "<ONEAPI_TOKEN_KEY>"
},
"models": {
"claude-sonnet-4-5": {
"name": "Claude Sonnet 4.5"
}
}
}
}
}By default, the thinking mode is automatically enabled for the deepseek-r1 model, and the response is returned in the open-router format.
curl --location 'https://oneapi.laisky.com/v1/rerank' \
--header 'Content-Type: application/json' \
--header 'Authorization: sk-xxxxxxx' \
--data '{
"model": "rerank-v3.5",
"query": "What is the capital of the United States?",
"top_n": 3,
"documents": [
"Carson City is the capital city of the American state of Nevada.",
"The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan.",
"Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district.",
"Capitalization or capitalisation in English grammar is the use of a capital letter at the start of a word. English usage varies from capitalization in other languages.",
"Capital punishment has existed in the United States since beforethe United States was a country. As of 2017, capital punishment is legal in 30 of the 50 states."
]
}'
Response:
{
"object": "cohere.rerank",
"model": "rerank-v3.5",
"id": "ff9458ce-318b-4317-ad49-f8654c976dff",
"results": [
{
"index": 2,
"relevance_score": 0.8742601
},
{
"index": 0,
"relevance_score": 0.17292508
},
{
"index": 4,
"relevance_score": 0.10793502
}
],
"meta": {
"api_version": {
"version": "2",
"is_experimental": false
},
"billed_units": {
"search_units": 1
}
},
"usage": {
"prompt_tokens": 153,
"total_tokens": 153
}
}Support:
kimi-k2-0905-previewkimi-k2-0711-previewkimi-k2-turbo-previewkimi-k2-thinkingkimi-k2-thinking-turbo
Support:
glm-zero-previewglm-3-turbocogview-3-flashcodegeex-4embedding-3embedding-2
glm-4.6glm-4.5glm-4.5-xglm-4.5-airglm-4.5-airxglm-4.5-flashglm-4v-flash
- BUGFIX: Several issues when updating tokens #1933
- feat(audio): count whisper-1 quota by audio duration #2022
- fix: Fix issue where high-quota users using low-quota tokens aren't pre-charged, causing large token deficits under high concurrency #25
- fix: channel test false negative #2065
- fix: resolve "bufio.Scanner: token too long" error by increasing buffer size #2128
- feat: Enhance VolcEngine channel support with bot model #2131
- fix: models API returns models in deactivated channels #2150
- fix: Automatically close channel when connection fails
- fix: update EmailDomainWhitelist submission logic #33
- fix: send ByAll
- fix: oidc token endpoint request body #2106 #36
Note
For additional enterprise-grade improvements, including security enhancements (e.g., vulnerability fixes), you can also view these pull requests here.





















