インボイス番号のチェックデジット計算と国税庁Web-APIの使い方

インボイス番号のチェックデジット計算と国税庁Web-APIの使い方

【PR】この記事にはアフィリエイトリンク(freee会計)が1箇所含まれます。記事の主題は番号検証の実装で、ツールとコードの部分に広告は関係しません。

この記事の仕様・URL・計算式は 2026年8月20日に国税庁の公式ページで確認した内容です。Web-API の仕様書は改訂されるため、実装前に必ず一次資料(記事末尾の「出典」)で最新版を確認してください。また、この記事はプログラムでの番号検証の話であり、仕入税額控除の可否など税務上の取り扱いについては触れません。判断が必要な場合は国税庁の情報または税理士にご確認ください。

請求書に書かれた インボイス登録番号(T+13桁) を、システム側で自動チェックしたい——受け取った請求書が月に何十枚もあると、1件ずつ国税庁のサイトに貼り付けて確認するのは現実的ではありません。

ところが実装しようとすると、情報がきれいに二分されていることに気づきます。「Excel でチェックする方法」を書いた非エンジニア向けの記事は大量にある一方で、「チェックデジットの計算式」と「国税庁 Web-API の使い方」を通しで書いた技術記事はほとんど見当たりません

私は自分のサイトで インボイス番号 一括チェッカー という無料ツールを公開・運用しています。この記事は、そのツールの中身(実際に動いているコード)と、そこであえてやらなかったことを含めた実装ノートです。

この記事の結論(先に要点)
  • 登録番号の検証は 2段構え。①チェックデジットによる形式の一次判定(通信なし・その場で終わる)→ ②国税庁の公表サイト/Web-API による実在確認(オンライン)
  • チェックデジットの計算式は国税庁が公開している。検査用数字 = 9 −(下12桁に重み1・2を掛けた合計 ÷ 9 の余り)。実装は10行程度で済む
  • ただし 一次判定が通っても「実在する」ことにはならない。失効・取消もあるし、そもそも架空の番号でも計算だけは通る。0と9の取り違えは数学的に検出できない(本文で実例を示します)
  • 実在確認に使う 国税庁 Web-API はアプリケーションIDの申請が必要(発行費用は掛からないと明記されている)。法人番号システムWeb-APIのIDを持っていても、インボイス側は別途申請・承認が必要
  • 数千件を一気に確認したいなら、API を叩き続けるより 「公表情報ダウンロード(全件・差分データ)」 を取り込む設計のほうが素直
  • 自作ツール /tools/invoice-check/あえて通信しない設計(取引先の番号を外部に送らないため)。判定も「無効」ではなく「要確認」と出す
インボイス番号の検証は2段構え:チェックデジットによるオフラインの一次判定と、国税庁Web-APIによるオンラインの実在確認(二次判定)の流れ図
目次

インボイス登録番号(T+13桁)の構造

まず番号そのものの構造を押さえます。国税庁の公表サイトによると、登録番号は次の形です(2026年8月20日確認)。

  • 法人の場合:「T」(ローマ字)+ 法人番号(数字13桁)
  • 個人事業者などの場合:「T」(ローマ字)+ 数字13桁

そして個人事業者などに付される13桁については、「13桁の数字には、マイナンバー(個人番号)は用いず、法人番号とも重複しない事業者ごとの番号」と説明されています。

つまり、法人の登録番号は法人番号そのものです。ここが実装上いちばん重要なポイントで、法人番号には検査用数字(チェックデジット)が組み込まれているため、通信せずに機械的な妥当性を判定できるという性質を、そのまま登録番号に持ち込めます。

インボイス登録番号(T+13桁)の構造:先頭Tの次の1桁が検査用数字、続く12桁が基礎番号であることを示した分解図

13桁の内訳は「検査用数字1桁+基礎番号12桁」

法人番号は、12桁の基礎番号と、その前に付された1桁の検査用数字で構成される13桁の番号です。左端の1桁が検査用数字で、残り12桁が基礎番号になります。

この記事のサンプルには T7000012050002 を使います。これは国税庁自身の法人番号(7000012050002)に T を付けたものです。分解するとこうなります。

  • 検査用数字:7
  • 基礎番号(12桁):000012050002

基礎番号の先頭が 0 で始まっている点に注意してください。Excel や CSV で扱うときに数値として読み込むと、この 0 が消えて桁が壊れます。番号は最初から最後まで文字列として扱うのが鉄則です(このミスは後半の「ハマりどころ」でもう一度出てきます)。

