> For the complete documentation index see https://domscan.net/llms.txt. Markdown versions of every docs page are available by appending .md to the page URL.

Source: https://domscan.net/zh/docs/response-format

# 响应格式

通过 DomScan API，所有响应均为 JSON。每个域名结果都包含以下通用字段：

所有响应均为 JSON。每个域名结果都包含以下通用字段：

- `domain` - 完整域名

- `available` - 布尔型可用状态

- `source` - "rdap" 或 "cache"

- `checked_at` - ISO 8601 时间戳

- `error` - 发生错误时会出现

### 响应元数据

每个 API 响应都包含请求 ID 和新鲜度值。在可用时，响应标头还会显示请求、已扣费、已退款和剩余的积分，以及您的速率限制方案、限制、剩余容量和策略。新鲜度值为 `unknown` 表示无法确定该响应的新鲜度。这并不表示数据是最新的。

### 字段选择与精简响应

在任意 GET 或 POST 请求的查询字符串中添加 `fields` 或 `compact`,即可获得更小的 JSON 响应。两者均为可选。对于 POST 请求,它们应放在查询字符串中,而不是请求体中。两者都不会改变积分消耗。

#### 选择字段

`fields` 接受以逗号分隔的点路径,例如 `fields=domain,classification.status,records.data`。当路径经过列表时,会应用于列表中的每一项。各项保持原有位置,没有任何所选字段的项会变为 `{}`。路径上的 null 值会保留为 null。

最多可传入 50 个路径,每个路径最多包含 6 段,每段为 1 到 64 个字母、数字或下划线。其他任何取值都会在请求执行前返回 400 INVALID_PARAMETER,因此不会产生扣费。

响应中未匹配到任何内容的路径会被忽略,并列在 `X-Fields-Ignored` 响应头中,最多 20 个路径。

#### 精简响应

`compact=true` 只会移除以下内容,且仅限响应的顶层:

- `meta` 对象中的 `served_by` 以及耗时相关的键 `duration_ms`、`query_time_ms`、`total_ms`、`total_time_ms`、`latency_ms`、`generation_ms` 和 `check_duration_ms`。如果 `meta` 对象中没有其他内容,则该对象本身也会被移除。

- 当 `warnings`、`caveats`、`notes` 和 `errors` 为空列表时。

- 当 `request_id` 与 `X-Request-Id` 响应头重复时。

数据字段、`classification`、嵌套对象和列表项绝不会被移除。同时传入两个参数时,先执行 compact,再执行 fields。

仅成功的 JSON 响应会被重塑。错误响应、CSV、文本和流式响应以及 `dry_run` 预估会原样返回。重塑后的响应不带缩进。

使用 `Idempotency-Key` 时,`fields` 和 `compact` 属于请求的一部分。使用相同取值重试会返回已存储的、经过重塑的响应。使用不同取值重复使用同一个密钥会返回 422 IDEMPOTENCY_KEY_REUSED。

MCP 工具接受相同的可选参数 `fields` 和 `compact`。未匹配的路径会列在工具结果的 `_meta.fields_ignored` 中。

#### 示例

```bash
curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns?domain=google.com&type=TXT&fields=domain,status,records.data,records.ttl,owner&compact=true"

X-Fields-Ignored: owner

{
  "domain": "google.com",
  "records": [
    {
      "data": "v=spf1 include:_spf.google.com ~all",
      "ttl": 300
    },
    {
      "data": "google-site-verification=abc123",
      "ttl": 300
    }
  ],
  "status": "success"
}
```

### snake_case 键 (naming)

大多数响应键已经是 snake_case，但少数端点仍会返回部分 camelCase 键，例如定价结果中的 `registrarName`、估值因素中的 `tldTier` 以及 RDAP 事件中的 `eventDate`。在查询字符串中添加 `naming=snake`，或发送 `DomScan-Naming: snake` 请求头，即可让这些键全部以 snake_case 返回。不使用该选项时，响应保持当前的键名。

只有以小写字母开头、仅包含字母和数字且至少含有一个大写字母的键才会被转换。每个新单词前会加下划线，整个键转为小写。缩写会保持连在一起，包括 `IPv4` 以及 `IPs` 这类复数形式：`registrarName` 变为 `registrar_name`，`secureDNS` 变为 `secure_dns`，`ipv4Address` 变为 `ipv4_address`，`nameserverIPs` 变为 `nameserver_ips`。

属于数据而非字段名的键会保持原有拼写，例如 `A` 和 `MX` 等 DNS 记录类型、`A+` 等评级、域名、请求头名称和技术名称。值永远不会被修改，嵌套的对象和列表在每一层都会被转换。

