new-api

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

8posts · 30d
Nov 30 posts
  1. 提醒一下各位做API中转站的,如果在用new-api,要及时更新到v1.0.0-rc.46版本,昨天公开的那个零日漏洞CVE-2026-111943在这个版本修复了(地址:github.com/QuantumNous/new-api/releases/tag/v1.0.… 另外,大部分中转站应该是在docker上部署的,docker也更新了,最新版本是29.9.2,也需要更新(地址:docs.docker.com

    1 like · 48 views
  2. YouTube · · YouTube description · AI & Tech Today

    3 Trending GitHub Repos: CC Switch, New API & LocalAI – Where Your AI Calls Go Three repositories trending on GitHub today, explained in plain language: what each one does, how it works, who should try it, how to get started, and where the caveats are. This edition is all about the plumbing between AI tools and AI models: a desktop app that switches providers for your coding agents in one click, a self-hosted gateway that puts one API in front of every model provider for a whole team, and an engine that runs models on your own hardware. ⏱ Chapters 0:00 Intro & this week in dev tools 1:39 CC Switch: one app for your coding agents 4:43 New API: a self-hosted AI gateway 8:03 LocalAI: run any model on your own hardware 11:11 Summary 📦 Repos 1. farion1231/cc-switch – CC Switch, by Jason Young (Rust · MIT)farion1231/cc-switch 2. QuantumNous/new-api – New API, by QuantumNous (Go · AGPL-3.0)QuantumNous/new-api Docs: docs.newapi.ai 3. mudler/LocalAI – LocalAI, by Ettore Di Giacinto and the LocalAI team (Go · MIT)mudler/LocalAI Docs: localai.io 📰 News mentioned • OpenCode Console breach exposes stored API keys (Oct 17): techcrunch.com • VS Code 1.142 adds agent Canvases (Oct 14): code.visualstudio.com • GitHub open source license compliance generally available (Oct 16): github.blog Star counts are as of 21 October 2026. Features and claims are as described in each project's README and release notes; try them in your own setup before relying on them. If you found this useful, like and subscribe for the next round of trending repos. #GitHub #OpenSource #AI #DeveloperTools #LLM

    44 views
  3. DEV · · @mystical

    Панель говорила «осталось $189». Консоль говорила «$291». Оба числа были неверны. Наша статус-панель показывала израсходовано $10.80 из $200.00, осталось $189.20. Консоль провайдера в соседней вкладке показывала осталось $291.77. Один аккаунт, один день. Оба числа были неверны, и по разным причинам. Это разбор того, как найти число, которое на самом деле верно, и того изменения в дизайне, после которого панель больше не сможет смешать две разные системы учёта. Что за задача Это плагин для агентной обвязки Claude Code: мод, который регистрирует панель интерфейса и перерисовывает её по таймеру. Панель показывает остаток на счету рядом с окнами лимитов, заполнением контекста и стоимостью сессии. Написан на TypeScript, подгружается исходником при старте сессии, и у него есть набор тестов, который прогоняет его через поддельный движок. Провайдер — реселлер, работающий на new-api, открытой консоли, на которой построена изрядная доля реселлеров LLM-API (её предок one-api ведёт себя так же). Эта деталь пригодится дальше. Ошибка первая: лимит, которого никто не задавал Панель сравнивала расход с budgetUsd — настройкой со значением по умолчанию 200: const DEFAULT_BUDGET_USD = 200 Эти 200 никто не измерял. Это была заглушка, которая уехала в релиз, и поскольку она рисовалась с двумя знаками после запятой рядом с настоящим расходом, читалась она как данные. Панель уверенно сообщала, что осталось 189 долларов, — а это ровно тот сорт неверного ответа, который хуже, чем «неизвестно»: по нему начинаешь действовать. Расход брался из billing-API: GET /v1/dashboard/billing/usage {"total_usage": 3004} // центы Это endpoint, совместимый с OpenAI, и у этого провайдера он отдаёт другое число, чем консоль. Об этом ниже. Ошибка вторая: считалось не то Консоль отдаёт сам аккаунт: GET /api/user/self Authorization: Bearer <токен консоли> New-Api-User: <числовой id пользователя> {"data": {"quota": 145883249, "used_quota": 16616751}, "success": true} quota — сколько осталось, used_quota — сколько сожжено. Оба в единицах квоты, не в центах и не в долларах. Две засады, каждая стоила лишнего круга: - Заголовок New-Api-User не опционален. Без него запрос падает так, что это выглядит как плохой токен, — и идёшь перевыпускать токен на ровном месте. - Нужен коэффициент единиц. new-api и one-api по умолчанию кладут 500 000 единиц на доллар США, но это настраивается на конкретной установке, так что хардкодить его второй раз нельзя. Впрочем, искать коэффициент не пришлось. Подсказка была в самих числах: quota + used_quota дало 162 500 000, а собственная страница консоли показывала аккуратные $325.00 итого. Круглые итоги случайно не получаются. 162 500 000 / 325 = 500 000. Так что честное прочтение такое: осталось $291.77, израсходовано $33.23, всего $325.00. (Именно «всего» и позволило вычислить коэффициент; сама панель его больше не тащит — об этом в конце.) Две системы учёта не сходятся | Источник | Израсходовано | | --- | --- | | /v1/dashboard/billing/usage | $30.04 | | Консоль (used_quota) | $33.23 | Ни то, ни другое не ошибка округления. Если усреднить, получится число, верное сразу нигде. Решение здесь не арифметическое — надо выбрать, какой источник главный, и пометить каждую цифру тем, откуда она пришла, чтобы две системы учёта никогда не смешались молча. Это размеченное объединение и null: export type QuotaOrigin = 'console' | 'billing' export type QuotaBudget = { at: number origin: QuotaOrigin balanceUsd: number | null // только консоль spentUsd: number | null // только billing budgetUsd: number // ... } А слияние снимков переносит цифры только из прошлого снимка того же источника: const merged = (was: QuotaBudget | null, now: QuotaBudget): QuotaBudget => { const same = was !== null && was.origin === now.origin ? was : null return { origin: now.origin, balanceUsd: now.balanceUsd ?? same?.balanceUsd ?? null, spentUsd: now.spentUsd ?? same?.spentUsd ?? null, // ... } } Разбор ответа намеренно строг в том, что вообще считается ответом: const balanceOf = (body: unknown, quotaPerUnit: number) => { if (typeof body !== 'object' || body === null) return null const data = (body as Record<string, unknown>).data if (typeof data !== 'object' || data === null) return null const { quota } = data as Record<string, unknown> if (typeof quota !== 'number' || !Number.isFinite(quota) || quota < 0) return null return { balanceUsd: quota / quotaPerUnit } } Всё, что не конечное неотрицательное число, возвращает null, а null рисуется как «данных нет» — не как ноль и не как прошлонедельное число, выданное за сегодняшнее. Главный источник теперь консоль, а billing-API остался запасным путём на случай, когда токен консоли не задан: он работает с токеном сессии, который есть всегда. Процент принадлежит только запасному пути — это доля от предела, который назван в той же строке, — а в строке консоли одно число, и делить его не на что: const budgetPercent = (shown: QuotaBudget) => shown.spentUsd === null || shown.budgetUsd <= 0 ? 0 : Math.max(0, Math.min(100, (shown.spentUsd / shown.budgetUsd) * 100)) Тест, который держит это честным Самый полезный тест в наборе — тот, который проверяет, что запрос не был сделан: test('остаток счёта берётся из консоли, а billing-API не спрашивается', async ($, on) => { const asked: string[] = [] on('http.fetch', (_$, e) => { asked.push(e.url) if (e.url.includes('/api/user/self')) return { value: SELF } if (e.url.includes('/api/log/self?p=1')) return { value: logPage(ones(1), 1) } return { value: { status: 404, ok: false, headers: {}, text: '' } } }) // ... expect(await ui.find({ text: /^остаток \$291\.77$/ })).toBeDefined() expect(asked.some(url => url.includes('/v1/dashboard/billing/usage'))).toBe(false) }) Плюс отдельный — на заданный коэффициент единиц, и ещё один: консоль отвечает 500, а панель обязана показать прошлый консольный остаток, помеченный как устаревший, и с причиной: остаток $291.77 · 5 мин назад · ответ 500 Устаревшее с честной пометкой лучше свежего и выдуманного. Обе проверки привязаны к строке целиком: если рядом с остатком снова появится второй доллар, набор упадёт, а не пропустит его обратно. Что я сделал бы иначе - Никогда не выпускать правдоподобное значение по умолчанию для измерения. Именно 200 в роли «лимита» и был настоящей ошибкой. Значение по умолчанию, похожее на данные, прочитают как данные. Если значение неизвестно, интерфейс должен это сказать. - Коэффициент единиц — в настройки, а не во вторую константу. Коэффициент — свойство конкретной установки, и если он настраивается на стороне сервера, его в конце концов настроят. - Дать «неизвестно» собственное состояние. Пусто, ноль и устаревшее — три разные вещи. Схлопывание их в одно и есть то, из-за чего панель уверенно ошибается. - Токен сессии отправлять только на тот хост, для которого он настроен. Панель читает переменную окружения, в которой лежит в том числе учётка сессии; перед тем как её приложить, она сверяет хост запроса с настроенным базовым адресом провайдера, и на это поведение есть тест. Панель — отличное место, чтобы случайно утечь токеном. Сейчас панель показывает остаток $291.77, ровно как консоль провайдера. Она перестала угадывать. Вместе с этим ушли «всего» и полоса, показывавшая, какая доля пополнения израсходована. Когда есть остаток, по которому и принимаешь решение, это были ещё два числа в ответ на вопрос, которого никто не задавал, — а проценту полосы на экране не осталось знаменателя, чтобы хоть что-то значить. Что уже писали по этой теме Материалы с DEV, которые повлияли на то, как я об этом думал: - Monitoring API credit usage before an automation runs out — messora. Тот же отказ: сборщик совершенно здоров и тихо ничего не собирает, потому что баланс дошёл до нуля. - Three Ways to Monitor Prepaid API Balances (Excel, Python + Cron, Power Automate) — saint_vandora. Полезно о том, где такая проверка должна жить в конвейере, а не в интерфейсе. - Hard caps on autonomous agent API spend — infracore. Вопрос сложнее того, о котором эта панель только сообщает: как потолок не наблюдать, а обеспечивать.

  4. DEV · · @mystical

    The budget panel said $189 left. The console said $291. Both numbers were wrong. Our little status pane said $10.80 spent of $200.00, $189.20 left. The provider's console, open in the next tab, said $291.77 remaining. Same account, same day. Both numbers were wrong, and for different reasons. This is the write-up of finding the number that is actually true, and of the one-line-shaped design change that stops the pane from ever mixing two accountings again. The setup It's a plugin for the Claude Code agent harness: a mod that registers a UI pane and redraws it on a timer. It shows the account's remaining balance next to the rate-limit windows, the context fill, and the session cost. It runs in TypeScript, it is loaded as source at session start, and it has a test suite that drives it through a mocked engine. The provider is a reseller running new-api, the open-source console that a lot of LLM API resellers are built on (its ancestor, one-api, behaves the same way). That detail matters later. Bug one: a budget nobody set The pane compared a spend figure against budgetUsd, a config value with a default of 200: const DEFAULT_BUDGET_USD = 200 Nobody measured that 200. It was a placeholder that shipped, and because it was rendered with two decimal places next to a real spend number, it read as data. The pane confidently announced that 189 dollars were left, which is exactly the kind of wrong answer that is worse than "unknown" — you act on it. The spend figure came from the billing API: GET /v1/dashboard/billing/usage {"total_usage": 3004} // cents That endpoint is the OpenAI-compatible one, and on this provider it reports a different number from the console. More on that below. Bug two: it was counting the wrong thing The console exposes the account itself: GET /api/user/self Authorization: Bearer <console token> New-Api-User: <numeric user id> {"data": {"quota": 145883249, "used_quota": 16616751}, "success": true} quota is what's left; used_quota is what's been burned. Both are in quota units, not cents, not dollars. Two gotchas, both of which cost me a round trip: - The New-Api-User header is not optional. Without it the request fails in a way that looks like a bad token, so you go and re-paste the token for no reason. - You need the unit ratio. new-api and one-api default to 500,000 units per US dollar, but it's configurable per deployment, so it is not something to hardcode a second time. I didn't have to look the ratio up, though. The tell was in the numbers: quota + used_quota came to 162,500,000, and the console's own page showed a tidy $325.00 total. Round totals don't happen by accident. 162,500,000 / 325 = 500,000. So the honest reading was: $291.77 left, $33.23 spent, $325.00 total. (The total is what pinned the ratio down; the pane itself no longer carries it — more at the end.) The two accountings do not reconcile | Source | Spent | | --- | --- | | /v1/dashboard/billing/usage | $30.04 | | Console (used_quota) | $33.23 | Neither is a rounding error. If you average them you get a number that is true in no system. The fix is not arithmetic — it's to decide which source is authoritative and to label every figure with where it came from, so two accountings can never be silently blended. That's a discriminated union and a null: export type QuotaOrigin = 'console' | 'billing' export type QuotaBudget = { at: number origin: QuotaOrigin balanceUsd: number | null // console only spentUsd: number | null // billing only budgetUsd: number // ... } And the merge function only carries figures across from a previous snapshot of the same origin: const merged = (was: QuotaBudget | null, now: QuotaBudget): QuotaBudget => { const same = was !== null && was.origin === now.origin ? was : null return { origin: now.origin, balanceUsd: now.balanceUsd ?? same?.balanceUsd ?? null, spentUsd: now.spentUsd ?? same?.spentUsd ?? null, // ... } } The parsing is deliberately strict about what counts as an answer: const balanceOf = (body: unknown, quotaPerUnit: number) => { if (typeof body !== 'object' || body === null) return null const data = (body as Record<string, unknown>).data if (typeof data !== 'object' || data === null) return null const { quota } = data as Record<string, unknown> if (typeof quota !== 'number' || !Number.isFinite(quota) || quota < 0) return null return { balanceUsd: quota / quotaPerUnit } } Anything that isn't a finite, non-negative number returns null, and null renders as "no data" — not as zero, and not as last week's number dressed up as this week's. The console is now the primary source, and the billing API survives only as a fallback for when the console token isn't configured, because it works with the session token that's always present. The percentage is the fallback's alone — a share of a limit that the same line spells out — while the console's line is one number with no denominator to divide by: const budgetPercent = (shown: QuotaBudget) => shown.spentUsd === null || shown.budgetUsd <= 0 ? 0 : Math.max(0, Math.min(100, (shown.spentUsd / shown.budgetUsd) * 100)) The test that keeps it honest The most useful test in the suite is the one that asserts a request was not made: test('balance comes from the console and the billing API is never asked', async ($, on) => { const asked: string[] = [] on('http.fetch', (_$, e) => { asked.push(e.url) if (e.url.includes('/api/user/self')) return { value: SELF } if (e.url.includes('/api/log/self?p=1')) return { value: logPage(ones(1), 1) } return { value: { status: 404, ok: false, headers: {}, text: '' } } }) // ... expect(await ui.find({ text: /^balance \$291\.77$/ })).toBeDefined() expect(asked.some(url => url.includes('/v1/dashboard/billing/usage'))).toBe(false) }) Plus one for a configured unit ratio, and one where the console answers 500 and the pane is required to show the previous console balance, marked stale, with the reason: balance $291.77 · 5 min ago · response 500 Stale-and-labelled beats fresh-and-fabricated. Both assertions are anchored to the whole line, so a second dollar figure reappearing next to the balance fails the suite rather than sneaking back in. What I'd do differently - Never ship a plausible default for a measurement. 200 as a "budget" was the actual bug. A default that looks like data will be read as data. If the value isn't known, the UI should say so. - Make the unit ratio config, not a second constant. The ratio is a property of the deployment, and if it's configurable on the server side, it will eventually be configured. - Give "unknown" its own state. Empty, zero, and stale are three different things. Collapsing them is how a panel ends up confidently wrong. - Only send the session token to the host it was configured for. This pane reads an env var that also carries the session credential; it checks that the request's host matches the configured provider base URL before attaching it, and a test pins that behaviour. A panel is a nice place to accidentally exfiltrate a token from. The pane now reads $291.77 left, which is what the provider's own console says. It stopped being a guess. The console's total went with it, and so did the bar showing what share of the top-up was gone. Once the remaining balance is the number you act on, those were two more figures answering a question nobody asked — and the bar's percentage had no denominator left on screen to mean anything. Community wisdom Prior art that shaped how I thought about this, from the DEV archive: - Monitoring API credit usage before an automation runs out — messora. Same failure mode: a scraper that is perfectly healthy and quietly producing nothing because the balance hit zero. - Three Ways to Monitor Prepaid API Balances (Excel, Python + Cron, Power Automate) — saint_vandora. Useful on where the check belongs in a pipeline rather than in a UI. - Hard caps on autonomous agent API spend — infracore. The harder question this pane only reports on: enforcing a ceiling instead of watching one.

  5. Cursor、Claude Code、自建 Bot,工具越用越多,Key 和渠道也越配越乱。 New API 把模型入口收拢,协议转换、渠道调度、额度管理一起处理。 如果你也在给每个工具单独配 API,可以看看这个开源项目,少维护几套配置。 QuantumNous/new-api #NewAPI #AI编程

    3 likes · 66 views
  6. 【全网最全】0基础新手自建AI中转站完整教程:项目选择、VPS部署、上游接入、模型定价、支付网关到Codex实测|红孩儿Redman ✦视频教程▶youtu.be ✦完整文字教程▶redman.blog ✦New-api官方仓库▶QuantumNous/new-api ✦VPS选购攻略▶ redman.blog ✦中转站上游资源▶codex3721.com ✦Zpay个人支付网关▶i.redman3721.com ✦服务器ssh连接工具下载▶hostbuf.com ✦CN2GIA线路购买▶i.redman3721.com (视频同款) ▶AI新手攻略 【GPT&Codex充值攻略】youtu.be 【AI学习资源合集】i.redman3721.com 【AI交流群】redman.blog 【6种AI赚钱方法】youtu.be 【美区APPLE ID注册】youtu.be 说明: 很多人问我:既然平时就在用 AI 中转站,能不能自己搭一个,把不同平台的模型接进来,用自己的地址和 API Key 统一调用?如果以后想开放给其他人使用,分组、定价和收款又该怎么设置? 这次我把自己的搭建流程整理成一篇完整教程。我会先准备 VPS 和 Docker,把 New API 跑起来,再接入上游、配置模型价格,最后打通支付和客户端调用。只想自用,可以跳过支付部分;打算对外运营,就需要继续处理用户、账单、维护和服务支持。 我希望你最终能独立跑通这条链路:**客户端 → 自己的 New API → 获得授权的上游模型服务。软件部署只是其中一环,能正常调用、价格算得清楚、发生错误时知道查哪里,才算真正上手。 ▶AI子频道(新):i.redman3721.com ▶跨境子频道(新):i.redman3721.com 免责声明:本文仅用于正常订阅、学习和稳定使用 AI 工具,不建议用于批量注册、多人拼车、高频自动化调用或违反平台条款的行为。所有工具和服务请根据自身情况自行判断风险。 ⛓ 标签▶️#NewAPI #AI中转站 #自建中转站 #API网关 #Docker部署 #VPS #模型定价 #ZPAY #Codex #AI教程 #红孩儿Redman 我的频道: YouTube:youtube.com Redman博客:redman.blog Redman网赚导航站:redman3721.com 推特(X):x.com TG资源发布群:t.me TG万人交流群:t.me 注意:觉得有帮助的话可以订阅我的YOUTUBE频道、每周更新最前沿的AIGC资讯、最赚钱的web3套利项目、最硬核的网络技术!不卖课、主打交个朋友。的web3套利项目、最硬核的网络技术!不卖课、主打交个朋友。

    1 like · 197 views
  7. @luispaterx New API在2023年就有转换功能,这次只是拆成独立包。AGPL 同样是开源。把早已有的能力拆出来供大家复用,不正是在解决重复造轮子的问题吗? github.com/QuantumNous/new-api/commit/796760222c4…

    1 like · 149 views
  8. 可能很多人还不知道,New API 的格式转换已拆成一个独立的 Go 包 RelayKit,支持 OpenAI Chat/Responses、Claude、Gemini 的转换,AstrLink 用的也是这套转换器。 我们想为社区多做些基础建设,让大家少重复造轮子,多花时间做自己的产品。 github.com/QuantumNous/new-api/tree/main/relaykit

    145 likes · 11 reposts · 7,376 views

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

6
PackageVersionDownloads · 30dTrend · 30d
———
———
———
———
———
———

README badges

Embed a badge in your README or website.

Live mentions · last 30 days
QuantumNous/new-api mentions in the last 30 days