# 首次调用 LLM API

## 先确认路由契约

在 [API Key 页面](/api-keys) 获取具有目标模型权限的服务端密钥。不要把密钥写入浏览器代码、截图或 Git。运行示例前，在环境变量中设置 `API_KEY`。查询目录是只读操作；生成请求会产生用量。

```bash
curl --fail-with-body "https://newrouters.com/v1/models" \
  -H "Authorization: Bearer $API_KEY"
```

通过 `/v1/models` 查询准确的公开模型 ID、声明的协议与能力。该发现接口不列出支持的端点。本示例先选择 `protocol: "openai"` 的模型，再到其当前[模型指南](/zh/docs)确认支持 `POST /v1/chat/completions`。协议标签本身不能保证端点兼容，目录中可见也不代表当前密钥有调用权限；继续前核对账号访问配置。

## 发送最小请求

将下面代码保存为 `first-request.mjs`，把环境变量 `MODEL_ID` 设置为已核对的公开 ID。示例使用 Node.js 内置 fetch，仅发送一次请求，不自动重试。

```javascript
const { API_KEY, MODEL_ID } = process.env;
if (!API_KEY || !MODEL_ID) throw new Error('Set API_KEY and MODEL_ID');
const response = await fetch('https://newrouters.com/v1/chat/completions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: MODEL_ID,
    messages: [{ role: 'user', content: 'Explain HTTP in three short steps.' }],
    stream: false,
  }),
  signal: AbortSignal.timeout(60000),
});
if (!response.ok) throw new Error(`Request failed: HTTP ${response.status}`);
const result = await response.json();
console.log(result.choices?.[0]?.message?.content ?? 'No text content returned');
console.log({ finishReason: result.choices?.[0]?.finish_reason, usage: result.usage });
```

在服务端运行 `node first-request.mjs`。输出长度限制和采样参数并非跨模型通用；确认模型接受的字段后再添加限制。这里的超时只是客户端策略，不是服务端延迟承诺。

## HTTP 成功之后还要检查什么

检查 `finish_reason`，不要把截断结果当成完整回答。达到输出上限时，先缩短输入或重新评估输出预算。文本为空也可能意味着返回了其他类型的内容或拒绝回答；排查时保留原生响应，但不要记录密钥及敏感提示词。

LLM 使用所选协议的原生结果，不返回媒体任务的 `pending` 包装，也不应到 `/v1/tasks` 轮询。连接超时不等于生成已取消或不计费，重新提交前应检查用量。

接下来阅读[协议选择](/zh/docs/llm/protocols)、[错误与重试](/zh/docs/llm/errors-and-retries)或已有的 [GPT-6.1 Sol 指南](/zh/docs/models/gpt-6.1-sol)。模型文档提供接入参考，不承诺实时可用性。
