> 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/ko/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개까지 보낼 수 있으며, 각 경로는 영문자, 숫자, 밑줄로 이루어진 1~64자 세그먼트를 최대 6개까지 가질 수 있습니다. 그 외의 값은 요청이 실행되기 전에 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`.

- `X-Request-Id` 헤더와 같은 값을 반복하는 `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이지만, 일부 엔드포인트는 가격 결과의 `registrarName`, 가치 평가 요인의 `tldTier`, RDAP 이벤트의 `eventDate`처럼 일부 camelCase 키를 반환합니다. 쿼리 문자열에 `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` 경로는 `fields=factors.tld_tier`처럼 snake_case로 작성하세요. 오류 응답은 이미 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`에 받은 데이터의 경과 시간이 표시됩니다. 0부터 2592000 사이의 정수가 아닌 `max_age`는 요청이 실행되기 전에 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`와 `http_404`, `nxdomain` 같은 선택적 `detail`이 포함됩니다.

- `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`을 보고합니다.