チェックデジットの計算式(国税庁の一次情報)

国税庁法人番号公表サイトが公開している「チェックデジットの計算」に沿って書きます。式はこれだけです。

検査用数字 = 9 −( Σ(n=1〜12)Pn × Qn を 9 で割った余り )

  • Pn:法人番号を構成する検査用数字以外の12桁の数字を、最下位の桁から順に1桁目、2桁目…12桁目としたときの、n桁目の数字
  • Qnn が奇数のとき 1、n が偶数のとき 2

言い換えると「最下位から数えて奇数番目の桁の合計」+「偶数番目の桁の合計 × 2」を9で割り、その余りを9から引くだけです。いわゆる モジュラス9・ウェイト1/2 の方式です。

法人番号のチェックデジット計算の流れ:基礎番号に重み1・2を掛けた合計11を9で割った余り2、9から引いて検査用数字7になる図

手で1回だけ計算してみる

実装する前に一度手で計算しておくと、コードのバグに気づけます。基礎番号 000012050002 を最下位から見ていきます。

最下位からの位置 n数字 Pn重み Qn
1212
2020
3010
4020
5515
6020
7212
8122
9〜1200

合計は 11。11 ÷ 9 の余りは 2。9 − 2 = 7 で、先頭の検査用数字 7 と一致します。この番号は形式として整合が取れている、という判定になります。

JavaScript / TypeScript での実装

計算部分はそのまま素直に書けます。以下は私のサイトの /tools/invoice-check/ で実際に動いているコード(src/lib/invoice.ts)から抜き出したものです。

/**
 * 法人番号(13桁)の検査用数字を、下12桁の基礎番号から計算する。
 *   検査用数字 = 9 −( Σ(Pn × Qn) を 9 で割った余り )
 *     Pn:基礎番号の最下位を1桁目としたときの n桁目の数字
 *     Qn:n が奇数なら 1、偶数なら 2
 */
function computeCheckDigit(base12: string): number {
  let sum = 0;
  for (let i = 0; i < 12; i++) {
    const digit = Number(base12[i]);
    // base12[i] は左(上位)からの位置。最下位を 1 とする位置 n に直す
    const n = 12 - i;
    const weight = n % 2 === 1 ? 1 : 2; // 奇数桁=1 / 偶数桁=2
    sum += digit * weight;
  }
  return 9 - (sum % 9);
}

ここでやってはいけない実装をひとつ挙げます。9 - (sum % 9) の結果をさらに % 9 で丸める実装です。この式は余りが 0〜8 にしかならないため、戻り値は必ず 1〜9 になります。つまり検査用数字に 0 は登場しません。ところが % 9 を足すと、余りが0のときの正しい 9 が 0 に化けて、正しい番号を弾いてしまいます。クレジットカードの Luhn 式に引きずられて (10 - sum % 10) % 10 と書くのも、同じ理由で誤りです。

なお % 10 は結果を変えません(9 % 10 は 9 です)が、意図が伝わらなくなるので書かないほうがよいでしょう。

副産物として、法人番号(=法人の登録番号)では、先頭が0で始まる13桁は計算式の上でありえないことも分かります。「T0…」で始まる法人の番号を見かけたら、まず入力ミスを疑う材料になります。ただし後述のとおり、個人事業者などに採番される13桁は仕様が公表されていないため、同じことが言えるとは限りません。

入力の正規化(現場のデータは汚い)

