経理には「新規の取引先、この会社ほんとに実在する?商号合ってる?インボイス番号は正しい?」を確認する地味な作業がある。国税庁のサイトで番号を一件ずつ引く、あれだ。これをAIに“チェック担当”として任せてみた。バクラクの申請を渡すと、AIが国税庁に照合してOK/要確認を返してくる。やってみたら、人が見落としがちな“消えた会社”まで拾ってきた。
たび丸投げで放置、じゃない。AIに担当させて、自分は最後の判断だけやる。やってみたら想像以上に実用だった。
そもそも、何を確認する作業か
新規取引先の登録申請が来るたび、確認するのはこの4点——実在するか/商号は正しいか/インボイス登録番号は整合するか/法人番号は妥当か。単純だが件数があり、合併で閉鎖された番号のような落とし穴は目視だと普通に見逃す。
AIに「チェック担当」として渡してみた
やったことはシンプル。AIに申請とツール(API)を渡して、こう動かす。まずバクラク側から対象の申請を取ってくる(ここはベンダーのAPIなので擬似コード)。
# バクラクAPIで「申請中の新規取引先申請」を取得し、
# 各申請から 法人番号・取引先名・インボイス番号 を取り出す
applications = bakuraku.fetch_requests(status="IN_PROGRESS", form="新規取引先申請")
次が本題。法人番号は“それっぽい13桁”でも、チェックディジットで真偽が分かる。ここは国が公開している計算式なので、実コードを載せる。
def validate_corporate_number(number: str) -> bool:
"""法人番号13桁のチェックディジットを検証する。"""
if not number or len(number) != 13 or not number.isdigit():
return False
check_digit = int(number[0])
base = number[1:] # 下位12桁が基礎番号
total = 0
for i, ch in enumerate(reversed(base)):
weight = 2 if i % 2 == 1 else 1 # 右から 奇数桁=1, 偶数桁=2
total += int(ch) * weight
return (9 - (total % 9)) == check_digit
そして実在・商号・“閉鎖”は、国税庁の公式Web-APIに当てる。AIが数字を捏造する余地がないのは、ここで一次情報に照合しているからだ。
import csv, requests
NTA_API = "https://api.houjin-bangou.nta.go.jp"
def nta_lookup(numbers: list[str], app_id: str, version: str = "4") -> dict:
"""国税庁 法人番号Web-APIで 実在・商号・閉鎖 を照会する。"""
resp = requests.get(
f"{NTA_API}/{version}/num",
params={
"id": app_id, # 無料発行のアプリID
"number": ",".join(numbers), # 最大10件まとめて
"type": "02", # CSV(Unicode)で受け取る
"history": "0", # 最新の登記のみ
},
)
resp.raise_for_status()
records = {}
for row in csv.reader(resp.content.decode("utf-8").splitlines()):
if len(row) <= 20:
continue # ヘッダー行などをskip
records[row[1]] = { # row[1] = 法人番号
"name": row[6], # 商号
"closeDate": row[18], # 閉鎖年月日(合併・解散など)
"successor": row[20], # 承継先の法人番号
}
return records
最後に、結果を「OK」と「要確認」に振り分ける。人が見るのは要確認だけだ。
issues = []
if not validate_corporate_number(corp):
issues.append("法人番号CD不正")
if invoice and invoice != "T" + corp:
issues.append("インボイス番号不整合")
if record is None:
issues.append("国税庁に該当なし")
elif record["closeDate"]: # ← ここが効いた
issues.append("閉鎖/合併(承継先: " + (record["successor"] or "不明") + ")")
elif normalize(client_name) != normalize(record["name"]):
issues.append("商号不一致")
verdict = "要確認" if issues else "OK"
やってみて分かったこと
数字の検算も国税庁照合も、AIが“道具”(計算式・公式API)を使って機械的にやっている。AIが法人番号を勝手に作るわけじゃないから、捏造が起きない。
やってみたら、消えた会社を拾ってきた
実際に回したら、ある申請の法人番号が合併ですでに閉鎖済みのものだった。存続する会社は別の番号を持っている。名前は合っているので目視なら通しかねないところを、閉鎖年月日と承継先番号を見て自動で「要確認」に落とした。差し戻したのは自分だ。
APIキーが無くても、AIがWebで代替照合する
実はこのチェック、国税庁の公式Web-APIには無料のアプリIDが要る。発行が間に合わないこともある。でも止まらない。APIが使えないときは、AIに法人番号データベース(houjin.info など)で一件ずつ実在・商号・閉鎖を調べさせる。やることは人間の手作業と同じ——番号で引いて、登記の商号と申請名を見比べ、閉鎖していないか確認する。
しかもこの手順はプロジェクトのREADMEに書いてあって、AIはそれを読んでそのまま実行する。人に手順書を渡して仕事を任せるのと同じだ。要点はこれだけ。
- houjin.info で登記の商号・所在地・登記状態(現存/閉鎖)・承継先番号を読む
- houjin.jp でもクロスチェック(※旧住所が出ることがある→最新は houjin.info を優先)
- 申請名・住所と照合し、商号不一致/閉鎖/所在地相違なら「要確認」
- 番号はAIが生成しない/参照URLを根拠に残す/承認は人
やってみて分かったこと(代替手段)
APIが理想だが、無くてもAIが“人と同じ手作業”を代行できる。しかも手順をREADMEに書いておけば、AIは毎回それを読んで同じ品質で動く。“道具が無いから止まる”が減る。
どこまで任せて、どこは自分がやるか
任せたのは「全件照合して、要確認を上げてくる」ところまで。承認・差し戻しは自分。
役割分担
作業(照合・振り分け)はAI。判断(承認・差し戻し)と責任は人。AIは“優秀な確認担当”、自分は“最終承認者”。
おまけ:このコード、全部AIに書かせた
最後に正直に言うと、ここに載せたコードは自分でゴリゴリ書いていない。要件(何を確認したいか)をAIに渡して、実装はAI、レビューと検証は自分、という分担だ。経理がコードを書けなくても、AIを相棒にすればこの手の道具は作れる。
まとめ
バクラクの新規取引先チェックは「全件照合して要確認だけ上げるAI担当」になり、閉鎖済みの番号も自動検知。任せるのは作業、判断は自分。実装すらAIに任せられる時代だ。
次は「レシートと明細の照合」をAIにやらせた話を書く(画像をAIに読ませる、より“AIらしい”処理だ)。