API 速查:请求、响应与报错
从快速起步到场景实战,你一直在跟同一个东西打交道:TypeSafe API 的 /v1/systemone 端点。这页把它单独抽出来压成一张速查表——请求字段、题型答案、请求头、请求规则、状态码,全部一表可查。写代码时开着这页,比翻官方 API 文档快。
学完你能做什么
- 说出 TypeSafe API 的两个端点、认证方式、请求体四个字段(model / state / questions / assets)
- 按题型查到每种答案的确切返回字段(Choice / Score / Noul / Box)
- 按状态码表定位报错:
400到529各自意味着什么、该改哪里 - 知道什么时候要加
TypeSafe-Danger-Zone-*请求头、什么时候该自己写重试 - 用 SDK 的等价方法对照表在 Python / JavaScript 里完成同样的调用
你现在的困境
- 写代码时每次都要翻回快速起步那课抄请求结构,没有一页能直接查
- 报错只知道一个状态码数字,不知道是请求体写坏了还是 Key 错了
- curl 直连和 SDK 两套写法在脑子里打架,字段名对不上
什么时候用这一招
当你需要:
- 一页放在手边,随写随查 TypeSafe API 的字段与状态码
- 排错时快速判断「这个 4xx 是我的问题还是服务的问题」
而且不想:
- 每次都去翻官方 API 参考的长文档
- 在多个教程页之间跳来跳去找同一个字段说明
🎒 开始前的准备
- 已跑通过第一个请求:安装 Python SDK 并发出第一个请求(或 curl 直连)
- API Key 在环境变量
TYPESAFE_API_KEY里 - 装不上跑不通的话,先去 起步排错——这页只做速查,不做逐步排错
核心思路:一个端点,一切从请求结构出发
Jev 系列模型全部由同一个端点服务:POST https://api.typesafe.ai/v1/systemone。请求里的 model 字段决定用哪个模型处理——不存在「每个模型一个 URL」这回事。
认证只认一个头:
POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer <你的API Key>
Content-Type: application/json配一个「查有哪些模型可用」的辅助端点:
curl https://api.typesafe.ai/v1/models \
-H "Authorization: Bearer $TYPESAFE_API_KEY"你应该看到:一个 models 数组,每项含 name、description、release_date(如 jev-latest、General-purpose system one model.、2026-09-15 这样的示例值)。拿到的 name 直接填进请求的 model 字段。
请求体长什么样?官方快速开始的工单示例(curl 直连版,节选两题,需要 curl 7.76+,--fail-with-body 让报错时也打印响应体):
curl --fail-with-body --silent --show-error \
https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"state": "Our API integration started returning 500 errors...",
"model": "jev-latest",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this",
"criteria": {
"billing": "Payment or subscription issues",
"technical": "Bugs or integration problems",
"sales": "Pricing or account questions"
}
},
"is_urgent": {
"type": "noul",
"instructions": "The message conveys urgency or time-sensitivity"
}
}
}
JSON整个 API 就这一个形状。下面逐块拆开速查。
请求字段全表
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
model | ✅ | 字符串 | 模型名或别名;可用名字由 GET /v1/models 返回。如 jev-latest、jev-preview |
state | ✅ | 字符串 / JSON 对象 / 文本数组 | 所有问题共同评估的内容。三种形态详见 State 状态 |
questions | ✅ | 对象(至少 1 题) | 键是你自取的问题 ID,值是问题对象;问题数量无上限,限制只在上下文长度 |
assets | ❌ | 对象(至少 1 项) | 图像资源,键为占位符(官方建议每图一个 UUID);用图像时必须配 TypeSafe-Danger-Zone-Images: true 头 |
问题对象的字段:
| 字段 | 必填 | 说明 |
|---|---|---|
| ID(对象的键) | ✅ | 你自取,用来在响应里对号取答案;不会发给模型——完整问题必须写在 instructions 里,哪怕 ID 看起来不言自明 |
type | ✅ | choice / score / noul / box 四选一 |
instructions | schema 里四种题型都可省 | 完整的问题;可以是字符串、JSON 对象或数组(问题与它引用的数据可以分开)。ID 不发给模型,所以实际每题都该写它 |
criteria | Choice、Score 必填 | Choice:选项 map(1–255 个);Score:有序等级列表(1–10 项);Noul:可选的 true/false 是非定义 |
在 instructions 里引用 state 的字段,用反引号包住点/下标路径,如 `ticket.messages[0].text`——详见 State 状态 课。
题型与答案字段全表
一个请求里可以混任意题型;所有题对同一 state 并行、独立评估(这种用法的极限示例见 并行提问)。
| 题型 | type 值 | criteria 形态 | 答案字段 |
|---|---|---|---|
| Choice | choice | 选项 map,1–255 个 | choice(选中项的名字,即概率最高项)、confidence、probabilities(每个选项一个概率,总和非严格等于 1) |
| Score | score | 有序等级列表,1–10 项 | score(概率加权期望值,可落在两级之间,如 0.67 / 1.7)、confidence、legend(等级到分值的映射)、probabilities |
| Noul | noul | 可选:true/false 的定义 | noul(0–1 的真/是概率;接近 0.5 = 不确定;无 confidence 字段) |
| Box | box | 无 | box(top/bottom/left/right 四条边,按图片高/宽的比例 0–1)、confidence(可为 null)。需要图像 + 开启图像头 |
题型怎么选、每种的完整用法:
- Choice 选择题 · Score 打分题 · Noul 是非题 · Box 与图像
- confidence 怎么算、怎么设阈值:Confidence 置信度
请求头全表
| 请求头 | 何时用 | 说明 |
|---|---|---|
Authorization: Bearer <key> | 每个请求 | 缺失或无效 → 401 |
Content-Type: application/json | 文本请求 | 图像走 multipart/form-data:JSON 作第一部分(名 request),每张图一个独立部分 |
Content-Encoding: gzip 或 x-gzip / zstd | 压缩大请求体 | 只能一层;zstd 的 window ≤ 8 MiB;不支持或多层 → 415,坏压缩体 → 400 |
TypeSafe-Danger-Zone-Images: true | 请求含图像或 Box 题时 | 每个含图请求都要带;漏带 → 400 |
TypeSafe-Danger-Zone-Long-Context: true | 长文本塞不进默认上下文时 | per-request 和 per-question 上下文都变 262k;价格不变,但更慢且更不准,只给需要的请求用 |
默认上下文限制(Jev 1.14 与 1.13 相同):每请求 64k / 每题 32k token;问题数量本身无上限。价格与模型版本速查见 模型与价格。
请求规则与压缩
官方 errors 文档给每个请求定了四条硬规则:
| 规则 | 限制 | 违规状态码 |
|---|---|---|
| 请求体大小 | ≤ 32 MiB(不含 header) | 413(超限时压缩前后都算) |
| 编码 | UTF-8 JSON,无 BOM | 400 |
| 嵌套 | state / instructions / criteria 各自 ≤ 64 层对象与数组,更深的先拍平 | 400 |
| 数字 | 只接受有限数:NaN、Infinity、1e400 这类都会被拒;大数和 ID 用字符串传 | 400 |
压缩只多两条:一层为限、zstd window ≤ 8 MiB。
响应字段全表
{
"model": "jev-1.14.0",
"answers": {
"department": {
"type": "choice",
"choice": "technical",
"confidence": 1.0,
"probabilities": { "technical": 1.0, "billing": 0.0, "sales": 0.0 }
},
"frustration": {
"type": "score",
"score": 0.67,
"confidence": 0.5,
"legend": { "0": "Calm…", "1": "Frustrated…", "2": "Very angry…" },
"probabilities": { "0": 0.33, "1": 0.67, "2": 0.0 }
},
"is_urgent": { "type": "noul", "noul": 0.99 }
},
"usage": { "input_tokens": 428, "output_tokens": 73 }
}(示例值,会随版本变化;完整示例见 第一个请求 课。)
| 字段 | 位置 | 说明 |
|---|---|---|
model | 顶层 | 实际作答的模型名;可能与请求里的别名不同(如请求 jev-latest、返回具体版本号) |
answers | 顶层 | 按你起的问题 ID 逐个对号;每题的 type 与其问题的 type 一致 |
usage.input_tokens | 顶层 | 本次计费的输入 token 数(计费只算输入) |
usage.output_tokens | 顶层 | 输出 token 数,目前免费 |
状态码全表
| 状态码 | 含义 | 你该做什么 |
|---|---|---|
200 | 成功 | 按 ID 取答案 |
400 Bad Request | 违反请求规则(非法 UTF-8、嵌套超 64 层、非有限数、坏压缩体、漏图像头);max_tokens_exceeded = 超上下文长度 | 对照「请求规则」表改请求体;超上下文就瘦身 state 或开长上下文头 |
401 Unauthorized | Key 缺失或无效 | 检查 Authorization 头;SDK 用户检查 TYPESAFE_API_KEY(见下方踩坑提醒) |
413 Payload Too Large | 请求体超 32 MiB | 减少 state;压缩救不了 413——32 MiB 对压缩前后都生效 |
415 Unsupported Media Type | Content-Encoding 不支持或压缩多层 | 只用 gzip / x-gzip / zstd 之一,一层 |
422 Unprocessable Entity | 请求体校验失败:缺必填字段、问题格式错误等 | 看 body 的 detail 数组定位 |
429 Too Many Requests | 超速率限制(按组织计:tokens/s + requests/s,控制台 console.typesafe.ai/rate-limits 可查) | 指数退避重试;SDK 默认自动处理 |
529 Overloaded | TypeSafe 临时过载 | 同 429:退避后重试 |
422 的 body 会精确到字段:
{
"detail": [
{ "loc": ["body", "state"], "msg": "Field required", "type": "missing" }
]
}按 loc 找到出错的字段,msg 告诉你缺了什么。
错误处理与重试
官方规则一句话:收到 429 或 529,用指数退避重试(逐次拉长等待),不要立刻原样重发;响应带 retry-after 头时遵循它。
用 SDK 的你:Python / JavaScript SDK 默认带重试策略,自动处理 429,无需额外代码。需要自定义时(Python):
from typesafe_sdk import RetryPolicy, TypeSafeClient
client = TypeSafeClient(retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0))Python SDK 捕获 API 错误的标准写法:
from typesafe_sdk import TypeSafeAPIError
try:
client.system_one(state, questions)
except TypeSafeAPIError as error:
print(error.status, error.request_id)error.status 是状态码,error.request_id 是请求标识——报给官方支持时带上它。
直连 API 的你:重试要自己写。curl 的 --fail-with-body 至少保证报错时能看到响应体。
Python 两套客户端速记
TypeSafe API 在两套 Python 客户端上方法同名:TypeSafeClient(同步)与 AsyncTypeSafeClient(异步),都是 system_one()。SDK 读的环境变量:
| 变量 | 作用 | 默认 |
|---|---|---|
TYPESAFE_API_KEY | API Key(必填) | — |
TYPESAFE_BASE_URL | API 根 URL | https://api.typesafe.ai |
TYPESAFE_DEFAULT_MODEL | 默认模型 | jev-latest |
TYPESAFE_LOG_LEVEL | typesafe_sdk 日志级别,import 时生效一次 | 未设置 |
TypeScript 答案速记
JS/TS SDK(@typesafe-ai/sdk)里答案按 ID 直接取:response.answers.department.choice,且类型从问题定义推断(如 "billing" | "technical" | "sales")。
踩坑提醒
❌ 请求 jev-latest,响应里 model 不是它
不是出错——响应里的 model 是实际作答的模型名,可能与请求中的别名不同(官方 API 规范明确说明了这一点)。别名当前指向见 模型与价格。
❌ Key 里混进空格或换行
直连时这类 Key 一直 401。SDK 会剥掉 Key 首尾空白(含从文件读出来的换行),但内部空格、控制字符、非 ASCII 会直接拒绝(客户端创建时就报错,到不了 401);显式传空 Key 不会回落到环境变量。从控制台复制 Key 时别多选一个空格。
❌ 拿 422 的状态码猜哪里错了
别猜,读 body:detail 数组的 loc 就是字段路径(如 ["body", "questions", "urgency", "criteria"]),msg 是原因。
❌ Noul 答案里找不到 confidence
不是丢了——Noul 天然没有 confidence 字段。要统一门槛可自算 |2p − 1|,官方建议起点:yes ≥ 0.7、no ≤ 0.3(见 Noul 是非题)。
❌ 直连 API 高频调用被 429 刷屏
速率限制按组织计(tokens/s + requests/s)。SDK 默认退避重试;直连就自己写指数退避。更高额度走官方申请表单(support.typesafe.ai)。
本课小结
✅ 一个端点 POST /v1/systemone,认证一个头,请求体四个字段(model / state / questions / assets)。
✅ 四种题型四种答案:Choice 出选择 + 概率 + confidence,Score 出期望分 + legend,Noul 只出 0–1 概率,Box 出四边比例。
✅ 状态码一条龙:400 规则 / 401 Key / 413 体积 / 415 压缩 / 422 校验(看 body)/ 429 529 退避重试。
✅ 两个 Danger Zone 头按需加:图像用 TypeSafe-Danger-Zone-Images,长上下文用 TypeSafe-Danger-Zone-Long-Context。
关键配置字段回顾:
| 字段 | 推荐值 | 说明 |
|---|---|---|
model | jev-latest | 别名,当前指向 Jev 1.14;要锁版本就写 jev-1.14.0 |
state | 字符串 / JSON 对象 / 文本数组 | 三种形态任选 |
questions | {ID: {type, instructions, criteria}} | ID 不发给模型;完整问题写 instructions |
| 上下文 | 64k / 请求 · 32k / 题 | 加长上下文头后都是 262k |
| 请求体 | UTF-8 JSON ≤ 32 MiB · 嵌套 ≤ 64 层 · 数字必须有限 | 压缩可一层 gzip / zstd |
下一课预告
API 会调了,账也要算明白:模型与价格:版本、上下文限制、费率。
你会学到:
jev-1.14.0与jev-1.13.0的版本时间线与别名指向- $42/Btok 的计费方式:为什么只算输入 token
- 上下文限制的细节与长上下文的代价
- 速率限制怎么查、怎么申请提额
相关教程
- 装不上跑不通怎么办:起步排错——按报错逐条排查的完整版
- 安装 Python SDK 并发出第一个请求——请求结构的逐步讲解
- 安装备用方式:uv、npm 与 curl 直连 API——curl 直连的完整走法