---
title: "JP-Verify Invoice Facts — one invoice's register, statutory-item, arithmetic and schedule facts (JSON)"
method: POST
path: "/v1/invoice/check"
tags: ["Compliance"]
---

# JP-Verify Invoice Facts — one invoice's register, statutory-item, arithmetic and schedule facts (JSON)

`POST /v1/invoice/check`

## Request

- Base URL: `https://jp-verify.obolpay.xyz`
- URL: `https://jp-verify.obolpay.xyz/v1/invoice/check`
- Auth: one of:
  - none
  - API key in header `X-API-Key`

Check ONE invoice from its facts (see ``InvoiceCheckRequest``). What is checked: the
issuer's 登録番号 against the NTA register — well-formed (REG-01), present (REG-02) and
registered on the transaction date / period (REG-03, evaluated against every registration
episode the NTA publishes for the number once the mirror's history table is complete —
``status_on_date.episode_scope`` says which); the statutory items of 消費税法57条の4 as
presence checks (ITEM-01..06);
the printed rates (RATE-01..03); arithmetic on the document's own figures (ARITH-01..05 —
per-rate tax within one-yen rounding, sums, totals); plus the published
transitional-deduction schedule tier for the evaluation date with its source URLs, and the
register/document-name comparison (``name_match``, never a verdict). Every rule carries a
status (``pass`` / ``fail`` / ``unknown`` / ``not_applicable``), a detail and a source id;
``rule_set_version`` names the rule set (catalog: GET /v1/invoice/rules).

**NOT tax advice**: register facts, document checks and the published schedule only; no
determination of any deduction, credit or entitlement — the buyer's consumption-tax
treatment is for the taxpayer and their 税理士. No buyer-side input is accepted.

Free refusal (400, nothing charged) for request-level defects only: not an object, missing
or malformed ``issue_date``, both ``transaction_date`` and ``transaction_period``, a bad
``document_type`` / ``category`` / ``amount_basis`` / ``currency``, more than 10
``tax_lines``, a non-numeric amount (negative amounts are accepted on every document type
and reported as ``document.amount_sign``), ``return_date`` on a document type other than
``return_invoice`` (適格返還請求書 — declared by the caller, never inferred), an over-long name, a
``supplier_t_number`` that is not number-shaped (longer than 32 characters) or a string
that cannot be UTF-8 encoded. A missing or malformed 登録番号 is a document finding and is
metered — reported as a finding WITHOUT its text (``document.supplier_t_number`` is null,
``document.supplier_t_number_state`` says ``malformed``). Metered 1 unit per document on
every tier. ``"sign": true`` returns an Ed25519-signed record with a sibling compact
``jws`` (Growth / Reseller keys; other tiers get ``signed_record: null`` and a note).
Opt-in ``Idempotency-Key`` request header: a retry with the same key + body replays the
first response (``Idempotent-Replayed: true``) instead of being re-metered. Names and
amounts are consumed in memory only — never stored, logged or echoed; the digest carries
no name.

## Headers

- `X-API-Key` string

## Request body