実務で受け取る文字列は、きれいな T7000012050002 ばかりではありません。私が実装時に想定した(実務でよく見かける)入力には、こんなものがあります。

  • 全角で貼り付けられた番号(T7000…)
  • 小文字の t
  • ハイフン区切り(T7000-0120-50002
  • 前後の空白、セルからコピーしたときの改行
  • そもそも T が付いていない13桁だけの入力

なので、判定の前に正規化を挟みます。

/** 全角の英数字を半角へ変換する(A→A、0→0) */
function toHalfWidth(input: string): string {
  return input.replace(/[A-Za-z0-9]/g, (ch) =>
    String.fromCharCode(ch.charCodeAt(0) - 0xfee0),
  );
}

export interface CheckResult {
  normalized: string;
  ok: boolean;
  code: 'valid' | 'length' | 'nondigit' | 'checkdigit';
  message: string;
}

export function checkInvoiceNumber(raw: string): CheckResult {
  const trimmed = raw.trim();
  // 半角化 → 大文字化 → 先頭の T を除去 → 空白・ハイフン等の区切りを除去
  const cleaned = toHalfWidth(trimmed)
    .toUpperCase()
    .replace(/^T/, '')
    .replace(/[\s\-‐-―ー.]/g, '');

  if (!/^\d+$/.test(cleaned)) {
    return { normalized: trimmed, ok: false, code: 'nondigit',
      message: '数字以外の文字が含まれています(番号は「T+13桁の数字」です)。' };
  }
  if (cleaned.length !== 13) {
    return { normalized: trimmed, ok: false, code: 'length',
      message: `桁数が違います(13桁必要ですが ${cleaned.length}桁です)。` };
  }

  const expected = computeCheckDigit(cleaned.slice(1)); // 下12桁から計算
  const actual = Number(cleaned[0]);                    // 先頭1桁が検査用数字
  const normalized = `T${cleaned}`;

  if (expected !== actual) {
    return { normalized, ok: false, code: 'checkdigit',
      message: 'チェックディジットが一致しません(打ち間違いの可能性があります)。' };
  }
  return { normalized, ok: true, code: 'valid',
    message: '形式・チェックディジットともに正常です。' };
}

正規化で消している文字の中に (長音符) を入れているのが地味なポイントです。日本語入力のまま数字を打つと、ハイフンのつもりで長音符が入ることが本当にあります。半角ハイフンだけを想定していると、ここで弾かれます。

判定結果を「OK / NG」の2値ではなく code で返しているのにも理由があります。利用者に返すべき情報は「ダメでした」ではなく「桁が足りないのか、打ち間違いの疑いなのか」だからです。桁落ちならコピペのやり直し、チェックデジット不一致なら原本の読み直し、と次の行動が変わります。

検算に使える値

実装したら、必ず既知の値で検算してください。手で計算できるものを置いておきます。

  • T7000012050002(国税庁の法人番号)→ 合計11 → 余り2 → 9−2=7 → 先頭と一致
  • T1180301018771(トヨタ自動車の法人番号)→ 合計53 → 余り8 → 9−8=1 → 先頭と一致
  • T1234567890123 → 先頭の1と計算結果が一致しない(不一致の見本として使えます)
  • 1234567890(10桁)→ 桁数エラー

上2つは公表されている実在の法人番号なので、「自分の実装が国税庁の式と同じ答えを出すか」の確認に使えます。

チェックデジットの限界(ここを外すと誤判定します)

実装記事でいちばん大事なのはここです。チェックデジットは「打ち間違いの検出器」であって、「実在の証明」ではありません。

0と9の取り違えは、数学的に検出できない

式をもう一度見ます。合計を 9で割った余りしか使っていません。ということは、合計が9だけ増減する変更は、余りを変えません

数字を 0 から 9 に書き換えると、その桁の積は「重み1の位置なら +9」「重み2の位置なら +18」変わります。どちらも9の倍数なので、余りは変わらず、検査用数字も変わりません

実例です。先ほどの T7000012050002 の、右から3桁目の 09 に書き換えてみます。

  • 元:基礎番号 000012050002 → 合計 11 → 余り 2 → 検査用数字 7
  • 改:基礎番号 000012050902 → 合計 20 → 余り 2 → 検査用数字 7

T7000012050902 も、チェックデジットの判定は「OK」で通ります。つまり /tools/invoice-check/ も、この番号には緑のチェックを出します。それが正しい挙動です——形式は整合しているのですから。

チェックデジットでは0と9の取り違えを検出できない例:T7000012050002 と T7000012050902 はどちらも検査用数字が7になる比較図

一方で、基礎番号の中で隣り合う2桁を入れ替えてしまった場合(転置)は検出できます。隣接する桁には重み1と2が交互に掛かるので、a と b を入れ替えると合計が a − b だけ変わります。これが9の倍数になるのは a = b のときか、{0, 9} の組み合わせのときだけ。ここでもやはり0と9だけが例外です。

個人事業者に採番された13桁は、そもそも仕様が公表されていない

もうひとつ、正直に書いておきたいことがあります。

個人事業者などに採番される13桁について、チェックデジットの仕様を国税庁が公表している資料を、私は見つけられませんでした(2026年8月20日時点)。公表サイトに書かれているのは「マイナンバーは用いず、法人番号とも重複しない事業者ごとの番号」というところまでです。

実務では「法人番号と同じ式で整合する」という前提で実装されているケースが多く、私のツールも同じ式を全件に当てています。ただしそれは公表された仕様に基づく確証ではありません。だから /tools/invoice-check/ では、不一致の件数を「無効」ではなく「要確認」と表示しています。ラベル1つの違いですが、「ツールが無効と言ったから取引先を疑う」という誤用を防ぐための線引きです。

一次判定でできること・できないこと
  • できる:桁数の過不足、数字以外の混入、1桁の打ち間違い(0と9の取り違えを除く)、隣接2桁の入れ替え(同上)の検出
  • できない:0と9の取り違えの検出/その番号が実在するかの判定/失効・取消の判定/その事業者が本当に取引相手かの確認
  • したがって、一次判定は「国税庁に問い合わせる前のフィルタ」として使うのが正しい位置づけです(明らかな入力ミスを先に落として、通信の回数を減らす)

実在確認:国税庁の公表サイトと Web-API

ここからが二次判定です。公的な確認手段は国税庁の適格請求書発行事業者公表サイトで、システムから使う入口は大きく3つあります。

公表サイトの画面で検索

登録番号を入力して確認する方法。1件ずつなら最短。ただしこの検索機能をプログラムで叩くことは、利用規約で明確に禁止されています(次の警告を参照)

Web-API 機能

企業などのシステムから条件を指定してリクエストを送り、データを動的に生成して応答してもらう方式(REST・GET)。アプリケーションIDの発行申請が必要

公表情報ダウンロード

全件データ・差分データをファイルで取得して自社側に取り込む方式。大量件数を扱うならこちらが本命

Web-API の3つの機能と、使う前の手続き

国税庁の公表サイトによると、Web-API は令和3年10月からサービス提供されており、機能は次の3つです。

  1. 登録番号指定機能:「登録番号の指定」で条件を絞り込む
  2. 取得期間指定機能:「取得期間の指定」で更新差分情報を抽出する
  3. 登録番号と日付指定機能:「登録番号と日付の指定」で特定の情報を取得する

利用にあたって、公式ページに明記されている条件を押さえておきます。

  • アプリケーションIDが必要。ただし「アプリケーションIDの発行申請」について「発行費用は掛かりません」と明記されています
  • Web-APIの利用規約への同意が必要
  • 令和5年1月20日から、法人番号システムWeb-APIのアプリケーションIDを持っている人であっても、発行申請書を提出して国税庁の承認を受けていないと、インボイスWeb-APIは利用できなくなりました(ここは引っかかりやすいポイントです。「法人番号APIのIDがあるから流用できる」は成り立ちません)
  • 取得した情報をもとに公開サービスを作る場合、「このサービスは、国税庁適格請求書発行事業者公表システムのWeb-API機能を利用して取得した情報をもとに作成しているが、サービスの内容は国税庁によって保証されたものではない」旨の明示が求められます。読者がそのまま掲出する文言なので、原文どおりに書いてください(法人番号側は「国税庁法人番号システムの」となり、文言が異なります)

つまり、社内システムに組み込むにせよ公開サービスを作るにせよ、コードを書く前に申請と規約確認が要ります。ここを飛ばして実装だけ先に進めると、動かせないコードが手元に残ります。

リクエストの組み立て方

国税庁は検証環境を提供しており、そのページにリクエストURLの書式が掲載されています(2026年8月20日確認)。3機能それぞれのパスは次のとおりです。

登録番号指定      https://kensyo.invoice-kohyo.nta.go.jp/【バージョン】/num?id=【アプリケーションID】&【条件】
取得期間指定      https://kensyo.invoice-kohyo.nta.go.jp/【バージョン】/diff?id=【アプリケーションID】&【条件】
登録番号と日付指定 https://kensyo.invoice-kohyo.nta.go.jp/【バージョン】/valid?id=【アプリケーションID】&【条件】

パスが num / diff / valid に分かれていること、バージョンとアプリケーションIDをURLに含める構造であることが読み取れます。

一方で、本番環境のホスト名・【条件】に指定するパラメータ名・応答ファイル形式の指定値(コード)は、仕様書に定義されています。仕様書は公表サイトの「Web-API仕様書ダウンロード」から入手できる「適格請求書発行事業者公表システムWeb-API機能のリクエストの設定方法及び提供データの内容について(Ver.1.0)」です。

🔴 自動化する前に、必ず利用規約を読んでください。国税庁適格請求書発行事業者公表サイトの利用規約は、「当サイトの検索機能に対して、スクレイピングなど、プログラムを用いて公開している情報を取得する行為」と「上記のプログラム又は当該プログラムに関するソースコード等の公開」を、いずれも明文で禁止しています。違反した場合は「当サイトへのアクセスを制限することがあります」に加えて、「損害賠償請求等の法的な措置を講じる場合があります」とも書かれています。 これは技術ブログでコードを公開する側にも直接かかってきます。自動化したいなら、迂回策を探すのではなく Web-API か公表情報ダウンロードを使う——これが唯一の正解です。 出典:国税庁適格請求書発行事業者公表サイト「利用規約」 https://www.invoice-kohyo.nta.go.jp/terms-of-use.html

ここで大事なのは、これらの値を個人ブログからコピーしないことです。第三者記事に載っている「応答形式を指定するコード値」のようなものは、改訂で意味が変わっても記事は更新されません。仕様書は無料で配布されているので、必ず自分でダウンロードして確認してください。この記事でも、公式ページに書かれていない値は書きません。

そのうえで、実装として汎用的に書ける部分——URLの組み立て・件数分割・待機・再試行——を示します。

一括検証の骨格(Node.js)

以下は「数百件の登録番号を、上限件数ずつ分割してAPIに投げる」処理の骨格です。

⚠️ 注意:私はアプリケーションIDの発行申請をしていないため、このコードで国税庁の環境に実際にリクエストを送って動作を確認したわけではありません。ここで示すのは、URL組み立て・分割・スロットリング・再試行という通信の作法の部分です。BASE_URL VERSION RESPONSE_TYPE MAX_PER_REQUEST の値は、必ず仕様書で確認して埋めてください。

// invoice-batch.mjs — 登録番号の一括問い合わせ(骨格)
// ※ エンドポイント・パラメータ・応答形式の指定値は仕様書で確認して設定すること

import { checkInvoiceNumber } from './invoice.mjs'; // 前半で作った一次判定

const BASE_URL = 'https://kensyo.invoice-kohyo.nta.go.jp'; // 検証環境。本番は仕様書を参照
const VERSION = '【バージョン】';        // 公開されているのは Ver.1 のみ(公式ページに明記)。URLでの表記形式は仕様書で確認

// 以下は公式ページに記載が無い=仕様書で確認して埋めること。そのままでは動きません
const PARAM_NUMBER  = '【登録番号を指定するパラメータ名】';
const PARAM_TYPE    = '【応答形式を指定するパラメータ名】';
const NUMBER_JOINER = '【複数指定時の区切り文字】';
const APP_ID = process.env.NTA_APP_ID;  // アプリケーションIDは環境変数から
const RESPONSE_TYPE = '【応答形式のコード】'; // 仕様書で確認
const MAX_PER_REQUEST = 0;              // 🔴 仕様書で確認して設定すること。10件は「法人番号システムWeb-API」側の公式記載で、インボイス側の上限は非公開
if (!MAX_PER_REQUEST) throw new Error('1リクエストの件数上限を仕様書で確認して設定してください');

/** 配列を size 件ずつに分割する */
function chunk(list, size) {
  const out = [];
  for (let i = 0; i < list.length; i += size) out.push(list.slice(i, i + size));
  return out;
}

/** 登録番号指定(num)のURLを組み立てる */
function buildNumUrl(numbers) {
  const url = new URL(`${BASE_URL}/${VERSION}/num`);
  url.searchParams.set('id', APP_ID);              // ← 公式ページに記載があるのはこれだけ
  url.searchParams.set(PARAM_NUMBER, numbers.join(NUMBER_JOINER));
  url.searchParams.set(PARAM_TYPE, RESPONSE_TYPE);
  return url.toString();
}

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

/** 一時的な失敗(429・5xx)だけ指数バックオフで再試行する */
async function fetchWithRetry(url, retries = 3, baseDelay = 1000) {
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(url, { headers: { 'User-Agent': 'my-accounting-app/1.0' } });
    if (res.ok) return await res.text();
    const retriable = res.status === 429 || res.status >= 500;
    if (!retriable || attempt >= retries) {
      throw new Error(`request failed: ${res.status}`);
    }
    await sleep(baseDelay * 2 ** attempt); // 1秒 → 2秒 → 4秒
  }
}