如果对象中已经存在 snake_case 名称，例如同时有 `fooBar` 和 `foo_bar`，则 `foo_bar` 保留其值，`fooBar` 保留原名，因此不会丢失任何数据。键的顺序不会改变。

查询参数的优先级高于请求头，因此 `naming=default` 可以在单次请求中关闭通过请求头启用的选项。可接受的值为 `snake` 和 `default`。任何其他值都会在请求执行前返回 400 INVALID_PARAMETER，因此不会扣费。响应中包含 `Vary: DomScan-Naming`。

`naming` 先于 `compact` 和 `fields` 执行，因此 `fields` 路径请使用 snake_case 书写，例如 `fields=factors.tld_tier`。错误响应本身已是 snake_case，不会发生变化，积分消耗也保持不变。

使用 `Idempotency-Key` 时，无论 naming 选择来自参数还是请求头，它都是请求的一部分，因此重试会返回相同的键。

MCP 工具接受同样的可选 `naming` 参数。MCP 调用不会读取该请求头。

```bash
curl -H "X-API-Key: $DOMSCAN_API_KEY" -H "DomScan-Naming: snake" "https://domscan.net/v1/value?domain=example.com&fields=domain,factors.tld_tier,factors.has_hyphens"

{
  "domain": "example.com",
  "factors": {
    "tld_tier": "premium",
    "has_hyphens": false
  }
}
```

### 新鲜度控制 (max_age)

可以基于近期检查过的数据作答的端点支持 `max_age` 参数，取值为 0 到 2592000（30 天）之间的整数秒数。早于 `max_age` 的数据会在返回前重新检查，`max_age=0` 则始终进行全新检查。不传 `max_age` 时，各端点保持原有行为。

这些端点的每个成功响应都会在顶层包含 `cache_age_s`：所用数据的存在时长（秒），若为全新检查则为 0。相同的值也会通过 `X-Cache-Age` 响应头返回。当响应包含多个条目时（例如一次检查多个域名的可用性），该值为其中最旧条目的存在时长，而原本就带有 `cache_age_s` 的条目会保留各自的值。

`max_age` 不会改变结果的分类方式。无法确认的结果无论多新，都保持 `unknown`；除非原始检查已经确认，否则近期数据绝不会显示为存在或不存在。

`max_age` 不会改变请求的费用。全新检查与基于近期数据的回答消耗相同的额度。

在 `/v1/status` 和 `/v1/status/bulk` 上，为保护注册局，强制全新检查 (`max_age=0`) 按客户端设有限额。超出限额后，请求将按未传 `max_age` 处理，`cache_age_s` 会显示您所收到数据的存在时长。如果 `max_age` 不是 0 到 2592000 之间的整数，系统会在请求执行前返回 400 INVALID_PARAMETER，因此不会产生任何费用。

支持 `max_age` 的端点： `GET /v1/status`, `POST /v1/status/bulk`, `GET /v1/subdomains`, `GET /v1/certificates`, `GET /v1/tech`, `GET /v1/categorize`, `GET /v1/identity-assets`, `GET /v1/identity-resolution`, `GET /v1/url-intelligence`, `GET /v1/agent-readiness`, `GET /v1/robots`, `GET /v1/ssl/deep-scan`

#### 旧版缓存参数

这些参数仍可使用，现已成为 `max_age` 的已弃用别名。如果同时传入 `max_age`，则以 `max_age` 为准。

| 参数 | 端点 | 等同于 |
| --- | --- | --- |
| `prefer_cache` | `/v1/status`, `/v1/subdomains` | `max_age=2592000` |
| `skip_cache` | `/v1/status`, `/v1/tech`, `/v1/categorize`, `/v1/identity-assets`, `/v1/identity-resolution`, `/v1/url-intelligence`, `/v1/agent-readiness`, `/v1/robots` | `max_age=0` |
| `cache_skip` | `/v1/status` | `max_age=0` |
| `cache-skip` | `/v1/status` | `max_age=0` |
| `options.prefer_cache (body)` | `/v1/status/bulk` | `max_age=2592000` |
| `prefer_cache (body)` | `/v1/status/bulk` | `max_age=2592000` |
| `options.skip_cache (body)` | `/v1/status/bulk` | `max_age=0` |
| `options.cache_skip (body)` | `/v1/status/bulk` | `max_age=0` |
| `options.cache-skip (body)` | `/v1/status/bulk` | `max_age=0` |
| `refresh` | `/v1/ssl/deep-scan` | `max_age=0` |

在 `/v1/subdomains` 上，`prefer_cache` 同样保留仅使用缓存的行为：当尚无任何已存储数据时，请求返回 202 且不扣费，并在后台启动查询。

这些端点对应的 MCP 工具支持相同的可选参数 `max_age`，其结果包含 `cache_age_s`。

