The short version: Moonshot is retiring two legacy models — kimi-k2.5 and moonshot-v1 — on August 31, 2026. New accounts already can't select either (they've been blocked since July 17), and after the cutoff any request that names them errors. The fix is a one-string change per call, because the Kimi API stays OpenAI-compatible. The real decision isn't the code — it's which replacement. The tempting answer, kimi-k3, is the new flagship and about 3x the price. For most routine work the like-for-like successor is kimi-k2.7-code, which isn't on the retirement list at all.

What is actually being retired#

kimi-k2.5 and moonshot-v1 are the two model IDs that older integrations tend to hard-code — moonshot-v1 especially, since it's the name from Moonshot's first API generation that a lot of early adopters never changed. Both are now on a fixed sunset: unusable for new accounts since July 17, gone for everyone on August 31, 2026. This is the Kimi-side echo of the same housekeeping DeepSeek did in July when it retired deepseek-chat and deepseek-reasoner — legacy aliases getting swept up as the frontier moves.

The mapping — and why K3 is the wrong default#

Here's the part most "just upgrade to the newest model" advice gets wrong:

kimi-k3 is a genuine step up — a 2.8-trillion-parameter MoE with native vision and a 1,048,576-token window — but it lists at $3 / $15 per million input/output tokens, roughly 3x the tier kimi-k2.5 lived in. Route your entire legacy workload to it and you've quietly tripled your token bill for calls that never needed frontier quality.

The loud failure is an error on September 1. The quiet failure is a tripled invoice because you find-and-replaced every old model name with the most expensive new one.

The migration: one line#

Because the API is OpenAI-compatible, you keep your SDK, base URL, and auth — you change the model string. In Python with the OpenAI client:

from openai import OpenAI

client = OpenAI(
    api_key="YOUR_MOONSHOT_KEY",
    base_url="https://api.moonshot.ai/v1",   # confirm your region's URL in the console
)

# BEFORE — errors after 2026-08-31
# resp = client.chat.completions.create(
#     model="kimi-k2.5",
#     messages=[{"role": "user", "content": "Refactor this function."}],
# )

# AFTER — routine coding: like-for-like successor, not the pricey flagship
resp = client.chat.completions.create(
    model="kimi-k2.7-code",
    messages=[{"role": "user", "content": "Refactor this function."}],
)

And the same swap over raw HTTP:

curl https://api.moonshot.ai/v1/chat/completions \
  -H "Authorization: Bearer $MOONSHOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kimi-k2.7-code",
    "messages": [{"role": "user", "content": "Refactor this function."}]
  }'

Then grep wider than you think you need to. Legacy names hide in prompt configs, notebooks, eval harnesses, and env files — not just the one call you remember:

grep -rn "kimi-k2\.5\|moonshot-v1" . --include="*.py" --include="*.js" \
  --include="*.ts" --include="*.json" --include="*.env" --include="*.ipynb"

Where you do move to K3, cache aggressively#

For the calls that genuinely warrant kimi-k3 — vision, long context, the hardest reasoning — the lever that keeps the price sane is prompt caching. Cache-hit input on k3 is $0.30 per million tokens against $3.00 uncached: a tenth. Agent and coding loops that resend a large, stable prefix (a system prompt, a repository dump, a tool schema) are the ideal shape — keep that prefix byte-identical across calls so it lands on the cache instead of getting re-billed at full rate. We walked through the effective-price math in how to use Kimi K3 cheaply, and if you're weighing K3 against the closed flagships for an agent backend, Kimi K3 vs Opus vs GPT-5.6 on coding-agent cost is the decision in one table.

The 10-minute checklist#

  1. Find every legacy name. Grep code, configs, notebooks, and env files for kimi-k2.5 and moonshot-v1.
  2. Map by workload, not by reflex. Routine coding/chat → kimi-k2.7-code. Frontier reasoning, vision, or ~1M context → kimi-k3.
  3. Pin the explicit model ID and log which model each request used, so the next retirement is a scheduled diff.
  4. Turn on prompt caching wherever you moved to k3 and resend a stable prefix.
  5. Verify in the console. Confirm the exact base URL and model IDs for your region and account before you ship — then watch cost for a day.

This is the second time this summer a major provider has retired the model names a lot of us hard-coded, and it won't be the last — the assistants-and-Sonnet August deadlines land in the same window. The change itself is one string. The discipline is refusing to let convenience pick your model: pin the name, split by workload, own the switch before August 31 does it for you.