export async function verifyAll(rawNumbers) {
  // 1) 事前に「形式+チェックデジット」で落とす(通信の無駄打ちを減らす)
  const targets = [...new Set(
    rawNumbers.map((n) => checkInvoiceNumber(n)).filter((r) => r.ok).map((r) => r.normalized),
  )];

  // 2) 上限件数ずつに分けて、間隔をあけながら順番に投げる
  const results = [];
  for (const group of chunk(targets, MAX_PER_REQUEST)) {
    const body = await fetchWithRetry(buildNumUrl(group));
    results.push(body);
    await sleep(1000); // 連続で叩かない
  }
  return results;
}

実務で効くのは、派手なところではなく次の4点です。

  • 問い合わせる前に一次判定で落とす:明らかな入力ミスを通信させない。100件のうち3件が桁落ちなら、その3件は API に投げる価値がありません
  • 重複を除く:同じ取引先の請求書が月に何枚もあれば、番号は当然重複します。Set に通すだけで件数が目に見えて減ります
  • 並列で投げないPromise.all で一気に流すのは、公的APIに対する作法として避けます。順番に、間隔をあけて。急ぐ場面ではないはずです
  • 再試行するのは一時的な失敗だけ:429(多すぎ)と5xx(サーバ側)は待って再試行、4xx(こちらの間違い)は即座に止める。パラメータを間違えたまま何度も投げるのが一番迷惑です