### 分页 (limit 和 cursor)

返回较长列表的端点支持 `limit` 和 `cursor`，每个响应都包含 `has_more` 和 `next_cursor`。要获取下一页，请重复该请求，并将 `cursor` 设置为 `next_cursor`。在最后一页，`has_more` 为 false，`next_cursor` 为 null。

不传 `limit` 时，各端点返回的条目数与以前相同，因此现有请求不受影响。您可以在翻页时更改 `limit`。

游标是不透明且经过签名的。游标仅对收到它的账户和相同的查询有效，例如相同的域名和筛选条件。被修改过、属于其他账户或搭配不同筛选条件发送的游标，会返回 400 INVALID_CURSOR。

分页遵循稳定的顺序，因此在两次请求之间新增或移除的条目不会被重复或遗漏。在历史记录端点上，汇总字段描述的是当前页的条目。

每一页都是一次普通请求，按该端点的常规额度计费，与以前带 `limit` 的请求完全一致。免费端点依然免费。

旧版参数仍可使用：`/v1/email/blacklist` 上的 `offset`，以及 `/v1/certificates` 上的数字型 `pagination.next_cursor`。

| 端点 | 默认每页数量 | limit 上限 |
| --- | --- | --- |
| `GET /v1/whois/history` | 50 | 100 |
| `GET /v1/dns/history` | 100 | 1000 |
| `GET /v1/subdomains` | 500 | 2000 |
| `GET /v1/certificates` | 100 | 1000 |
| `GET /v1/watchlist` | 完整列表 | 100 |
| `GET /v1/watchlist/expiring` | 完整列表 | 100 |
| `GET /v1/watchlist/available` | 完整列表 | 100 |
| `GET /v1/brand-monitor` | 完整列表 | 100 |
| `GET /v1/email/blacklist` | 1000 | 10000 |

#### 示例

```bash
curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/whois/history?domain=example.com&limit=20"

{
  "domain": "example.com",
  "snapshots": [
    "..."
  ],
  "has_more": true,
  "next_cursor": "eyJvIjoi..."
}

curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/whois/history?domain=example.com&limit=20&cursor=eyJvIjoi..."
```

### 分类状态

用于报告某项内容是否存在的端点（域名注册、社交媒体账号、DNS 与邮件认证记录、security.txt、robots.txt、站点地图、安全标头、域名停放、抢注域名注册以及 SSL 证书）会在现有字段之外新增一个 `classification` 对象。现有字段的名称和含义保持不变。

- `status` - 取值为 `present`（存在）、`absent`（不存在）或 `unknown`（未知）。只有当检查获得了准确且权威的证据时，才会返回 present 和 absent。

- `reason` - 仅在状态为 `unknown` 时返回，用于说明为何无法给出明确答案。

- `evidence` - 结果的来源信息，包括 `source`、`method`、`observed_at`，以及可选的 `detail`（例如 `http_404` 或 `nxdomain`）。

- `checked_at` - DomScan 生成该分类的时间。对于缓存结果，`evidence.observed_at` 的时间更早。

#### unknown 的原因

- `blocked` - 目标拒绝了访问，例如返回 HTTP 401、403 或触发了机器人验证。

- `rate_limited` - 目标或注册机构要求我们降低请求频率，例如返回 HTTP 429。

- `timeout` - 检查未能在时间预算内完成。

- `ambiguous` - 收到了响应，但无法证明存在或不存在，例如状态码异常或记录格式错误。

- `upstream_error` - 数据源出现故障，例如 DNS 服务器故障或返回 HTTP 5xx 响应。

- `unsupported` - 该检查不适用于此输入，例如不受支持的 TLD，或没有可靠检测手段的平台。

```json
{
  "classification": {
    "status": "unknown",
    "reason": "rate_limited",
    "evidence": {
      "source": "rdap",
      "method": "rdap_lookup",
      "observed_at": "2026-10-10T09:30:00.000Z",
      "detail": "http_429"
    },
    "checked_at": "2026-10-10T09:30:00.000Z"
  }
}
```

被拦截、被限流、超时或失败的检查绝不会被报告为 absent。请将 `unknown` 理解为“请稍后重试”，而不是“不存在”，也不要把不存在当作名称可被注册的证明。

#### 包含未知检查的评分和等级

评分绝不会把未知的检查当作缺失。DNS 安全评分和邮件认证等级会排除未知的检查，在 `checks_unknown` 中报告它们，并将 `score_confidence` 设为 `partial`。当所有检查均未知时，评分和等级为 `null`。无法读取证书时，SSL 等级和评分为 `null`，且 `grade_reason` 设为 `certificate_not_retrieved`；信誉评分在停放状态未知时报告 `null`，而不是未停放。
