Kimi Code API URL: Base URL Setup for OpenAI Clients
The Kimi Code API URL you need for this service is https://api.kimicode.cc/v1. Put it in any OpenAI client as the base URL, add your key, and use the model ID uncensored.
Updated

The URL and what each part means
If you are searching for the kimi code api url, you may be looking for the address of Kimi's own service. For that, use the documentation from the vendor, since I cannot vouch for it. This site runs a different thing: a hosted, OpenAI-compatible API in front of one open-weight model, run by an independent provider. Its address is:
https://api.kimicode.cc/v1
That string is the base URL. It is the part every request shares. The SDK adds the rest. When you call chat.completions.create, the OpenAI library sends a POST to https://api.kimicode.cc/v1/chat/completions. The model list lives at https://api.kimicode.cc/v1/models and takes a GET.
Those two are the only methods this API serves: POST /v1/chat/completions and GET /v1/models. If you were hoping for image, audio or embedding endpoints, they do not exist here. It is a text API.
Three settings matter, and nothing else has to change in your existing OpenAI code: the base URL, the API key, and the model ID uncensored.
Why a base URL is the only switch
OpenAI-style clients are built around one idea: the request format is fixed, and the host is a setting. The library has a default host that points at the original vendor. When you replace it with another base URL, the same request body goes somewhere else. Nothing in your prompts, message arrays or response parsing has to change.
That is why a migration from another OpenAI-compatible provider is usually three edits: the base URL, the key, and the model name. The fields in the response, such as choices, message, finish_reason and usage, have the same names, so code that reads them keeps working.
It also explains the odd errors people hit. If a tool asks for a "server URL" and you paste only the host, the path is missing. If a tool asks for a "full endpoint" and you paste the base, the request goes to the wrong place. When a settings screen is unclear, try the base URL first and read the status code that comes back. The quickstart in the docs walks through the same migration with one more example.
Environment variables for tools you cannot edit
Many command-line tools and frameworks build an OpenAI client without letting you touch the constructor. They usually read the standard environment variables, so setting them is enough:
export OPENAI_BASE_URL="https://api.kimicode.cc/v1"
export OPENAI_API_KEY="YOUR_KEY"
Some older tools look for OPENAI_API_BASE instead, so if one ignores the first name, try the second. After setting them, start the tool in the same shell session, since variables set in another terminal window are not shared.
The tool will still need a model name. If it hard-codes a hosted model, look for a flag or config line that sets it, and use uncensored. If it cannot be changed, the tool is not a fit, and a small script like the ones above is a better path.
Get a key first
Requests are authenticated with a header of the form Authorization: Bearer YOUR_KEY. Every official SDK builds that header for you from the api_key argument. You can create the key after signing in with Google or with an email and password.
New accounts can claim $0.50 of trial credit with one click on the API key page. It needs no card and lasts 7 days. That is enough to run every example below many times over. Trial keys allow 2 concurrent requests and 60 requests per minute, so run the examples one at a time.
Store the key in an environment variable instead of in source files. A key committed to a public repository will be found and used by someone else within hours, and the credit it holds is yours.
First request in curl
Curl is the fastest way to prove the URL works, because it removes every library from the picture. If this call succeeds, any problem you meet later is in your client configuration.
export KIMICODE_KEY="YOUR_KEY"
curl https://api.kimicode.cc/v1/models -H "Authorization: Bearer $KIMICODE_KEY"
curl https://api.kimicode.cc/v1/chat/completions -H "Authorization: Bearer $KIMICODE_KEY" -H "Content-Type: application/json" -d '{
"model": "uncensored",
"messages": [
{"role": "user", "content": "Say hello in five words."}
]
}'
The first call returns the model list, which should include uncensored. The second returns a standard chat completion object. Look at the response headers with curl -i and you will see X-Request-Id, X-Balance-USD, X-RateLimit-Limit-Requests and X-RateLimit-Limit-Concurrency. Keep the request ID if you ever contact support about a specific call.
Python with the OpenAI SDK
Install the library with pip install openai, then change two arguments on the client constructor.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.kimicode.cc/v1",
api_key=os.environ["KIMICODE_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You are a concise assistant."},
{"role": "user", "content": "Explain what a base URL is in two sentences."},
],
temperature=0.7,
)
print(resp.choices[0].message.content)
print(resp.usage)
Parameters such as temperature, top_p, stop, seed and the frequency and presence penalties are passed through to the model. The max_tokens value is optional. Without it the completion can use whatever is left of the 100,000-token window, which is the prompt and the completion combined.
The SDK also reads two environment variables if you do not pass arguments: OPENAI_BASE_URL and OPENAI_API_KEY. That is useful for tools you cannot edit. Set both, launch the tool, and it talks to this API.
Node, streaming and JSON mode
The Node setup mirrors Python. Install with npm install openai.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.kimicode.cc/v1",
apiKey: process.env.KIMICODE_KEY,
});
// Streaming over SSE
const stream = await client.chat.completions.create({
model: "uncensored",
stream: true,
messages: [{ role: "user", content: "Write a four-line poem about routers." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
// JSON mode
const json = await client.chat.completions.create({
model: "uncensored",
response_format: { type: "json_object" },
messages: [
{ role: "system", content: "Reply with a JSON object only." },
{ role: "user", content: "Give me keys name and port for a local dev server." },
],
});
console.log(JSON.parse(json.choices[0].message.content));
Streaming uses server-sent events and usage is reported at the end of the stream. A streamed request holds its concurrency slot until the stream finishes, so a client that opens a stream and never reads it will block a slot. With JSON mode, still tell the model in the prompt to answer in JSON. The flag constrains the output format, but a clear instruction gives you better field names.
Tool calling
Tools use the usual OpenAI shape: a tools list, an optional tool_choice, and tool results sent back as messages with role: "tool". When streaming, the tool_calls arrive in pieces across chunks.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.kimicode.cc/v1", api_key=os.environ["KIMICODE_KEY"])
tools = [{
"type": "function",
"function": {
"name": "get_port",
"description": "Look up the port of a named local service",
"parameters": {
"type": "object",
"properties": {"service": {"type": "string"}},
"required": ["service"],
},
},
}]
messages = [{"role": "user", "content": "Which port does the api service use?"}]
first = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
call = first.choices[0].message.tool_calls[0]
messages.append(first.choices[0].message)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps({"service": "api", "port": 8080}),
})
final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
print(final.choices[0].message.content)
Treat arguments from the model as untrusted input. Validate them before you run anything. The model may skip a tool call or call it with a wrong field, as any model can, so keep a fallback path in your loop.
When the URL fails
Most failures fall into a short list.
- 404 Not Found. The path is wrong. Common causes: the base URL was set to
https://api.kimicode.ccwithout/v1, or tohttps://api.kimicode.cc/v1/chat/completionsso the client appends the path twice. Use exactly the base URL above. - 401 Unauthorized. The key is missing, has a stray space or newline, or the header is not a Bearer token. Print the length of the variable to check.
- 429 with code
rate_limited. You passed the per-minute cap: 300 requests for a full key, 60 for a trial key. - 429 with code
concurrency. Too many requests at once: 8 for a full key, 2 for a trial key. - 429 with a
Retry-After: 5header. Temporary overload. Wait five seconds and retry. - Request too large. The body limit is 8 MB, and the prompt plus completion must fit 100,000 tokens.
A retry loop that honours Retry-After and backs off on the other two codes handles nearly all of this. Cost per call is small; the pricing page has the per-token rates, and the docs quickstart shows the migration steps from another OpenAI-style provider.
Retries and production habits
Once the first call works, add a retry wrapper before you ship. Honour the Retry-After header when it is present and back off with a short random delay otherwise.
import os, time, random
from openai import OpenAI, RateLimitError
client = OpenAI(base_url="https://api.kimicode.cc/v1", api_key=os.environ["KIMICODE_KEY"])
def ask(messages, tries=5):
for attempt in range(tries):
try:
return client.chat.completions.create(model="uncensored", messages=messages)
except RateLimitError as err:
retry_after = 5
if getattr(err, "response", None) is not None:
retry_after = int(err.response.headers.get("retry-after", 5))
time.sleep(retry_after + random.random())
raise RuntimeError("still rate limited after retries")
Cap your own concurrency to match your key: a thread pool of 8 for a full key, 2 for a trial key. That stops the concurrency error before it starts, and it keeps you inside the 300 requests per minute limit as well when each call takes more than a couple of seconds.
Finally, remember that you pay per token. Log the usage object for each call, and watch the X-Balance-USD header. At $0.15 per 1M input tokens and $0.50 per 1M output tokens, a typical chat turn is a fraction of a cent, but loops and long histories add up, and the log tells you where.
More guides
Questions and answers
What is the base URL for this API?
https://api.kimicode.cc/v1. Set it as the base URL in any OpenAI-compatible client and leave the path after it to the library.
Which model ID do I send?
Send uncensored as the model value. You can confirm it by calling GET /v1/models with your key.
Can I use the official Kimi endpoint with my key from here?
No. This is a separate service with its own keys and one open-weight model, not the official API of any vendor. Keys do not carry over in either direction.
Why do I get 404 on chat completions?
The base URL probably lacks /v1 or already includes /chat/completions. Use https://api.kimicode.cc/v1 and nothing more.
Your key is one form away
Create an account, copy the key, change the base URL. That is the whole setup.
Get API key