- object: ``POST /v1/invoice/check`` body — the facts of ONE invoice, as printed. Names and amounts are consumed in memory only and never stored, logged or echoed. A missing or malformed ``supplier_t_number`` is a document finding (metered), not a request error.
  - `document_type` string, nullable: qualified_invoice (適格請求書, default) | simplified_qualified_invoice (適格簡易請求書) | return_invoice (適格返還請求書 — 'credit note' in Peppol/UBL vocabulary; JP PINT models it as a negative Invoice (380)) — as claimed by the caller, never inferred from the sign of the amounts; industry eligibility is not checked
  - `supplier_t_number` string, nullable: the 登録番号 AS PRINTED (NFKC-folded, whitespace removed); absent = the document shows no number; a malformed value is a metered finding reported WITHOUT its text; longer than 32 characters (not number-shaped) or not UTF-8 encodable = free 400
  - `seller_name` string, nullable: issuer name as printed (<= 200 chars after NFKC/strip); compared with the register name, never echoed
  - `buyer_name` string, nullable: recipient name as printed; only its presence is used, never echoed
  - `buyer_name_present` boolean, nullable: alternative to buyer_name: whether the recipient's name is printed
  - `issue_date` string, required: REQUIRED — the date printed on the document ('YYYY-MM-DD', ibt-002)
  - `transaction_date` string, nullable: 課税資産の譲渡等を行った年月日 (goods: delivery; services: completion) — the evaluation date; mutually exclusive with transaction_period. On a return_invoice: the ORIGINAL supply (57条の4③二's second date), which is the register date of record (基通1-8-18/1-8-19)
  - `transaction_period` object, nullable: ``transaction_period`` for ``POST /v1/invoice/check`` (まとめ請求 — 一定の期間).
    - `start` string, required: 'YYYY-MM-DD' — evaluated as one of the two dates
    - `end` string, required: 'YYYY-MM-DD' (>= start) — evaluated as the other date
  - `return_date` string, nullable: return_invoice only — 売上げに係る対価の返還等を行う年月日 (57条の4③二's first date), 'YYYY-MM-DD'; optional (ITEM-02 reports unknown without it); informational for the register status (基通1-8-19); a free 400 on any other document_type
  - `preceding_invoice_reference_present` boolean, nullable: return_invoice — a reference to the original invoice is printed (presence only; the reference itself is never sent)
  - `currency` string, nullable: ISO 4217 (default JPY)
  - `description_present` boolean, nullable: 資産又は役務の内容 is stated (null = not supplied)
  - `reduced_rate_marked` boolean, nullable: 軽減対象である旨 is marked, in any form per 基通1-8-4 (null = not supplied)
  - `rate_only_stated` boolean, nullable: 適格簡易請求書 printing 適用税率 but no 消費税額等
  - `tax_lines` object[], nullable: 0..10 entries, one per rate/category on the document
    - `rate_percent` union: 適用税率 in percent (10, 8, or 0); null when the document prints none
      - integer
      - number
      - string
    - `category` string, nullable: standard | reduced | old_rate_8 | exempt | out_of_scope | export | unknown (8% alone does not say which 8% — supply reduced or old_rate_8)
    - `amount_basis` string, nullable: tax_exclusive (税抜) | tax_inclusive (税込) — which figure `amount` is
    - `amount` union: 税率ごとに区分した合計額 for this rate/category (signed)
      - integer
      - number
      - string
    - `tax_amount` union: 消費税額等 for this rate/category (yen, whole; signed)
      - integer
      - number
      - string
    - `tax_amount_jpy` union: the 消費税額等 in yen for this rate/category on a non-JPY document (基通1-8-16 / 問68: the statutory figure is the yen amount; a foreign-currency tax_amount alone is 参考) — ignored when currency is JPY
      - integer
      - number
      - string
  - `totals` object, nullable: ``totals`` for ``POST /v1/invoice/check`` — every key optional.
    - `tax_exclusive_total` union: 税抜合計
      - integer
      - number
      - string
    - `tax_total` union: 消費税額等の合計
      - integer
      - number
      - string
    - `tax_inclusive_total` union: 税込合計
      - integer
      - number
      - string
    - `payable_amount` union: 請求金額 (not reconciled — prepaid/rounding amounts legitimately differ)
      - integer
      - number
      - string
  - `sign` boolean, nullable: return an Ed25519-signed record (Growth/Reseller keys only; otherwise the response says so and signs nothing)

## Response `200`

One document's register facts, document checks, published schedule tier and limitations — every rule with a status and a source; never a verdict. Two real responses on the sample register: a registered issuer, and a malformed 登録番号 reported as a finding whose `register` record is `invalid` with every key present (null) and the printed text never echoed.

- unknown

## Other responses

- `400`: Malformed input — refused before metering; nothing was charged.
- `401`: Unknown, inactive, or expired API key.
- `413`: Request body over the size cap — refused before it was buffered or parsed; nothing was charged.
- `422`: Validation Error
- `429`: Quota exceeded for the caller's tier.
- `503`: The register, or an optional feature, is unavailable or not configured on this deployment. A register 503 (since 1.4.1) also carries the mirror's `data_as_of` with the source fields — `source_latest_diff_date` (the newest 差分 the NTA 公表サイト listed when the sync last read it), `source_checked_at`, `source_gap_business_days` and `freshness.rule` (`stale` here) — so a caller can tell a mirror that is behind its source (`data_date` older than `source_latest_diff_date`) from a source that has not published (equal, but `source_checked_at` older than `freshness.source_check_max_hours`); `data_as_of` is null when the mirror is absent. Nothing was charged.

---

[API](https://skmtc.dev/obolpay/apis/jp-verify.md) · [All operations](https://skmtc.dev/obolpay/apis/jp-verify/llms.txt) · [OpenAPI document](https://skmtc.dev/obolpay/apis/jp-verify/revisions/bf8851690df0?raw)
