An OpenAI-compatible HTTP gateway that exposes the public
https://kimi-ai.chat/chat/ chat demo as a local /v1/chat/completions
endpoint. The gateway is a thin protocol adapter: it forwards requests
to the demo's public AJAX endpoint, refreshes the page nonce
transparently, and re-emits the upstream SSE stream in OpenAI format.
Disclaimer. The upstream site is an unofficial third-party demo, not the official Moonshot / Kimi service. Do not send personal data, secrets, or any other sensitive information through this gateway. The project authors are not affiliated with the upstream site and do not guarantee its availability or behaviour.
- OpenAI-compatible
POST /v1/chat/completions(non-streaming and SSE streaming). - OpenAI-compatible
GET /v1/modelsreturning the configured model aliases. GET /healthzfor liveness checks.- Bearer-token and
X-API-Keyauthentication with constant-time key comparison. - Automatic page-nonce refresh with a single-shot retry on stale nonces.
- Optional single-image support via
image_urldata URLs.
- The upstream protocol is a public demo. The
modelfield is accepted for OpenAI compatibility but does not select a different upstream model. Pass the configured alias (defaultkimi-ai-chat). - Sampling fields (
temperature,top_p,max_tokens,stop, ...) are accepted for compatibility but the upstream does not honour them. The gateway does not fabricate their effect. - Token usage is unavailable. The OpenAI
usageblock is always reported as zeros. - At most one image
data:URL per request is supported. Remote image URLs, audio, video, multi-image inputs, and any non-textual content part are rejected with HTTP 400. tools,tool_choice, and function calling are not supported; requests containing them are rejected with HTTP 400. The gateway does not emulate tool use through prompt tricks.- Single-session concurrency is capped by
UPSTREAM_MAX_CONCURRENT(default 1) to be polite to the demo.
- Python 3.13+
uvfor dependency management
uv sync --dev
copy .env.example .env
# Edit .env and replace API_KEYS with a long random value.
uv run uvicorn main:app --host 0.0.0.0 --port 8000API_KEYS is a comma-separated list of accepted client keys. The
sample value shipped in .env.example is a placeholder and is rejected
at startup. Replace it with a long random secret before running the
server in any environment that accepts real traffic.
The server is reachable at http://<host>:<port> (defaults:
0.0.0.0:8000).
All settings are loaded via pydantic-settings from .env or the
process environment. See .env.example for the full list. Notable
names:
| Variable | Purpose |
|---|---|
HOST, PORT |
Uvicorn bind address and port. |
LOG_LEVEL |
Uvicorn / app log level. |
API_KEYS |
Comma-separated accepted client keys. |
DEFAULT_MODEL |
Default model alias returned by /v1/models. |
MODEL_ALIASES |
Comma-separated exposed aliases; must include DEFAULT_MODEL. |
UPSTREAM_PAGE_URL |
Public chat page used for nonce refresh. |
UPSTREAM_AJAX_URL |
Optional override for the AJAX endpoint. |
UPSTREAM_TIMEOUT_SECONDS |
Upstream HTTP timeout (seconds). |
UPSTREAM_REFRESH_SECONDS |
How often to refresh the cached page nonce. |
UPSTREAM_MAX_CONCURRENT |
Concurrency cap for upstream calls (default 1). |
UPSTREAM_MAX_MESSAGE_LENGTH |
Max combined user content length per request. |
UPSTREAM_MAX_CONVERSATION |
Max number of messages per request. |
ENABLE_IMAGES |
Whether to accept image_url data URLs. |
TRUST_PROXY_HEADERS |
Whether to honour forwarded host / scheme headers. |
CORS_ORIGINS |
Comma-separated allowed CORS origins (empty disables CORS). |
Every /v1/* endpoint requires an API key. Either header is accepted:
Authorization: Bearer <API_KEY>
X-API-Key: <API_KEY>
Keys are compared with hmac.compare_digest (constant time). Invalid or
missing keys return HTTP 401 with an OpenAI-shaped error body. The raw
key is never logged.
Lists the configured model aliases. No upstream call is made.
curl http://127.0.0.1:8000/v1/models \
-H "Authorization: Bearer $GATEWAY_API_KEY"Accepts the standard OpenAI Chat Completions payload. stream may be
false (default) or true. See Limitations above for unsupported
fields.
Non-streaming example:
curl http://127.0.0.1:8000/v1/chat/completions \
-H "Authorization: Bearer $GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"kimi-ai-chat","messages":[{"role":"user","content":"你好"}]}'Streaming example:
curl http://127.0.0.1:8000/v1/chat/completions \
-H "Authorization: Bearer $GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"kimi-ai-chat","messages":[{"role":"user","content":"你好"}],"stream":true}'The streaming response is text/event-stream with data: {...} chunks
terminated by data: [DONE], matching the OpenAI streaming format.
Returns 200 whenever the gateway has loaded its configuration. The
response body reports the upstream session status (uninitialized,
ready, or error) but never includes the nonce, cookies, or API
keys. This endpoint never performs an upstream call.
The upstream page embeds a short-lived nonce that must accompany each
chat request. The gateway caches the most recent nonce, refreshes it
after UPSTREAM_REFRESH_SECONDS, and transparently retries once when
the upstream rejects a request with a stale nonce (HTTP 401/403 or an
SSE error event of type nonce_invalid). The refresh happens under a
lock so concurrent requests share a single page fetch.
- Treat
kimi-ai.chatas an untrusted, unofficial service. Do not send personal data, credentials, source code, or any sensitive prompt content through this gateway. - Real
.envfiles are git-ignored. Only.env.exampleis committed. - The HAR file used during development (
kimi-ai.chat_*.har) contains session cookies and account-related traffic for the demo. Do not commit it to a repository or share it publicly. If you obtained a copy locally, keep it off disk once you no longer need it and never include it in pull requests or issue attachments.
uv sync --dev
uv run pytest -q
uv run python -m compileall kimi_gateway main.pymain.py # uvicorn entry point
kimi_gateway/ # application package (app, routes, auth, protocol, upstream)
tests/ # pytest suite (config, auth, protocol, upstream, app)
docs/superpowers/ # design spec and implementation plan
No license has been declared. Add one before publishing a public distribution of this project.