Anysite API 可能返回的每一种响应、每种状态的含义、计费规则、超时、分页和速率限制。
目标:正确处理 API 可能返回的每一种响应,并清楚哪些调用会消耗积分。
成功的数据调用响应体始终是 JSON 数组,即使端点返回的是单个实体 —— linkedin/user 返回的是包含
一个元素的列表。没有匹配结果的搜索是正常的 200,响应体为 []。
应从 x-result-count 响应头读取结果数量,而不是数组长度:如果 x-result-count 较大而响应体为空,
说明响应被截断了,而不是没有结果。
检查按以下顺序执行;第一个未通过的检查会返回其错误,且不计费:
422。401 / 403。404 / 529 / 403 / 400。401。429。以下状态来自 Anysite 的计费层,在到达端点之前返回。这些响应均不计费,响应体的结构是
{"detail": ...}:
{"detail": "Token expired"}
422 返回的是字段错误列表,429 返回一个对象,并附带一个值相同(单位:秒)的 X-Retry-After
响应头:
{"detail": {"message": "Rate limit exceeded: ...", "retry_after": 12}}
| 状态码 | detail |
该怎么做 |
|---|---|---|
422 |
缺少必需的请求头 | 发送 access-token 请求头。 |
422 |
Body should be a valid dict object |
请求体应为 JSON 对象,而不是数组或标量值。 |
401 |
Invalid token |
从「订阅与 API」页面重新复制密钥。参见身份验证。 |
401 |
Token does not exist |
密钥已被删除;请使用另一个密钥。 |
401 |
Token expired |
套餐已到期;请在「订阅与 API」页面续订。 |
401 |
Points limit exhausted, required at least N points |
购买更多积分或升级套餐。参见套餐与积分。 |
403 |
This token is restricted to MCP usage only and cannot be used for direct API access |
改用 MCP 服务器,或选择一个包含 REST API 的套餐。 |
403 |
This endpoint is disabled for your plan |
选择一个包含此端点的套餐。 |
400 |
Parameter 'count' exceeds the maximum allowed for your plan: N |
把 count 降到 N 或更低,或分页获取结果。 |
404 |
Endpoint was removed |
该端点已不存在;请在 API 参考中查找替代端点。 |
529 |
This endpoint is temporarily unavailable while we work on a fix. ... |
该端点已被我们临时关闭。重试无济于事;如果你依赖它,请从「支持」页面提交工单。 |
429 |
object, Rate limit exceeded: scope=..., limit=N requests <window>. ... |
等待 retry_after 秒。参见 Rate limits。 |
429 |
object, You've reached your <window> usage limit. ... |
等待窗口释放额度,或升级套餐。参见 Usage windows。 |
429 一定来自 Anysite 的速率限制器 —— 端点背后的数据源本身永远不会产生这个状态码。
通过检查之后,端点自身的状态码和响应体会原样返回给你。端点的错误响应体仍然是空的 JSON 数组
[];原因在 x-error 响应头中,该响应头只有在状态码为 400 或更高时才会出现:
HTTP/1.1 412
x-error: Failed to fetch URL. Website is not accessible
x-result-count: 0
[]
验证错误是例外:格式错误的请求体会被 422 拒绝,并返回一个指明具体字段的 detail 对象。
| 状态码 | 含义 |
|---|---|
200 |
成功。响应体是一个数组,可能为空。 |
209 |
查找了但没有结果,且本次查找没有产生费用 —— 一次免费的未命中。仅出现在 What is charged 中列出的端点上。 |
400 |
客户端在结果准备好之前断开了连接,或者 LinkedIn URN 格式有误,且验证未能捕获这种错误。 |
408 |
调用超时。参见 Timeouts。响应体中仍可能包含截止前已收集到的数据行。 |
412 |
API 的「未找到」:实体不存在、资料是私密的或被限制访问,或者(在 webparser/* 上)目标主机不可达。 |
415 |
webparser/* 指向的是 PDF、Office 文档、图片、压缩包或其他非页面文件。 |
422 |
模式验证失败(detail 中指明字段)、请求体无效,或响应过大而无法返回。 |
500 |
数据源无法访问,或对它的重试已耗尽。 |
529 |
该数据源目前的抓取能力全部繁忙。 |
API 参考中每个端点只列出它不那么显而易见的状态码 —— 例如 linkedin/user
会返回 412,而不是你可能预期的 404。列表中没出现的状态码并非不可能出现;上面的含义始终适用。
被限制访问的 LinkedIn 资料,只要仍处于限制状态就会一直返回 412 —— 用同一个别名重试不会改变结果。
简而言之:
200 会计费,包括返回空数组的搜索。你支付的是查找本身的费用,而不是结果条数。412 —— 「未找到」的回答 —— 会计费。查找的工作已经完成。408 超时会计费,且响应体中仍可能包含部分数据行。209 不计费。它只出现在未命中不会产生成本的端点上:linkedin/search/sql/users、
linkedin/search/sql/companies、crunchbase/db/search、linkedin/user/email、
linkedin/user/find_email_by_url、person/by_email、person/by_phone、phone/find、
email/find、company/resolve。在这些端点上,如果付费数据供应商已经给出过未命中的答案,结果
仍然是 412 并计费 —— 你无法预先知道会得到哪一种,所以要读取 x-credits-charged。400、415、422、500、529 —— 仅当响应仍然带回了结果时才计费。带回
数据行的失败是一次付费调用,同样的失败但响应体为空则免费。响应头 x-result-count 会告诉你属于
哪一种。{"error": "Internal server error"}。| Endpoint response | Charged |
|---|---|
低于 400 的任意状态码(209 除外) |
计费 |
209 |
不计费 |
408、412 |
计费 |
其他任意 4xx / 5xx |
仅当响应报告了至少一条结果时计费 |
上述检查产生的任何错误,或端点不可达时返回的 500「Internal server error」 |
不计费 |
调用的价格取决于端点和你的套餐,并且在许多端点上会随结果数量增长:每开始一个结果区块就按基础价格
计费一次,因此按每 10 条结果计价的端点,返回 11 条时收费两次,返回 21 条时收费三次。这两个数字都
按端点发布在 API 参考中:x-price 是基础价格,x-increase-every 是区块大小(没有该
字段表示每次调用一口价)。只请求你真正需要的 count —— count 越大,可能越贵。每次调用的精确
金额在 x-credits-charged 响应头中 —— 0 表示本次调用免费 —— 以及「订阅与 API」页面的请求日志里。
积分优先从套餐积分中扣除,然后才扣除已购买积分。只要余额能覆盖基础价格,调用就会被允许;如果 最终价格更高(例如返回结果更多),余额可能变为负数,负的部分会从你之后追加的积分中扣除。
| 响应头 | 含义 |
|---|---|
x-credits-charged |
本次调用花费的积分。0 表示免费。 |
x-token-points |
余额中剩余的积分。 |
x-result-count |
响应中的结果行数。如果比你收到的数组长度大 → 说明响应被截断了。 |
x-error |
调用失败的原因。仅当状态码为 400 或更高时出现。 |
x-warning |
请求虽然成功,但存在一些问题 —— 参见 Ignored parameters。 |
x-execution-time |
端点处理耗时,单位为秒。 |
x-request-id |
本次调用的 id。在支持工单中引用它。你也可以自己指定它,但必须是合法的 UUID,否则请求会被 422 拒绝。 |
X-Total-Available-Results |
在数据源提供可用总数的端点上,总共可获取的结果数量。 |
请求体中的 timeout 字段默认值为 300 秒,可接受 20-1500 之间的值。
它是停滞预算,而不是总时长:衡量的是调用在多长时间内没有产生新结果。每收到一条新数据,
截止时间就会向后推移,直到 1500 秒的硬上限为止。因此,一次持续有进展的调用完全可能比它的 timeout
运行得更久,而一旦停滞的调用在 timeout 时间内没有进展,就会被 408 中断。
由于这个上限的存在,对于可能长时间运行的端点,请把你的 HTTP 客户端自身的超时设置为约 1600 秒。如果客户端在 30 秒或 60 秒就放弃,会中断那些其实仍在正常工作的调用。
curl --max-time 1600 -X POST "https://api.anysite.io/api/linkedin/search/users" \
-H "access-token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"keywords": "cto", "count": 100, "timeout": 600}'
ACTION FOR THE HUMAN: copy your API key at https://app.anysite.io/billing — an agent cannot obtain it.
请求体中无法识别的字段会被忽略,而不是拒绝。 因此拼错的过滤条件的表现和没有过滤条件完全一样:
你会得到 200 和未过滤的结果,并为此付费。每个被忽略的字段都会列在 x-warning 响应头中(在 MCP
结果中则是 warnings 字段),所以当某个过滤条件看起来没有生效时,检查一下这个响应头。
在每个可能返回多条结果的端点上,count 都是必填的,而且它是上限而不是承诺:请求的数量超过实际
存在的数量时,会返回 200 和更少的结果行。
REST API 上没有游标可以跟随。每次调用时把 offset 增加 count(或者对接受 page 参数的端点,
递增 page)。不推进就重复同样的调用会返回相同的结果 —— 这通常就是「API 一直给我重复数据」的原因。
429:等待 retry_after 秒(同样的值也在 X-Retry-After 中)后再重试。529:该数据源的抓取能力正忙。请稍后重试,并把调用分散开,而不是并行发起。500:数据源不可达,或已放弃处理。数据源短暂不可用是正常现象;等待一段时间后重试,如果某个数据源
持续故障而其他数据源正常,请从「支持」页面提交工单。x-credits-charged。408:本次调用会计费。重试会再次计费 —— 应缩小请求范围,而不是直接重试。412:重试会得到相同的答案,并再次计费。应先用搜索端点找到该实体。401、403、400、404、422:重试同样的请求只会得到相同的错误。Anysite 与数据源之间的传输失败已经替你自动重试过了 —— 最多重试三次,退避间隔分别为 1 秒、5 秒 和 10 秒 —— 你看到错误之前这些重试已经发生。这里没有幂等键:如果状态属于计费状态,你自己发起的重试 会再次计费。
某个端点即使已经被关闭,仍可能出现在 API 参考中。列出的端点返回 404
Endpoint was removed 或 529,就是这种情况,而不是你这边的问题。如果你依赖它,请从「支持」页面
提交工单。
套餐以及部分端点会在滚动窗口(10 秒、1 分钟、1 小时、1 天或 30 天)内限制请求数量。任何通过了之前
检查的请求都会计入这些限制,无论最终是否计费 —— 包括免费的 209。达到限制后,API 会返回 429,
retry_after 等于窗口中最早那次请求过期所需的秒数。
部分套餐(包括 MCP 套餐)还会在两个滚动窗口内限制消耗的积分:5 小时和每周。部分套餐还会 加上单独的 LinkedIn 5 小时和每周窗口,只统计 LinkedIn 端点。用量是窗口内被计费积分的总和,所以随着 较早的调用移出窗口,额度会逐渐释放。
窗口用满后,API 会返回 429,retry_after 等于整个窗口的长度 —— 这是最长的等待时间,实际释放
可能更早。
对于 MCP 套餐,每个窗口当前的用量百分比会显示在「MCP 集成」页面上。
ACTION FOR THE HUMAN: open https://app.anysite.io/mcp (查看 MCP 用量).