> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.claw-ops.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.claw-ops.com/_mcp/server.

# 증명서 조회

GET https://api.claw-ops.com/v1/accounts/{accountId}/certificates/{certificateNumber}

Reference: https://docs.claw-ops.com/api-reference/claw-ops-api/certificates/get-certificate

## Authentication

- `Authorization` header (bearer token, required) — API Key를 Bearer 토큰으로 전달

## Request

### Path parameters

- `accountId` (string, required) — 계정 ID
- `certificateNumber` (string, required) — 발급번호(문서에 찍힌 번호)

## Response

### 200

증명서

- `certificateNumber` (string, required) — 발급번호 KAT-YYYYMMDD-NNNN(날짜 = KST 발급일)
- `type` (enum, required)
  - Allowed values: `telecom_subscription`
- `title` (string, required) — 발급 당시 문서 제목
- `holder` (CertificateHolder, required) — 문서에 찍힌 명의. 사업자 계정은 상호·사업자등록번호, 개인 계정은 그 번호에 연결된 본인확인 명의다. 관리번호(발급 링크로 최종이용자에게 배정한 번호)는 계정과 관계없이 최종이용자 명의다 — 법인은 발급 때 확인한 상호·사업자등록번호, 개인은 본인확인 명의. 개인의 생년월일은 **가려서** 돌려준다(원문은 PDF 에만 있다).
- `subject` (TelecomSubscriptionSubject, required) — telecom_subscription(통신서비스 이용증명원)이 증명하는 대상 — 번호와 가입일.
- `issueDate` (date, required)
- `status` (enum, required)
  - Allowed values: `issued`, `revoked`
- `revokedAt` (datetime, required, nullable)
- `revokedReason` (string, required, nullable)
- `pdfSha256` (string, required, nullable) — PDF 파일의 SHA-256(hex). 받은 파일과 대조할 수 있다.
- `pdfPath` (string, required) — PDF 다운로드 경로(이 API 의 GET …/pdf)
- `createdAt` (datetime, required)

## Errors

### 401 Unauthorized Error

인증 실패

- `error` (string, optional) — 사람이 읽을 수 있는 에러 메시지
- `code` (string, optional) — 기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서 바뀔 수 있지만 코드는 계약입니다. 같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는 - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서 해제해야 발신됩니다. - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다. 전화번호 정규화 관련: - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님) - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)
- `ip` (string, optional) — `overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다. 해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔 「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.
- `processedAt` (datetime, optional) — 문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.
- `blockers` (list of CertificateBlocker, optional) — `certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.

### 403 Forbidden Error

접근 권한 없음 (OIDC 토큰은 scope 필요)

- `error` (string, optional) — 사람이 읽을 수 있는 에러 메시지
- `code` (string, optional) — 기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서 바뀔 수 있지만 코드는 계약입니다. 같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는 - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서 해제해야 발신됩니다. - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다. 전화번호 정규화 관련: - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님) - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)
- `ip` (string, optional) — `overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다. 해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔 「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.
- `processedAt` (datetime, optional) — 문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.
- `blockers` (list of CertificateBlocker, optional) — `certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.

### 404 Not Found Error

증명서를 찾을 수 없음 (`certificate_not_found`)

- `error` (string, optional) — 사람이 읽을 수 있는 에러 메시지
- `code` (string, optional) — 기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서 바뀔 수 있지만 코드는 계약입니다. 같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는 - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서 해제해야 발신됩니다. - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다. 전화번호 정규화 관련: - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님) - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)
- `ip` (string, optional) — `overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다. 해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔 「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.
- `processedAt` (datetime, optional) — 문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.
- `blockers` (list of CertificateBlocker, optional) — `certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.

## Types

### CertificateHolder

문서에 찍힌 명의. 사업자 계정은 상호·사업자등록번호, 개인 계정은 그 번호에 연결된 본인확인 명의다. 관리번호(발급 링크로 최종이용자에게 배정한 번호)는 계정과 관계없이 최종이용자 명의다 — 법인은 발급 때 확인한 상호·사업자등록번호, 개인은 본인확인 명의. 개인의 생년월일은 **가려서** 돌려준다(원문은 PDF 에만 있다).

- `type` (enum, required)
  - Allowed values: `business`, `personal`
- `name` (string, required)
- `registrationNumber` (string, optional) — 사업자등록번호(사업자일 때만)
- `birthDate` (string, optional) — 가린 생년월일(개인일 때만)

### TelecomSubscriptionSubject

telecom_subscription(통신서비스 이용증명원)이 증명하는 대상 — 번호와 가입일.

- `number` (string, required) — 저장형 번호(하이픈 없음)
- `numberType` (enum, required) — internet_phone = 070 인터넷전화, representative_number = 대표번호(15xx·16xx·18xx)
  - Allowed values: `internet_phone`, `representative_number`
- `subscriptionDate` (date, required) — 이 계정이 이 번호를 처음 배정받은 날(KST)

### CertificateBlocker

번호 하나가 발급되지 않는(또는 안내가 필요한) 이유. | code | 뜻 | 발급 | |---|---|---| | `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 | | `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 | | `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 | | `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 | | `account_restricted` | 이용 제한 계정 | 막힘 | | `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 | | `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |

- `code` (enum, required)
  - Allowed values: `number_not_owned`, `number_not_carrier_issued`, `business_info_incomplete`, `identity_unverified`, `account_restricted`, `business_recheck_pending`, `holder_is_personal`
- `message` (string, required)
- `number` (string, optional) — 422 응답의 blockers 에만 있다

## Examples

**Response**

```json
{
  "certificateNumber": "KAT-20261016-0001",
  "type": "telecom_subscription",
  "title": "통신서비스 이용증명원",
  "holder": {
    "type": "business",
    "name": "주식회사 예시",
    "registrationNumber": "123-45-67890",
    "birthDate": "1980-**-**"
  },
  "subject": {
    "number": "07012340001",
    "numberType": "internet_phone",
    "subscriptionDate": "2026-08-14"
  },
  "issueDate": "2026-10-16",
  "status": "issued",
  "revokedAt": null,
  "revokedReason": null,
  "pdfSha256": "3b5f0c1e9a7d4b2e8f6a1c0d9e8b7a6f5e4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b",
  "pdfPath": "/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001/pdf",
  "createdAt": "2026-10-16T01:02:03.000Z"
}
```

**SDK Code**

```python
import requests

url = "https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.claw-ops.com/v1/accounts/AC1a2b3c4d/certificates/KAT-20261016-0001")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```