数千件あるなら「公表情報ダウンロード」を検討する

取引先マスタが数千件あるなら、そもそも API を叩き続ける設計が向きません。公表サイトには公表情報のダウンロード機能があり、次のファイルが提供されています(2026年8月20日確認)。

  • 全件データ:前月末日時点の最新情報。毎月初日(休日を除く)に作成され、翌日午前6時以降に公開
  • 差分データ:日次の更新情報(新規追加・取消・失効など)。原則として翌日午前6時以降に公開され、過去40日分が利用可能
  • ファイル形式:CSV・XML・JSON の3種類

「月初に全件を取り込み、日次で差分を当てて自社マスタを更新する」構成にすれば、照合はすべて自社DBの中で完結します。API のレート制限も気にしなくて済みます。

ただし注意が1つあります。公表サイトのダウンロードページには、全件データおよび差分データについて「氏名等の一部項目について値を削除して提供」している旨が記載されています。画面で見える情報とダウンロードデータの内容は同じではありません。取得できる項目の正確な定義は、公表サイトのリソース定義書で確認してください(この記事では推測で項目を列挙しません)。

法人番号システム Web-API との違い

紛らわしいのですが、法人番号システムWeb-API は別のサービスです。こちらは法人番号公表サイト側の API で、公式ページには次のように書かれています。

  • アプリケーションIDが必要(発行費用は掛からない)
  • 機能は「法人番号を指定して情報を取得」「取得期間を指定して情報を取得」「法人名を指定して情報を取得(Ver.2.0以上)」
  • 法人番号は最大10件までまとめて指定できる
  • バージョンは Ver.1.0 / 2.0(英語表記)/3.0(フリガナ)/4.0(検索対象除外法人情報)と拡張されてきた

