APICheck 交流群 · 欢迎加入讨论
QQ 群二维码
群号: 1058136854

使用 QQ 扫一扫上方二维码即可加群

← 返回文章列表

我为什么做了API检测APICheck — 来龙去脉

2026-07-27APICheck 团队
APICheckAI中转站模型检测产品故事tRPCSSG

这篇不聊融资、不画饼,就是讲一个我自己遇到的小痛点,以及怎么顺手做成了一个能用的工具。源码没开源,但架构思路和工程上的取舍都可以聊聊。

一、背景:中转站这行,水有点浑

从 2023 年开始,AI API 中转/代理服务一下子冒出来一大堆。搜一下能找到几十家,个个都喊着"官方同源""低价直连""无限额度"。

但真掏了钱,问题就来了:

  • 模型到底是不是真的? 嘴上说是 gpt-4o,返回的到底是 OpenAI 原版,还是拿个小模型套壳糊弄人?
  • Key 填进去能不能用? 端点通不通、要不要先充值才能测试、报错信息是不是故意藏着掖着?
  • 延迟和稳定性怎么样? 宣传页写着"20ms 直连",实际跑一次推理要 8 秒,连流式都不支持。
  • 最关键的是:没有一个中立的第三方,能在你掏钱之前先帮你验验货。

社区里也不是没人讨论,但基本都是零散的吐槽、过期的跑分截图,或者让你先把 Key 托管给某个监控平台——这本身又是一次信任让步。

所以我就动手做了 APICheck在把钱交给任何一家中转站之前,先自己亲手验证一下,它到底能不能用、模型是不是真的。

二、为啥不直接用现成的?

我一开始也找了一圈现成方案,最后发现都不太对味:

  1. 长期监控类的 SaaS:要注册、要托管你的 Key、要长期跑任务。我就想"点一下,马上知道现在这个端点行不行",犯不着把密钥交出去。
  2. 各种跑分/排行榜:数据来源不透明,很多看起来就是宣发稿,你根本不知道它测没测、怎么测的。
  3. 自己写脚本测:能写,但每次换端点都要改参数、对着 JSON 看半天,非技术的同事根本用不了。

最后给自己定了三条原则,后面所有技术选型都是围着这三条转的:

  • 不托管密钥:检测在你授权下,针对你提供的端点发一次真实请求,结束后不留存任何业务数据。
  • 单次就能验证:不要什么长期大盘,就要"此刻这一发"的结果,点完直接看。
  • 老老实实说清楚边界:排行是人工维护的参考,不是实时监控;检测是快照,不是承诺。

说起来有意思,第三条反而成了这个项目最核心的东西。市面上的工具都在往满了吹,我反而觉得把"能做什么、不能做什么"写在第一屏更重要。

三、APICheck 到底是个啥

一句话:一个 AI API 中转站的单次检测平台,外加一份人工维护的服务商参考排行。

解决的就是接入前那一步验证的问题:

  • 这个 API 能不能用?Key 填进去会不会打水漂?
  • 号称的 gpt-4o / claude真模型还是套壳
  • 几十家中转站,哪家相对更稳、更透明

目前主要两块功能:

1. 单次 API 检测

把端点和 Key 粘贴进去,立刻发起一次真实请求,验证连通性和基本可用性,然后出一份可读的报告:端点状态、模型真实性、延迟、连通结果

2. 人工维护的服务商参考排行

我们结合公开信息、社区反馈和抽样检测,定期人工整理一份服务商榜单,覆盖稳定性、透明度、合规这些维度。就是个选型参考,不是什么"唯一真理"。

四、一次检测具体是怎么跑的

核心思路其实很朴素:用你给的端点,发一个我们专门设计的探针请求,然后看返回里都藏着什么信息。

下面是一段原理示意代码(不是生产环境的),主要是讲清楚思路,线上实现比这个复杂得多:

