- Use REGISTRANT_* env vars instead of DEFAULT_* for registrant info - Add REGISTRANT_ADDRESS2 to env config - Remove duplicate /childns/* endpoints (keep /glue/* only) - Add error handling to glue record endpoints - Document /domains/register endpoint in README Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
426 lines
11 KiB
Markdown
426 lines
11 KiB
Markdown
# Namecheap API
|
||
|
||
Namecheap 도메인 관리 및 가격 조회 Python 라이브러리
|
||
|
||
## 설치
|
||
|
||
```bash
|
||
cd /home/admin/namecheap_api
|
||
source ~/.local/bin/env
|
||
```
|
||
|
||
## 환경 설정
|
||
|
||
`.env` 파일 설정:
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
nano .env
|
||
```
|
||
|
||
```env
|
||
# Namecheap API 설정
|
||
NAMECHEAP_API_USER=your_api_user
|
||
NAMECHEAP_API_KEY=your_api_key
|
||
NAMECHEAP_USERNAME=your_username
|
||
NAMECHEAP_CLIENT_IP=your_whitelisted_ip
|
||
NAMECHEAP_SANDBOX=false
|
||
|
||
# REST API 서버 인증
|
||
API_SERVER_KEY=your_api_server_key # Vault: secret/namecheap/api-server
|
||
|
||
# 등록자 정보 (도메인 등록 시 기본값)
|
||
REGISTRANT_ORGANIZATION=회사명
|
||
REGISTRANT_FIRST_NAME=이름
|
||
REGISTRANT_LAST_NAME=성
|
||
REGISTRANT_ADDRESS1=주소1
|
||
REGISTRANT_ADDRESS2=주소2 (선택)
|
||
REGISTRANT_CITY=도시
|
||
REGISTRANT_STATE_PROVINCE=시/도
|
||
REGISTRANT_POSTAL_CODE=우편번호
|
||
REGISTRANT_COUNTRY=국가코드 (JP, KR, US 등)
|
||
REGISTRANT_PHONE=+국가번호.전화번호
|
||
REGISTRANT_EMAIL=이메일
|
||
```
|
||
|
||
## 사용법
|
||
|
||
### 도메인 목록 조회
|
||
|
||
```python
|
||
from dotenv import load_dotenv
|
||
import os
|
||
load_dotenv()
|
||
from namecheap import NamecheapAPI, NamecheapConfig
|
||
|
||
config = NamecheapConfig(
|
||
api_user=os.getenv('NAMECHEAP_API_USER'),
|
||
api_key=os.getenv('NAMECHEAP_API_KEY'),
|
||
username=os.getenv('NAMECHEAP_USERNAME'),
|
||
client_ip=os.getenv('NAMECHEAP_CLIENT_IP'),
|
||
sandbox=False,
|
||
)
|
||
api = NamecheapAPI(config)
|
||
|
||
# 도메인 목록
|
||
domains = api.domains_get_list()
|
||
for d in domains:
|
||
print(f"{d['name']} - 만료: {d['expires']}")
|
||
```
|
||
|
||
### 도메인 가용성 확인
|
||
|
||
```python
|
||
result = api.domains_check(["example.com", "example.net"])
|
||
for domain, available in result.items():
|
||
print(f"{domain}: {'사용 가능' if available else '등록됨'}")
|
||
```
|
||
|
||
### 도메인 등록
|
||
|
||
```python
|
||
from namecheap import RegistrantInfo
|
||
|
||
registrant = RegistrantInfo(
|
||
organization=os.getenv('REGISTRANT_ORGANIZATION'),
|
||
first_name=os.getenv('REGISTRANT_FIRST_NAME'),
|
||
last_name=os.getenv('REGISTRANT_LAST_NAME'),
|
||
address1=os.getenv('REGISTRANT_ADDRESS1'),
|
||
city=os.getenv('REGISTRANT_CITY'),
|
||
state_province=os.getenv('REGISTRANT_STATE_PROVINCE'),
|
||
postal_code=os.getenv('REGISTRANT_POSTAL_CODE'),
|
||
country=os.getenv('REGISTRANT_COUNTRY'),
|
||
phone=os.getenv('REGISTRANT_PHONE'),
|
||
email=os.getenv('REGISTRANT_EMAIL'),
|
||
)
|
||
|
||
result = api.domains_create("newdomain.com", registrant, years=1)
|
||
print(result)
|
||
# {'domain': 'newdomain.com', 'registered': True, 'charged_amount': 11.48, ...}
|
||
```
|
||
|
||
### 도메인 갱신
|
||
|
||
```python
|
||
result = api.domains_renew("example.com", years=1)
|
||
print(result)
|
||
# {'domain': 'example.com', 'renewed': True, 'charged_amount': 11.48, ...}
|
||
```
|
||
|
||
### 등록자 정보 조회/수정
|
||
|
||
```python
|
||
# 조회
|
||
contacts = api.domains_get_contacts("example.com")
|
||
print(contacts['registrant'])
|
||
# {'firstName': 'Taro', 'lastName': 'Tanaka', 'organizationName': 'LIBEHAIM Inc.', ...}
|
||
|
||
# 수정
|
||
from namecheap import RegistrantInfo
|
||
|
||
new_contact = RegistrantInfo(
|
||
organization="New Company",
|
||
first_name="Taro",
|
||
last_name="Tanaka",
|
||
address1="123 Street",
|
||
city="Tokyo",
|
||
state_province="Tokyo-to",
|
||
postal_code="100-0001",
|
||
country="JP",
|
||
phone="+81.312345678",
|
||
email="new@example.com",
|
||
)
|
||
api.domains_set_contacts("example.com", new_contact)
|
||
```
|
||
|
||
### DNS 관리
|
||
|
||
```python
|
||
# 네임서버 조회
|
||
ns_info = api.dns_get_list("example", "com")
|
||
print(ns_info)
|
||
# {'domain': 'example.com', 'is_using_our_dns': False, 'nameservers': ['ns1.cloudflare.com', ...]}
|
||
|
||
# DNS 레코드 조회 (Namecheap DNS 사용 시에만 가능)
|
||
records = api.dns_get_hosts("example", "com")
|
||
|
||
# DNS 레코드 설정
|
||
new_records = [
|
||
{"name": "@", "type": "A", "address": "1.2.3.4", "ttl": "1800"},
|
||
{"name": "www", "type": "CNAME", "address": "example.com", "ttl": "1800"},
|
||
]
|
||
api.dns_set_hosts("example", "com", new_records)
|
||
|
||
# 커스텀 네임서버로 변경
|
||
api.dns_set_custom("example", "com", ["ns1.cloudflare.com", "ns2.cloudflare.com"])
|
||
|
||
# Namecheap 기본 네임서버로 복원
|
||
api.dns_set_default("example", "com")
|
||
```
|
||
|
||
### 글루 레코드 (Child Nameserver)
|
||
|
||
자신의 도메인을 네임서버로 사용하려면 먼저 글루 레코드를 등록해야 합니다.
|
||
|
||
```python
|
||
# 글루 레코드 생성 (ns1.example.com → 1.2.3.4)
|
||
result = api.ns_create("example", "com", "ns1.example.com", "1.2.3.4")
|
||
print(result)
|
||
# {'domain': 'example.com', 'nameserver': 'ns1.example.com', 'ip': '1.2.3.4', 'success': True}
|
||
|
||
# 글루 레코드 조회
|
||
info = api.ns_get_info("example", "com", "ns1.example.com")
|
||
print(info)
|
||
# {'domain': 'example.com', 'nameserver': 'ns1.example.com', 'ip': '1.2.3.4', 'statuses': ['ok']}
|
||
|
||
# 글루 레코드 IP 변경
|
||
result = api.ns_update("example", "com", "ns1.example.com", "1.2.3.4", "5.6.7.8")
|
||
|
||
# 글루 레코드 삭제
|
||
result = api.ns_delete("example", "com", "ns1.example.com")
|
||
```
|
||
|
||
### 계정 정보
|
||
|
||
```python
|
||
# 잔액 조회
|
||
balance = api.users_get_balances()
|
||
print(f"잔액: ${balance['available_balance']}")
|
||
```
|
||
|
||
## 가격 조회 시스템
|
||
|
||
### 수동 가격 업데이트
|
||
|
||
```bash
|
||
uv run python update_prices.py
|
||
```
|
||
|
||
### 가격 조회 CLI
|
||
|
||
```bash
|
||
# 전체 TLD (저렴한 순)
|
||
uv run python prices.py
|
||
|
||
# 특정 TLD 검색
|
||
uv run python prices.py com
|
||
uv run python prices.py io
|
||
```
|
||
|
||
### 가격 계산 방식
|
||
|
||
```
|
||
최종가격 = USD × 환율 × 1.10(부가세) × 1.03(마진)
|
||
→ 1,000원 단위 올림
|
||
```
|
||
|
||
### 자동 업데이트 스케줄
|
||
|
||
systemd timer로 하루 3회 자동 업데이트:
|
||
|
||
| 시간 | 설명 |
|
||
|------|------|
|
||
| 09:30 | 시장 개장 후 |
|
||
| 12:30 | 중간 |
|
||
| 16:00 | 시장 마감 후 |
|
||
|
||
```bash
|
||
# 타이머 상태 확인
|
||
systemctl --user list-timers namecheap-prices.timer
|
||
|
||
# 로그 확인
|
||
journalctl --user -u namecheap-prices.service
|
||
|
||
# 타이머 재시작
|
||
systemctl --user restart namecheap-prices.timer
|
||
```
|
||
|
||
## REST API 서버 (OpenAI 호환)
|
||
|
||
OpenAI Function Calling / Custom GPT / Cloudflare Workers에서 사용할 수 있는 REST API 서버입니다.
|
||
|
||
### 공개 엔드포인트
|
||
|
||
```
|
||
https://namecheap-api.anvil.it.com
|
||
```
|
||
|
||
### 인증
|
||
|
||
모든 요청에 `X-API-Key` 헤더 필요:
|
||
|
||
```bash
|
||
curl -H "X-API-Key: YOUR_API_KEY" https://namecheap-api.anvil.it.com/domains
|
||
```
|
||
|
||
API Key는 Vault에 저장됨:
|
||
- 경로: `secret/namecheap/api-server`
|
||
- 키: `key`
|
||
|
||
```bash
|
||
vault kv get secret/namecheap/api-server
|
||
```
|
||
|
||
### 수동 실행
|
||
|
||
```bash
|
||
uv run python api_server.py
|
||
# http://localhost:8000 에서 실행
|
||
```
|
||
|
||
### systemd 서비스
|
||
|
||
```bash
|
||
# 상태 확인
|
||
systemctl --user status namecheap-api.service
|
||
|
||
# 재시작
|
||
systemctl --user restart namecheap-api.service
|
||
|
||
# 로그 확인
|
||
journalctl --user -u namecheap-api.service -f
|
||
```
|
||
|
||
### API 엔드포인트
|
||
|
||
| Method | Endpoint | 설명 |
|
||
|--------|----------|------|
|
||
| GET | `/domains` | 도메인 목록 |
|
||
| POST | `/domains/check` | 도메인 가용성 확인 |
|
||
| POST | `/domains/register` | 도메인 등록 (과금됨) |
|
||
| GET | `/domains/{domain}` | 도메인 상세 정보 |
|
||
| POST | `/domains/{domain}/renew` | 도메인 갱신 |
|
||
| GET | `/domains/{domain}/contacts` | 등록자 정보 조회 |
|
||
| PUT | `/domains/{domain}/contacts` | 등록자 정보 수정 |
|
||
| GET | `/dns/{domain}/nameservers` | 네임서버 조회 |
|
||
| PUT | `/dns/{domain}/nameservers` | 네임서버 변경 |
|
||
| POST | `/dns/{domain}/nameservers/default` | 기본 NS 복원 |
|
||
| GET | `/dns/{domain}/records` | DNS 레코드 조회 |
|
||
| POST | `/dns/{domain}/glue` | 글루 레코드 생성 |
|
||
| GET | `/dns/{domain}/glue/{nameserver}` | 글루 레코드 조회 |
|
||
| PUT | `/dns/{domain}/glue` | 글루 레코드 수정 |
|
||
| DELETE | `/dns/{domain}/glue/{nameserver}` | 글루 레코드 삭제 |
|
||
| GET | `/account/balance` | 계정 잔액 |
|
||
| GET | `/prices/{tld}` | TLD 가격 조회 |
|
||
| GET | `/prices` | 전체 가격 목록 |
|
||
| GET | `/openai/schema` | OpenAI Function 스키마 |
|
||
|
||
### Swagger UI
|
||
|
||
http://localhost:8000/docs
|
||
|
||
### OpenAI Custom GPT 설정
|
||
|
||
1. Custom GPT 생성
|
||
2. Actions 추가
|
||
3. Import from URL: `http://your-server:8000/openapi.json`
|
||
|
||
## MCP 서버
|
||
|
||
Claude에서 직접 Namecheap API를 사용할 수 있는 MCP 서버입니다.
|
||
|
||
### MCP 도구 목록
|
||
|
||
| 도구 | 설명 |
|
||
|------|------|
|
||
| `domains_check` | 도메인 가용성 확인 |
|
||
| `domains_list` | 보유 도메인 목록 |
|
||
| `domains_info` | 도메인 상세 정보 |
|
||
| `domains_renew` | 도메인 갱신 |
|
||
| `domains_get_contacts` | 등록자 정보 조회 |
|
||
| `dns_get_nameservers` | 네임서버 조회 |
|
||
| `dns_set_nameservers` | 네임서버 변경 |
|
||
| `dns_set_default` | 기본 NS로 복원 |
|
||
| `dns_get_records` | DNS 레코드 조회 |
|
||
| `glue_create` | 글루 레코드 생성 |
|
||
| `glue_get` | 글루 레코드 조회 |
|
||
| `glue_update` | 글루 레코드 수정 |
|
||
| `glue_delete` | 글루 레코드 삭제 |
|
||
| `account_balance` | 계정 잔액 |
|
||
| `price_check` | TLD 가격 조회 |
|
||
|
||
### Claude Code 설정
|
||
|
||
`~/.claude/settings.json`:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"namecheap": {
|
||
"command": "/home/admin/.local/bin/uv",
|
||
"args": ["run", "--directory", "/home/admin/namecheap_api", "python", "mcp_server.py"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Claude Desktop 설정
|
||
|
||
`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"namecheap": {
|
||
"command": "uv",
|
||
"args": ["run", "--directory", "/path/to/namecheap_api", "python", "mcp_server.py"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 테스트 실행
|
||
|
||
```bash
|
||
uv run python mcp_server.py
|
||
```
|
||
|
||
## 파일 구조
|
||
|
||
```
|
||
namecheap_api/
|
||
├── .env # 환경 설정 (git 제외)
|
||
├── .env.example # 환경 설정 템플릿
|
||
├── namecheap.py # API 클라이언트
|
||
├── __init__.py # 패키지 export
|
||
├── api_server.py # REST API 서버 (OpenAI 호환)
|
||
├── mcp_server.py # MCP 서버 (Claude)
|
||
├── db.py # 데이터베이스 모듈
|
||
├── prices.db # SQLite 가격 DB
|
||
├── prices.py # 가격 조회 CLI
|
||
├── update_prices.py # 가격 업데이트 스크립트
|
||
└── example.py # 사용 예제
|
||
```
|
||
|
||
## systemd 서비스 파일
|
||
|
||
```
|
||
~/.config/systemd/user/
|
||
├── namecheap-api.service # REST API 서버
|
||
├── namecheap-prices.service # 가격 업데이트 서비스
|
||
└── namecheap-prices.timer # 가격 업데이트 타이머
|
||
```
|
||
|
||
## API 메서드
|
||
|
||
| 메서드 | 설명 |
|
||
|--------|------|
|
||
| `domains_check(domains)` | 도메인 가용성 확인 |
|
||
| `domains_get_list()` | 보유 도메인 목록 |
|
||
| `domains_get_info(domain)` | 도메인 상세 정보 |
|
||
| `domains_create(domain, registrant)` | 새 도메인 등록 |
|
||
| `domains_renew(domain, years)` | 도메인 갱신 |
|
||
| `domains_get_contacts(domain)` | 등록자 정보 조회 |
|
||
| `domains_set_contacts(domain, registrant)` | 등록자 정보 수정 |
|
||
| `dns_get_list(sld, tld)` | 네임서버 조회 |
|
||
| `dns_get_hosts(sld, tld)` | DNS 레코드 조회 |
|
||
| `dns_set_hosts(sld, tld, records)` | DNS 레코드 설정 |
|
||
| `dns_set_custom(sld, tld, nameservers)` | 커스텀 NS 설정 |
|
||
| `dns_set_default(sld, tld)` | 기본 NS로 복원 |
|
||
| `ns_create(sld, tld, nameserver, ip)` | 글루 레코드 생성 |
|
||
| `ns_get_info(sld, tld, nameserver)` | 글루 레코드 조회 |
|
||
| `ns_update(sld, tld, nameserver, old_ip, ip)` | 글루 레코드 수정 |
|
||
| `ns_delete(sld, tld, nameserver)` | 글루 레코드 삭제 |
|
||
| `users_get_balances()` | 계정 잔액 조회 |
|
||
| `users_get_pricing(type, category)` | 상품 가격 조회 |
|