“目录里有这个型号,怎么还是调不通?”碰到这种情况,先别急着换 Key。目录、当前账号权限和客户端实际请求的接口,是三件不同的事。只盯着首页目录改配置,很可能一直改不到出错的那一层。
先说明本文的范围:下面的程序是本地模拟网关,只用来演示检查顺序,没有连接任何真实中转站,也没有测某个平台的成功率、速度或价格。示例里故意让目录列出两个型号,却只允许调用其中一个。你可以先在本机跑通,再把同样的检查顺序用到自己的接入环境。
把下面的代码保存为 model-access-demo.mjs,用 Node.js 18 或更新版本运行。它只监听本机随机端口,不需要 API Key,也不会向外网发请求。
import { createServer } from 'node:http';
const server = createServer(async (req, res) => {
res.setHeader('content-type', 'application/json; charset=utf-8');
if (req.method === 'GET' && req.url === '/v1/models') {
res.end(JSON.stringify({
data: [{ id: 'demo-chat' }, { id: 'demo-restricted' }]
}));
return;
}
if (req.method === 'POST' && req.url === '/v1/chat/completions') {
let body = '';
for await (const chunk of req) body += chunk;
const { model } = JSON.parse(body);
if (model === 'demo-restricted') {
res.writeHead(403);
res.end(JSON.stringify({ error: { message: 'model unavailable to this key' } }));
return;
}
res.end(JSON.stringify({
choices: [{ message: { content: 'ok' }, finish_reason: 'stop' }]
}));
return;
}
res.writeHead(404);
res.end(JSON.stringify({ error: { message: 'unknown path' } }));
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const base = `http://127.0.0.1:${server.address().port}`;
try {
const listed = await fetch(`${base}/v1/models`).then(r => r.json());
console.log('目录:', listed.data.map(x => x.id).join(', '));
for (const model of listed.data.map(x => x.id)) {
const response = await fetch(`${base}/v1/chat/completions`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ model, messages: [{ role: 'user', content: 'ping' }] })
});
console.log(model, 'HTTP', response.status);
}
} finally {
server.close();
}运行后会看到两个型号都在目录里,但第二个请求返回 403。这个结果是程序刻意设置的,不代表任何真实平台的权限状态。它说明了一个很具体的边界:目录回答“有哪些候选型号”,实际请求才回答“当前身份能不能在这个接口调用它”。
真实服务的验证顺序可以沿用这个小程序,但请求路径和字段一定要按该平台的当前文档改。第一步记录公开目录或控制台显示的模型 ID;第二步确认客户端实际发出的接口路径、鉴权方式和模型 ID;第三步用同一个 Key 做最小请求。客户端若用的是 Responses 或其他协议,就测试它真正使用的接口,不能拿 Chat Completions 的结果替代。
看到 401,先查 Key 是否被正确传入;403,查账号或型号权限;404,同时查模型 ID 和接口路径;429,查余额、周期额度、并发与限速。它们是排查方向,不是所有平台统一的错误定义,最终仍以该平台的文档与脱敏后的响应为准。不要为查一个错误,把 Key、业务提示词和完整请求头贴到论坛。
即便最小请求返回 200,也还没到“可以交给日常任务”的程度。代码客户端要另外测工具调用和文件改动;流式输出要确认收到了当前协议要求的结束事件;结构化结果要通过解析和字段校验。把这三项分别记录,避免把一段普通聊天回复误记为 Claude Code 或 Codex 的完整兼容。
如果候选平台里有 NexoToken,也按这个顺序检查:先把目录中的目标型号记下,再用自己的账号和目标客户端做最小请求与完整任务。它有按量和会员两种入口,但选哪种计费方式应放在“型号与接口已通过验收”之后,按实际输入、输出、缓存和重试用量计算。目录里的名称不是授权证明,本文的本地模拟结果也不是对 NexoToken 可用率的测量。
最省事的记录方式是一行一型号:目录是否出现、当前账号是否可选、接口路径、最小请求状态、工具任务结果、失败时间和脱敏后的错误类别。下次同一型号突然不可用时,拿这张表先定位哪一层变了,比重新搜索“哪个中转站最好用”更快。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。