NTS BizNo CLI
by @chloepark85
Verify Korean business registration numbers (사업자등록번호) via the official NTS (국세청) public API. Operating-status lookup (계속/휴업/폐업), full authenticity check (b_n...
clawhub install nts-bizno-cli📖 About This Skill
name: nts-bizno-cli description: Verify Korean business registration numbers (사업자등록번호) via the official NTS (국세청) public API. Operating-status lookup (계속/휴업/폐업), full authenticity check (b_no + 개업일 + 대표자명), local checksum validation without API calls, and bulk file processing. Use when onboarding Korean businesses, validating B2B partners, building KYB pipelines, deduplicating supplier lists, or pre-filling 세금계산서/견적서/계약서 forms with NTS-confirmed data. Pairs with unified-invoice (form fill), opendart-cli (corporate filings), and juso-address-cli (address resolution) to complete the Korean B2B onboarding toolchain. version: 0.1.0 license: MIT
nts-bizno-cli
Command-line wrapper for the NTS 사업자등록정보 진위확인 및 상태조회 서비스 (Korean National Tax Service business-registration API), exposed via data.go.kr / api.odcloud.kr.
Two official endpoints + two local conveniences:
| Command | Endpoint | API key? | Purpose |
|---|---|---|---|
| scripts/status.sh | POST /v1/status | yes | Look up operating status (계속사업자/휴업자/폐업자) for up to 100 b_no per call. |
| scripts/validate.sh | POST /v1/validate | yes | Authenticity check — does (b_no + 개업일 + 대표자명) match NTS records? |
| scripts/format.sh | local | no | Verify checksum + format XXX-XX-XXXXX. No network. |
| scripts/bulk.sh | POST /v1/status | yes | Read a file of b_no's, checksum-filter, batch-call status in groups of 100. |
All output is JSONL (one record per line) so it pipes straight into jq, csvkit, or downstream skills.
When to use this skill
Do not use this skill for
juso-address-cli.opendart-cli.unified-invoice.Prerequisites
1. Get a serviceKey at 상태조회 and 진위확인 are commonly approved on the same day. Free-tier quota is 10,000 requests/day for each.
2. Export the encoded key:
Use the Encoding key (URL-encoded) — the wrapper passes it through export NTS_API_KEY='Ad9...%2BAbc%3D' # paste the "일반 인증키 (Encoding)" value
serviceKey= directly.
3. Dependencies: bash, curl, jq (default on macOS/Linux).
Commands
1) Status lookup (scripts/status.sh)
# Single
scripts/status.sh 124-81-00998Multiple (up to 100 per call)
scripts/status.sh 1248100998 220-81-62517 120-81-47521
Sample row:
{"b_no":"1248100998","b_no_formatted":"124-81-00998","b_stt_cd":"01","b_stt":"계속사업자","tax_type_cd":"01","tax_type":"부가가치세 일반과세자","end_dt":"","utcc_yn":"N","tax_type_change_dt":"","invoice_apply_dt":"","rbf_tax_type_cd":"","rbf_tax_type":""}
Status codes:
b_stt_cd=01 → 계속사업자 (active)b_stt_cd=02 → 휴업자 (dormant)b_stt_cd=03 → 폐업자 (closed) — end_dt carries 폐업일.b_stt_cd="" → b_no not registered with NTS at all.Tax-type codes:
01 부가가치세 일반과세자, 02 부가가치세 간이과세자, 03 부가가치세 면세사업자, 04 비영리법인, 05/06 외국 / 임시.2) Authenticity check (scripts/validate.sh)
Single record — flags:
scripts/validate.sh \
--b-no 124-81-00998 \
--start-dt 19690113 \
--p-nm "한종희"
Batch — JSON file:
cat > /tmp/payload.json <<'EOF'
{"businesses":[
{"b_no":"1248100998","start_dt":"19690113","p_nm":"한종희","p_nm2":"","b_nm":"","corp_no":"","b_sector":"","b_type":""},
{"b_no":"2208162517","start_dt":"19990602","p_nm":"최수연","p_nm2":"","b_nm":"","corp_no":"","b_sector":"","b_type":""}
]}
EOF
scripts/validate.sh --file /tmp/payload.json
Sample row:
{"b_no":"1248100998","b_no_formatted":"124-81-00998","valid":true,"valid_code":"01","valid_msg":"확인","status":{...}}
valid: true ⇔ NTS confirms a match. valid: false (valid_code:"02") means at least one of (b_no, 개업일, 대표자명) does not match — valid_msg carries the reason.
3) Local checksum (scripts/format.sh)
No network, no key. Cheap pre-filter before hitting the API.
scripts/format.sh 1248100998 abc-def-1234 220-81-62517
{"input":"1248100998","normalized":"1248100998","formatted":"124-81-00998","valid_checksum":true}
{"input":"abc-def-1234","normalized":"abcdef1234","formatted":"abcdef1234","valid_checksum":false}
{"input":"220-81-62517","normalized":"2208162517","formatted":"220-81-62517","valid_checksum":true}
Algorithm (NTS official): weights [1,3,7,1,3,7,1,3,5] over the first 9 digits, plus floor(d8*5/10), mod 10, complement to 10. Saves you a network round trip on typo'd inputs.
4) Bulk processor (scripts/bulk.sh)
# File input — one b_no per line, comments with #
cat > /tmp/suppliers.txt <<'EOF'
124-81-00998 # Samsung Electronics
220-81-62517 # NAVER
120-81-47521 # Kakao
123-45-67890 # bogus typo
EOF
scripts/bulk.sh /tmp/suppliers.txt > /tmp/audit.jsonlstdin
psql -At -c 'SELECT bno FROM suppliers' | scripts/bulk.sh - > /tmp/audit.jsonl
bulk.sh runs the local checksum first; bad entries get flagged with {"error":"checksum_failed"} and never burn API quota. Good entries are batched in groups of 100 (NTS hard limit).
Common pipelines
# Find all suppliers that closed
scripts/bulk.sh suppliers.txt | jq -c 'select(.b_stt_cd=="03") | {b_no, end_dt}'Tax-type breakdown
scripts/bulk.sh suppliers.txt | jq -r '.tax_type' | sort | uniq -c | sort -rnOnboarding gate — only proceed if 계속사업자 + 일반과세
scripts/status.sh "$BNO" \
| jq -e 'select(.b_stt_cd=="01" and .tax_type_cd=="01")' >/dev/null \
&& echo "ok to issue 세금계산서" \
|| { echo "blocked"; exit 1; }
Errors & quirks
code:-4 "등록되지 않은 인증키 입니다." — your NTS_API_KEY is wrong or hasn't been approved yet for this specific endpoint. Check data.go.kr → 마이페이지 → 활용신청 현황.code:-22 "사용한도..." — you've exceeded your free-tier daily quota. Apply for 활용 한도 증가 in 마이페이지.validate endpoint counts each item in businesses[] separately against quota; status counts only one request regardless of b_no[] length. Prefer status for cheap status sweeps.end_dt even when b_stt_cd != "03" if the business was once closed and re-opened — read both fields.start_dt on validate must be YYYYMMDD (no dashes); pre-1900 / future dates are rejected.Project layout
nts-bizno-cli/
├── SKILL.md # this file
├── README.md # short user-facing intro (mirrors SKILL.md)
├── LICENSE # MIT
├── scripts/
│ ├── _common.sh # shared helpers (auth, POST, checksum, format)
│ ├── status.sh # 상태조회
│ ├── validate.sh # 진위확인
│ ├── format.sh # local checksum + formatter
│ └── bulk.sh # file-driven status sweep
└── examples/
└── supplier-audit.md
⚙️ Configuration
1. Get a serviceKey at 상태조회 and 진위확인 are commonly approved on the same day. Free-tier quota is 10,000 requests/day for each.
2. Export the encoded key:
Use the Encoding key (URL-encoded) — the wrapper passes it through export NTS_API_KEY='Ad9...%2BAbc%3D' # paste the "일반 인증키 (Encoding)" value
serviceKey= directly.
3. Dependencies: bash, curl, jq (default on macOS/Linux).