法人名から法人番号を引きたい(=取引先名しか分からない)ならこちらが使えます。ただし前述のとおり、このIDでインボイスWeb-APIは使えません。「取引先が適格請求書発行事業者として登録されているか」を確認したいなら、インボイス側の申請が必要です。

自作ツール /tools/invoice-check/ では、あえて通信していません

最後に、自分のツールの設計判断を書いておきます。ここは他所には書いていない実装ノートです。

インボイス番号 一括チェッカー は、API を一切呼びません。番号を貼り付けると、ブラウザの中だけで形式とチェックデジットを判定し、結果を出します。理由は3つです。

  1. 取引先の登録番号を外部に送りたくない。番号自体は公表情報ですが、「どこの誰が、どの取引先を、いつ調べたか」という情報は利用者のものです。サーバーに送らなければ、預からずに済みます
  2. アプリケーションIDの規約と運用が乗る。公開サービスで API を使うなら、申請・規約・免責表示・障害時の挙動まで面倒を見る必要があります。「打ち間違いを見つける」という目的に対して重すぎます
  3. 速い。100件貼り付けても体感で待ち時間なく処理でき、通信障害もレート制限もありません

その代わり、ツールの画面には「本ツールが確認するのは形式とチェックディジットだけで、実際に登録されているかは判定できません」と明記し、形式OKの各行から国税庁の公表サイトへ直接飛べるリンクを置いています。これで「一次判定はツール、二次判定は国税庁」という2段構えを、利用者側でもそのまま取れるようにしています。