// 核心思路:发一次真实探针请求,做基础校验
async function probe(endpoint: string, apiKey: string, claimedModel: string) {
  const t0 = Date.now();
  const res = await fetch(`${endpoint}/v1/chat/completions`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`,
    },
    body: JSON.stringify({
      model: claimedModel,
      messages: [{ role: 'user', content: '用一句话解释量子纠缠,并给出一个只有真实 GPT-4 才会犯的典型错误示例。' }],
      stream: false,
    }),
  });
  const latency = Date.now() - t0;
  if (!res.ok) return { ok: false, status: res.status, latency };
  const data = await res.json();
  // 校验 1:协议兼容 —— 返回是不是标准 OpenAI 兼容的 choices[0].message.content
  const content = data?.choices?.[0]?.message?.content;
  // 校验 2:计费字段 —— usage.prompt_tokens / completion_tokens 齐不齐
  const hasUsage = !!data?.usage?.completion_tokens;
  // 校验 3:模型字段有没有被改(有些套壳会篡改 model 字段)
  const echoedModel = data?.model;
  return { ok: true, latency, hasUsage, echoedModel, contentLen: content?.length ?? 0 };
}

"模型真实性"不是什么玄学,就是几个可观测维度交叉验证出来的:

  • 协议一致性:返回符不符合 OpenAI / Anthropic 兼容的 schema?字段缺东少西往往就是二次封装的信号。
  • 探针 prompt:用只有特定模型才能稳定答对(或者稳定答错)的问题,看响应对不对得上这个模型的"风格边界"和知识边界。
  • 计费与延迟分布usage 字段合不合理、流式格式标不标准、首字延迟是不是离谱。
  • 异常指纹:套壳站常见的特征——模型字段被篡改、思考链格式乱、函数调用能力缺失之类的。

强调一下:这些判定都是"参考性"的,不是司法鉴定。我们从来不说自己能"100% 识别套壳",这既是科学上的诚实,也是不想误导用户。

五、关于数据口径和边界:做技术产品得有点诚实

这一节是我最想聊的——做减法有时候比做加法更需要勇气

很多同类产品首页都写着"实时排行榜""全网监控""权威认证"。我没这么干,原因很实在:

  • 单次检测结果只反映"检测那一刻"这个端点的表现。网络和供应商状态随时在变,说成长期承诺就是骗人。
  • 服务商排行是人工维护的,参考了公开资料、社区反馈和抽样检测。更新有周期,不可能等于实时状态。
  • 我们不对排行的绝对准确性或者任何商业决策后果做担保。它应该是个参考起点,不是唯一依据。

把边界写清楚,短期看像是"自曝其短",长期反而能建立信任:用户知道你哪里靠谱、哪里只是参考,用起来反而更放心。

六、技术选型:为啥选了这一套

公开的、不涉及敏感信息的技术概览如下:

选型原因
前端React + TypeScript + Vite(SSG)首屏快、利于 SEO;类型安全能减少线上问题
后端Node.js + tRPC前后端共享类型,省掉接口文档和联调的麻烦
数据库PostgreSQL稳定、schema 演进成熟(用 Drizzle ORM 管迁移)
网关 / 反代Nginx + Caddy静态托管 + HTTPS 终止,部署省事
部署Docker Compose一套配置本地跑通、服务器直接复刻

说几个具体的工程取舍:

  • 用 tRPC 不用 REST:检测报告、排行这类结构化数据,前后端共用 TS 类型,改一处编译期就能把不兼容的地方拦住。
  • 用 SSG 不用纯 CSR:官网大部分是静态内容(介绍、排行展示),预渲染后首屏直接出,对 SEO 和弱网环境都友好。
  • 优先轻量:没搞什么重型微服务,单体 Node 服务 + 网关足够支撑当前规模,复杂度可控。

出于安全和商业考虑,服务器地址、环境变量、密钥、内部架构和部署脚本就不公开了。上面这套是"思路级"的分享,照着搭一个同类工具问题不大。

七、最后说两句

做这个项目最大的收获其实不是多了个工具,而是验证了一件事:大家都在往满了承诺的时候,老老实实把边界说清楚,反而成了一种稀缺的竞争力。

做技术产品,尤其是 To B 类的工具,诚实其实是最高效的策略——用户知道你哪里能做到、哪里只是参考,反而敢放心用。后面有时间的话,打算再写一篇聊聊探针设计的具体细节,以及套壳站识别上踩过的一些坑。


查看 APICheck 排行榜 →