自分でシステムに組み込む場合も、この線引きはそのまま使えます。入力欄のバリデーション=チェックデジット、支払い前の確定処理=API または取り込んだ公表データ、という役割分担です。

経理フローへの組み込みと、そもそも自作するかどうか

実装の話をひととおり書いたうえで、身も蓋もないことを書きます。この検証を自分で実装する必要があるのは、既存の会計ソフトに載っていない業務がある場合だけです。

私の場合は「自分のサイトに無料ツールとして置く」という目的があったので実装しましたが、受け取った請求書の処理そのものが目的なら、インボイス制度に対応した会計ソフトの機能を使うほうが早いです。帳簿付けや請求書の保存までを一つの流れで扱える製品が多くあります(対応範囲は製品・プランによって異なるので、公式サイトの仕様でご確認ください。保存要件や税務上の取り扱いそのものは制度の話なので、詳しくは国税庁の情報や税理士にご確認ください)。なお会計ソフトは複数あり、ここで紹介するのは当サイトが提携している1社です。

自作する/しないの判断材料としては、こんなところでしょうか。

  • 自作が向く:自社の基幹システムに組み込みたい/独自の受発注システムがある/マスタ登録時のバリデーションとして使いたい
  • ソフトに任せるのが向く:請求書の受領・記帳・申告までの一連の業務が目的/自分ひとりの事業でシステム開発の工数を割きたくない

【PR】以下は freee会計の広告リンクです。 料金・機能・対応範囲は変わります。申し込み前に公式サイトで最新の内容をご確認ください。

なお、開発したツールを動かすサーバー代や、会計ソフトの利用料をどの勘定科目で処理するかは別記事にまとめています。

「そもそも自分は青色申告とインボイスをどう組み合わせるのが良いのか」を整理したい場合は、青色申告・インボイス最適解診断で条件を入れて確認してみてください(診断結果は一般的な整理であり、税務上の判断は税理士・国税庁の領域です)。

まとめ

  • 登録番号は T + 13桁。法人は法人番号がそのまま入り、個人事業者などには法人番号と重複しない13桁が採番される(マイナンバーは用いない)
  • 13桁の内訳は 検査用数字1桁+基礎番号12桁。検査用数字は 9 −(下12桁に重み1・2を掛けた合計 ÷ 9 の余り) で計算でき、実装は10行程度
  • 9 - (sum % 9)さらに % 9 で丸めない。この式の戻り値は1〜9で、% 9 を足すと正しい9が0に化ける
  • 0と9の取り違えは検出できない(合計が9増減しても余りが変わらないため)。T7000012050002 と T7000012050902 はどちらも通ります
  • 個人事業者に採番された13桁のチェックデジット仕様は公表資料が見当たらない。不一致は「無効」ではなく「要確認」として扱うのが安全
  • 実在確認は 国税庁の公表サイト/Web-API/公表情報ダウンロード。Web-API はアプリケーションIDの申請が必要で、法人番号Web-APIのIDでは使えない
  • 数千件規模なら 全件データ+日次差分の取り込みが素直。ただしダウンロードデータは氏名等の一部項目が削除されている
  • 一括処理の作法は「先に一次判定で落とす/重複を除く/並列で投げない/再試行は一時的な失敗だけ

コード自体は難しくありません。難しいのは「どこまでが計算で分かり、どこからが国税庁に聞かないと分からないのか」の線引きのほうです。そこさえ間違えなければ、この仕組みは日々の請求書チェックをかなり楽にしてくれます。

チェックデジットが一致すれば、その登録番号は有効ですか?

いいえ。一致して分かるのは「番号の形式が計算式と整合している」ことだけで、その番号が実際に登録されているかどうかは判定できません。登録の取消や失効もありますし、計算式を満たすだけの架空の番号を作ることもできます(本文で実例を示したとおり、0と9を取り違えた番号も同じ検査用数字になります)。実在の確認は、国税庁の適格請求書発行事業者公表サイト、または Web-API・公表情報ダウンロードで行ってください。

個人事業主の登録番号もチェックデジットで検証できますか?

確証はありません。 国税庁の公表サイトに書かれているのは「13桁の数字には、マイナンバー(個人番号)は用いず、法人番号とも重複しない事業者ごとの番号」というところまでで、個人事業者などに採番される13桁のチェックデジット仕様を公表した資料は、2026年8月20日時点で見つけられませんでした。実務では法人番号と同じ計算式を当てている実装が多く、当サイトのツールも同様ですが、不一致だった場合に「無効」と断定はできません。当サイトでは「要確認」と表示し、国税庁の公表サイトでの確認を案内しています。

国税庁の Web-API は無料で使えますか?

国税庁の公表サイトには、アプリケーションIDの発行申請について「発行費用は掛かりません」と明記されています。ただし利用にはアプリケーションIDの発行申請と利用規約への同意が必要で、令和5年1月20日以降は、法人番号システムWeb-APIのアプリケーションIDを持っている場合でも、インボイスWeb-API用に別途申請して国税庁の承認を受ける必要があります。最新の手続きは国税庁の公式ページで確認してください。

数千件の登録番号を一括で確認したいときは、どうするのが良いですか?

Web-API に大量のリクエストを送り続けるより、公表サイトの公表情報ダウンロード機能(全件データ+日次の差分データ/CSV・XML・JSON)を自社側に取り込み、照合を自社DBの中で行う設計のほうが素直です。全件データは前月末日時点の情報が毎月初日に作成され、差分データは過去40日分が利用できます。ただしダウンロードデータは氏名等の一部項目について値を削除して提供されているため、必要な項目が含まれるかを公表サイトのリソース定義書で先に確認してください。

出典

いずれも 2026年8月20日に確認しました。仕様書・利用手続は改訂されるため、実装前に必ず最新版を確認してください。

  • 国税庁 適格請求書発行事業者公表サイト「登録番号とは」(登録番号の構成/法人はT+法人番号13桁/個人事業者などはT+数字13桁/マイナンバーは用いず法人番号とも重複しない):https://www.invoice-kohyo.nta.go.jp/about-toroku/index.html
  • 国税庁 適格請求書発行事業者公表サイト(実在確認の公的な入口):https://www.invoice-kohyo.nta.go.jp/
  • 国税庁法人番号公表サイト「チェックデジットの計算」(検査用数字の計算式と計算例。最下位から奇数桁の和+偶数桁の和×2 を9で割り、余りを9から引く):https://www.houjin-bangou.nta.go.jp/documents/checkdigit.pdf
  • 法人番号の指定等に関する省令(法人番号関係抜粋。PnQn の記法はこちらが出典):https://www.houjin-bangou.nta.go.jp/pc/setsumei/images/bangouhou_syorei.pdf
  • 国税庁適格請求書発行事業者公表サイト「利用規約」(スクレイピング禁止・公表項目に登録取消年月日/登録失効年月日を含む):https://www.invoice-kohyo.nta.go.jp/terms-of-use.html
  • 国税庁 適格請求書発行事業者公表サイト「Web-API機能」(令和3年10月提供開始/3機能/アプリケーションIDの必要性と発行費用が掛からない旨/利用規約への同意/令和5年1月20日以降は法人番号Web-APIのID保有者も別途申請が必要/公開サービスでの明示事項):https://www.invoice-kohyo.nta.go.jp/web-api/index.html
  • 国税庁 適格請求書発行事業者公表サイト「Web-API仕様書ダウンロード」(適格請求書発行事業者公表システムWeb-API機能のリクエストの設定方法及び提供データの内容について Ver.1.0):https://www.invoice-kohyo.nta.go.jp/web-api/web-api-download.html
  • 国税庁 適格請求書発行事業者公表サイト「Web-API検証環境の提供について」(num/diff/valid のリクエストURL書式):https://www.invoice-kohyo.nta.go.jp/web-api/kensyou.html
  • 国税庁 適格請求書発行事業者公表サイト「公表情報ダウンロード」(全件データ・差分データ/CSV・XML・JSON/公開スケジュール/過去40日分/氏名等の一部項目を削除して提供):https://www.invoice-kohyo.nta.go.jp/download/index.html
  • 国税庁法人番号公表サイト「法人番号システムWeb-API」(アプリケーションIDの必要性と発行費用/3機能/法人番号は最大10件までまとめて指定できる/バージョン):https://www.houjin-bangou.nta.go.jp/webapi/index.html
  • 国税庁 タックスアンサー(税務上の取り扱いに関する一次情報):https://www.nta.go.jp/taxes/shiraberu/taxanswer/index2.htm

最終更新:2026年8月20日

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コスト最小で制作をしたいという意識強め(笑)

目次