APIリファレンス · v1
APIドキュメント
予約1件につき1回の呼び出しで、各泊をその日の規則で課税します。泊ごとの料金・人数・課税主体別の内訳まで、JSONで返します。
- ベースURL:
https://yadozei.jp/v1 - JSON
- CORS対応
- 全国66エリア
- データ 2026.10
- 日付は日本時間
- 料金は1泊ごと・税抜
目次
クイックスタート
キーなしで始められます
APIキーがなくても、IPアドレスごとに1日100回・毎分10回まで呼び出せます(
POST /v1/resolve、GET /v1/dataを除く)。キーなしの呼び出しにもAPIキーでの利用にも利用規約が適用され、契約内容となります。
最初のリクエスト
東京都で1人1泊¥15,000(税抜)、2泊・2名の場合:
cURLcurl -X POST https://yadozei.jp/v1/calculate \ -H 'content-type: application/json' \ -d '{"areaId":"tokyo","ratePerNight":15000,"date":"2026-12-01","nights":2,"guests":2}'JavaScriptconst res = await fetch("https://yadozei.jp/v1/calculate", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ "areaId": "tokyo", "ratePerNight": 15000, "date": "2026-12-01", "nights": 2, "guests": 2 }), }); const data = await res.json(); if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);Pythonimport requests res = requests.post( "https://yadozei.jp/v1/calculate", json={"areaId": "tokyo", "ratePerNight": 15000, "date": "2026-12-01", "nights": 2, "guests": 2}, timeout=10, ) data = res.json() if not res.ok: raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}"){ "areaId": "tokyo", "areaName": { "en": "Tokyo", "ja": "東京都" }, "currency": "JPY", "dateUsed": "2026-12-01", "basis": "per_person", "perNightTax": 200, "breakdown": [ { "authority": { "en": "Tokyo Metropolitan Government", "ja": "東京都" }, "amount": 200, "type": "fixed" } ], "nights": 2, "guests": 2, "nightly": [ { "date": "2026-12-01", "ratePerNight": 15000, "perNightTax": 200, "breakdown": [ { "authority": { "en": "Tokyo Metropolitan Government", "ja": "東京都" }, "amount": 200, "type": "fixed" } ] }, { "date": "2026-12-02", "ratePerNight": 15000, "perNightTax": 200, "breakdown": [ { "authority": { "en": "Tokyo Metropolitan Government", "ja": "東京都" }, "amount": 200, "type": "fixed" } ] } ], "stayTotal": { "perPerson": 400, "total": 800, "breakdown": [ { "authority": { "en": "Tokyo Metropolitan Government", "ja": "東京都" }, "amount": 800, "type": "fixed" } ] } }宿泊全体の税額は
stayTotal.total(この例では¥800)です。APIキーを取得する
本番ではAPIキーをお使いください。お問い合わせから、システム名と月間の想定リクエスト数をお知らせください。お見積りのうえ、キー(
yz_…)を発行します。キーはX-API-Keyヘッダで送ります。
APIが扱わないこと
- 免税・課税免除(修学旅行など)は自動では適用されません。対象の方は guests から除くか、別に計算してください。
- 料金の異なる宿泊者や、途中で人数が変わる宿泊は、条件ごとに分けて呼び出してください。
- 本結果は参考情報であり税務助言ではありません。最終的な金額は各自治体の公式情報をご確認ください。
試してみる
本番のAPIに実際にリクエストを送ります。キーは不要です。
curl -X POST https://yadozei.jp/v1/calculate \
-H 'content-type: application/json' \
-d '{"areaId":"tokyo","ratePerNight":15000,"nights":2,"guests":2}'const res = await fetch("https://yadozei.jp/v1/calculate", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
"areaId": "tokyo",
"ratePerNight": 15000,
"nights": 2,
"guests": 2
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import requests
res = requests.post(
"https://yadozei.jp/v1/calculate",
json={"areaId": "tokyo", "ratePerNight": 15000, "nights": 2, "guests": 2},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")「リクエストを送信」を押すと、ここにAPIの応答が表示されます。
認証
APIキーは X-API-Key ヘッダで送ります。キーは yz_ で始まり、発行時に一度だけ表示されます。
curl https://yadozei.jp/v1/areas/tokyo \
-H "x-api-key: $YADOZEI_API_KEY"const res = await fetch("https://yadozei.jp/v1/areas/tokyo", {
headers: { "x-api-key": process.env.YADOZEI_API_KEY },
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import os
import requests
res = requests.get(
"https://yadozei.jp/v1/areas/tokyo",
headers={"x-api-key": os.environ["YADOZEI_API_KEY"]},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")キーはサーバー側で保管してください。 ブラウザやモバイルアプリに埋め込まないでください。CORSは開いていますが、公開されたキーは誰でもあなたの枠で使えてしまいます。
- 存在しない・失効したキーは
401 unauthorizedです。匿名の枠に切り替わることはありません。 - 誤ったキーを繰り返し送ると、IPごとに毎分10回を超えた時点で
429になります。 - プランと料金は料金ページをご覧ください。
レート制限
| プラン | 毎分 | 枠 | リセット |
|---|---|---|---|
| 匿名(キーなし・IPごと、IPv6は/64単位) | 10 | 1日 100回 | 毎日 0:00(日本時間) |
| Standard | 30 | 月 10,000回 | 毎月1日 0:00(日本時間) |
| Pro | 60 | 月 100,000回 | 毎月1日 0:00(日本時間) |
| Vendor | 60 | 月 1,000,000回 | 毎月1日 0:00(日本時間) |
- 枠は
/v1の全エンドポイントで共通です。POST /v1/resolve、GET /v1/dataは有料プラン限定です。 POST /v1/resolveは、住所の件数によらず1回の呼び出しを1リクエストと数えます。- 毎分の上限は時計の1分ごとにリセットされます。
- キーの確認を通ったリクエストは、検証エラー(400)になったものも含めてすべて数えます。1日・1か月の枠を超えて断られたリクエストも数えます(毎分の上限で断られたものは数えません)。
- 枠を超えたキーは、リセットまで 429 になります。
Retry-Afterとerror.retryAfterは、最初に当たった上限がリセットされるまでの秒数です。待って再試行しても 429 なら、より長い枠を使い切っています。その応答の値に従ってください。
残りの枠を知る
キーの確認を通った応答(成功と、その後の 400・404・413)には、次のヘッダが付きます。キーなしは今日の枠、キーありは今月の枠です。毎分の上限はここには含まれません(超えると 429 と Retry-After)。
| ヘッダ | 意味 |
|---|---|
X-RateLimit-Limit | 枠の上限。キーなしは1日、キーありは1か月の回数。 |
X-RateLimit-Remaining | この呼び出しを数えたあとの残り回数。 |
X-RateLimit-Reset | 枠がリセットされるまでの秒数(日本時間の0時、またはキーありは月初)。 |
エラー
エラーは共通の形式で返ります。error.code で分岐してください(message は人が読むためのものです)。
{
"error": {
"code": "unknown_area",
"message": "Unknown area: Kyoto",
"suggestions": [
"kyoto"
]
}
}| ステータス | コード | 発生条件 | 対処 |
|---|---|---|---|
| 400 | invalid_json | 本文が正しいJSONではない | content-type: application/json で、正しいJSONの本文を送ってください。 |
| 400 | validation_error | 本文またはクエリが検証に失敗した(message に最初の問題を記載) | パラメータ表の型と範囲を確認してください。未定義のキーと null は受け付けません。 |
| 401 | unauthorized | X-API-Key が存在しない、または失効している | キーを確認してください。匿名の枠に切り替わることはありません。 |
| 403 | forbidden | 有料プランのキーが必要なエンドポイント | 有料プランのキーを X-API-Key で送ってください。 |
| 404 | unknown_area | エリアIDが見つからない | suggestions(最大3件の候補ID)か GET /v1/areas から正しいIDを選んでください。 |
| 413 | payload_too_large | 本文が上限を超えている(/v1/calculate は 4KB、/v1/resolve は 128KB) | 余分なキーを除いてください(365泊分の nightlyRates は収まります)。/v1/resolve の住所は、複数の呼び出しに分けてください。 |
| 429 | rate_limited | 毎分の上限、または1日・1か月の枠を超えた | Retry-After(秒)待ってから再試行してください。再び 429 なら、より長い枠を使い切っています。 |
| 503 | unhealthy | /healthz のみ:データベースに書き込めない | 一時的な障害です。少し時間をおいて確認してください。 |
上の表以外の応答
- CORSのプリフライト(
OPTIONS)は204を返します。 - 対応していないメソッドは、本文なしの
405です。 - 想定外の障害では、JSONでない
500が返ることがあります。間隔を空けて再試行してください。 X-Data-Versionヘッダは、APIのJSON応答に付きます(これらの応答には付きません)。
データバージョンと変更フィード
すべてのJSON応答に X-Data-Version ヘッダが付き、使ったデータのバージョンがわかります(ブラウザの fetch からも読めます)。規則には施行日があり、施行予定の規則もデータに含まれるため、将来の日付はその日に適用される規則で計算されます。
変更の同期(APIキーが必要)
- 処理済みの最大の
seqを保存します(最初は 0)。 - APIキー付きで
GET /v1/changes?since_seq=<seq>を呼びます。seqがそれより大きい変更が古い順にすべて返ります。 - 各変更の
areaIdsをGET /v1/areas/{id}(有料プランなら/v1/data)で取り直してから、そのseqを保存します。
匿名の呼び出しは、条件に合う変更のうち最新5件だけを返します(プレビュー用)。これで同期すると変更を取りこぼします。
メールで受け取りたい方は、改定アラートにご登録ください。
エンドポイント
1件の宿泊の宿泊税を計算します。各泊をその泊の日付の規則で課税し、泊ごとの結果、宿泊全体の合計、課税主体(県・市町村)別の内訳を返します。
パラメータ
| 名前 | 型 | 必須 | 説明 |
|---|---|---|---|
X-API-Keyheader | string | 任意 | APIキー。省略すると匿名(IPごとの無料枠)で処理されます。 |
areaIdbody | string | 必須 | エリアID(GET /v1/areas で取得。例:tokyo、kyoto、onna)。存在しないIDは 404 unknown_area(候補付き)。 |
ratePerNightbody | integer | いずれか | 1泊あたりの課税対象料金(円・消費税抜き)。1人あたり(適用される課税単位が per_unit の場合は1室/1棟あたり)の、素泊まり・サービス料込みの金額で、全泊にこの料金を使います。税込の金額は送らないでください。 |
nightlyRatesbody | integer[] | いずれか | 泊ごとの料金(円・消費税抜き、ratePerNight と同じ単位)の配列。nightlyRates[0] がチェックイン日(date)の泊、nightlyRates[i] が date + i 日の泊で、泊数は配列の長さです。各泊は個別に課税されるため、平均せず実際の料金を送ってください。 |
datebody | string (YYYY-MM-DD) | 任意 | チェックイン日(1泊目)。YYYY-MM-DD。 |
nightsbody | integer | 任意 | 泊数。nightlyRates と一緒に送る場合は、配列の長さと一致させてください。 |
guestsbody | integer | 任意 | 宿泊人数。適用される課税単位が per_person の場合、合計に掛けます。 |
basisbody | string | 任意 | 課税単位の指定。variable の地域(「課税単位」を参照)でのみ使われ、ほかの地域では無視されます。 |
未定義のキーは受け付けません。任意の項目は省略できますが、null は送れません。本文は4KBまでです。
リクエスト
curl -X POST https://yadozei.jp/v1/calculate \
-H 'content-type: application/json' \
-d '{"areaId":"tokyo","ratePerNight":15000,"date":"2026-12-01","nights":2,"guests":2}'const res = await fetch("https://yadozei.jp/v1/calculate", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
"areaId": "tokyo",
"ratePerNight": 15000,
"date": "2026-12-01",
"nights": 2,
"guests": 2
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import requests
res = requests.post(
"https://yadozei.jp/v1/calculate",
json={"areaId": "tokyo", "ratePerNight": 15000, "date": "2026-12-01", "nights": 2, "guests": 2},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"areaId": "tokyo",
"areaName": {
"en": "Tokyo",
"ja": "東京都"
},
"currency": "JPY",
"dateUsed": "2026-12-01",
"basis": "per_person",
"perNightTax": 200,
"breakdown": [
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"amount": 200,
"type": "fixed"
}
],
"nights": 2,
"guests": 2,
"nightly": [
{
"date": "2026-12-01",
"ratePerNight": 15000,
"perNightTax": 200,
"breakdown": [
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"amount": 200,
"type": "fixed"
}
]
},
{
"date": "2026-12-02",
"ratePerNight": 15000,
"perNightTax": 200,
"breakdown": [
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"amount": 200,
"type": "fixed"
}
]
}
],
"stayTotal": {
"perPerson": 400,
"total": 800,
"breakdown": [
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"amount": 800,
"type": "fixed"
}
]
}
}レスポンスの項目
| 項目 | 型 | 説明 |
|---|---|---|
areaId | string | 計算したエリアのID。 |
areaName | { en, ja } | エリア名(英語・日本語)。 |
currency | "JPY" | 常に JPY。 |
dateUsed | YYYY-MM-DD | チェックイン日(送った date。省略時は日本時間の今日)。 |
basis | "per_person" | "per_unit" | 適用された課税単位。per_unit の場合、金額は1室/1棟あたりです。 |
nights | integer | 泊数。 |
guests | integer | 人数。 |
nightly[] | array | 泊ごとの結果:date(その泊の日付)、ratePerNight(その泊の税抜料金)、perNightTax(1人または1単位あたり)、breakdown(課税主体別)。 |
stayTotal.perPerson | integer | 全泊の合計(1人あたり。per_unit の場合は1単位あたり)。 |
stayTotal.total | integer | 請求する合計額。per_person の場合は人数を掛けた額です。 |
stayTotal.breakdown[] | array | 課税主体(県・市町村)ごとの宿泊全体の合計で、total と一致します。type は最後の泊の規則の方式です。泊ごとの方式は nightly[].breakdown を見てください。 |
perNightTax, breakdown | compat | 互換用:1泊目の値のみ。宿泊全体には stayTotal を使ってください。 |
エラー: invalid_jsonvalidation_errorunauthorizedunknown_areapayload_too_largerate_limited
対応している全エリアの一覧(ID、名称、都道府県、行政区分、課税単位)を返します。
パラメータ
| 名前 | 型 | 必須 | 説明 |
|---|---|---|---|
X-API-Keyheader | string | 任意 | APIキー。省略すると匿名(IPごとの無料枠)で処理されます。 |
リクエスト
curl https://yadozei.jp/v1/areasconst res = await fetch("https://yadozei.jp/v1/areas");
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import requests
res = requests.get(
"https://yadozei.jp/v1/areas",
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"areas": [
{
"id": "tokyo",
"name": {
"en": "Tokyo",
"ja": "東京都"
},
"prefecture": {
"en": "Tokyo",
"ja": "東京都"
},
"level": "prefecture",
"taxBase": "per_person"
},
{
"id": "osaka",
"name": {
"en": "Osaka",
"ja": "大阪府"
},
"prefecture": {
"en": "Osaka",
"ja": "大阪府"
},
"level": "prefecture",
"taxBase": "per_person"
},
{
"id": "kyoto",
"name": {
"en": "Kyoto",
"ja": "京都市"
},
"prefecture": {
"en": "Kyoto",
"ja": "京都府"
},
"level": "city",
"taxBase": "per_person"
}
]
}1エリアの全規則(施行日・終了日、税額の区分または税率、上限、免税点)、免税・課税免除の項目、公式の出典URLを返します。
パラメータ
| 名前 | 型 | 必須 | 説明 |
|---|---|---|---|
X-API-Keyheader | string | 任意 | APIキー。省略すると匿名(IPごとの無料枠)で処理されます。 |
idpath | string | 必須 | エリアID。 |
リクエスト
curl https://yadozei.jp/v1/areas/tokyoconst res = await fetch("https://yadozei.jp/v1/areas/tokyo");
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import requests
res = requests.get(
"https://yadozei.jp/v1/areas/tokyo",
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"id": "tokyo",
"name": {
"en": "Tokyo",
"ja": "東京都"
},
"prefecture": {
"en": "Tokyo",
"ja": "東京都"
},
"level": "prefecture",
"taxBase": "per_person",
"rules": [
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"effectiveFrom": "2002-10-01",
"effectiveUntil": "2027-03-31",
"type": "fixed",
"tiers": [
{
"min": 0,
"max": 9999,
"amount": 0
},
{
"min": 10000,
"max": 14999,
"amount": 100
},
{
"min": 15000,
"max": null,
"amount": 200
}
]
},
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"effectiveFrom": "2027-04-01",
"effectiveUntil": null,
"type": "percentage",
"rate": 0.03,
"cap": null,
"threshold": 13000
}
],
"exemptions": [
"school_trips"
],
"notes": "Revision consented by the Minister of Internal Affairs 2026-06-30, in effect from 2027-04-01: flat 3% of the nightly charge (no cap), exempt threshold raised to stays under 13,000 yen per person per night, and hostels (kan'i-shukusho) / minpaku added to the scope (their operators register as collection agents from 2026-07-01).",
"source": "https://www.tax.metro.tokyo.lg.jp/kazei/leisure/shuk"
}住所から、その物件の課税エリア(areaId)を判定します。市町村が独自に課税しているか、都道府県全域の課税か、宿泊税がないかを、都道府県と市町村から決めます。
パラメータ
| 名前 | 型 | 必須 | 説明 |
|---|---|---|---|
X-API-Keyheader | string | 任意 | APIキー。省略すると匿名(IPごとの無料枠)で処理されます。 |
addressquery | string | いずれか | 住所。都道府県から書いてください(例:沖縄県国頭郡恩納村…)。郵便番号、先頭の「日本」、全角文字、空白はそのままで構いません。 |
prefecturequery | string | いずれか | address の代わりに送る都道府県名(例:沖縄県)。municipality と一緒に送ります。 |
municipalityquery | string | いずれか | address の代わりに送る市区町村名(例:国頭郡恩納村、那覇市)。 |
address か、prefecture と municipality の組み合わせで送ってください(両方は送れません)。住所は都道府県から書いてください。都道府県がないと、データ内に一つしかない市町村名しか判定できません。
リクエスト
curl -G https://yadozei.jp/v1/resolve \
--data-urlencode 'address=沖縄県国頭郡恩納村字恩納2451'const res = await fetch("https://yadozei.jp/v1/resolve?" + new URLSearchParams({"address":"沖縄県国頭郡恩納村字恩納2451"}));
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import requests
res = requests.get(
"https://yadozei.jp/v1/resolve",
params={"address": "沖縄県国頭郡恩納村字恩納2451"},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"input": "沖縄県国頭郡恩納村字恩納2451",
"areaId": "onna",
"match": "municipal",
"areaName": {
"ja": "恩納村",
"en": "Onna"
},
"prefecture": "沖縄県",
"municipality": "恩納村"
}レスポンスの項目
| 項目 | 型 | 説明 |
|---|---|---|
input | string | 送った住所(そのまま)。prefecture と municipality で送った場合は、その二つをつなげたものです。 |
areaId | string | null | POST /v1/calculate に渡すエリアID。宿泊税がない場合と判定できない場合は null です。 |
match | "municipal" | "prefecture" | "no_tax" | "unresolved" | 判定の種類(下の表)。 |
areaName | { en, ja } | エリア名。areaId があるときだけ含まれます。 |
prefecture | string | 見つかった都道府県(日本語)。見つからなかったときは含まれません。 |
municipality | string | null | 一致した市町村エリアの名前。市町村エリアに一致しなかったときは null です。 |
message | string | unresolved のときだけ:住所に足りないもの(英語)。 |
match の値
| 値 | 意味 |
|---|---|
municipal | 独自に課税している市町村です。areaId はその市町村のエリアで、都道府県の税がかかる場合はそれも含みます(例:沖縄県国頭郡恩納村 → onna)。 |
prefecture | 都道府県全域の課税です。その市町村には独自のエリアがありません(例:沖縄県那覇市 → okinawa_other、東京都新宿区 → tokyo)。 |
no_tax | 宿泊税はかかりません。都道府県に全域の課税がなく、市町村も課税していません(例:京都府宇治市)。areaId は null です。 |
unresolved | 判定できませんでした。都道府県が見つからない場合(都道府県がなくても、データ内で一つしかない市町村名なら判定します)と、市町村で結果が変わる都道府県で市町村がない場合です。message に従って住所を補ってください。 |
最大100件の住所をまとめて判定し、送った順に結果を返します。件数によらず1回の呼び出しを1リクエストと数えます。有料プラン限定です。
パラメータ
| 名前 | 型 | 必須 | 説明 |
|---|---|---|---|
X-API-Keyheader | string | 必須 | 有料プランのAPIキー(必須)。 |
addressesbody | string[] | 必須 | 住所の配列。それぞれ GET の address と同じように書きます。 |
未定義のキーは受け付けません。本文は128KBまでです。results は送った順に並び、各要素は GET /v1/resolve の応答と同じ形です。
リクエスト
curl -X POST https://yadozei.jp/v1/resolve \
-H 'content-type: application/json' \
-H "x-api-key: $YADOZEI_API_KEY" \
-d '{"addresses":["沖縄県国頭郡恩納村字恩納2451","沖縄県那覇市泉崎1-2-2","京都府宇治市宇治琵琶33","那覇市泉崎1-2-2"]}'const res = await fetch("https://yadozei.jp/v1/resolve", {
method: "POST",
headers: { "content-type": "application/json", "x-api-key": process.env.YADOZEI_API_KEY },
body: JSON.stringify({
"addresses": [
"沖縄県国頭郡恩納村字恩納2451",
"沖縄県那覇市泉崎1-2-2",
"京都府宇治市宇治琵琶33",
"那覇市泉崎1-2-2"
]
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import os
import requests
res = requests.post(
"https://yadozei.jp/v1/resolve",
json={"addresses": ["沖縄県国頭郡恩納村字恩納2451", "沖縄県那覇市泉崎1-2-2", "京都府宇治市宇治琵琶33", "那覇市泉崎1-2-2"]},
headers={"x-api-key": os.environ["YADOZEI_API_KEY"]},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"results": [
{
"input": "沖縄県国頭郡恩納村字恩納2451",
"areaId": "onna",
"match": "municipal",
"areaName": {
"ja": "恩納村",
"en": "Onna"
},
"prefecture": "沖縄県",
"municipality": "恩納村"
},
{
"input": "沖縄県那覇市泉崎1-2-2",
"areaId": "okinawa_other",
"match": "prefecture",
"areaName": {
"ja": "沖縄県(その他地域)",
"en": "Okinawa Prefecture (other areas)"
},
"prefecture": "沖縄県",
"municipality": null
},
{
"input": "京都府宇治市宇治琵琶33",
"areaId": null,
"match": "no_tax",
"prefecture": "京都府",
"municipality": null
},
{
"input": "那覇市泉崎1-2-2",
"areaId": null,
"match": "unresolved",
"message": "Could not identify the prefecture: start the address with it (e.g. 沖縄県那覇市…)."
}
]
}エラー: invalid_jsonvalidation_errorunauthorizedforbiddenpayload_too_largerate_limited
データセットの変更を、since_seq より後のものから古い順に返します。同期にはAPIキーが必要です(匿名では最新5件のみ)。
パラメータ
| 名前 | 型 | 必須 | 説明 |
|---|---|---|---|
X-API-Keyheader | string | 任意 | APIキー。省略すると匿名(IPごとの無料枠)で処理されます。 |
since_seqquery | integer | 任意 | この seq より大きいものを返します。処理済みの最大の seq を保存して渡してください。 |
リクエスト
curl 'https://yadozei.jp/v1/changes?since_seq=5' \
-H "x-api-key: $YADOZEI_API_KEY"const res = await fetch("https://yadozei.jp/v1/changes?since_seq=5", {
headers: { "x-api-key": process.env.YADOZEI_API_KEY },
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import os
import requests
res = requests.get(
"https://yadozei.jp/v1/changes",
params={"since_seq": 5},
headers={"x-api-key": os.environ["YADOZEI_API_KEY"]},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"changes": [
{
"seq": 6,
"releasedAt": "2026-09-20",
"dataVersion": "2026.09",
"areaIds": [
"kutchan",
"niseko"
],
"type": "corrected",
"summary": {
"en": "Notes clarified, no rate or date change: in Kutchan, and in Niseko from 2026-11-01, the Hokkaido prefectural tiers legally still apply but the town tax is 3% minus the prefectural amount, collected as one 3% charge by the town. The dataset keeps a single 3% town rule, so the breakdown does not split out the prefectural share.",
"ja": "注記の明確化(税率・施行日に変更なし):倶知安町、および2026年11月1日以降のニセコ町では道税の定額区分が法的に存続するが、町税=3%-道税額として町が3%を一括徴収する。データは単一の3%町ルールを維持し、内訳は道税分を分離しない。"
},
"effectiveFrom": null,
"sources": [
"https://www.town.kutchan.hokkaido.jp/town_administration/AccommodationTax/3108/",
"https://www.pref.hokkaido.lg.jp/kz/kkd/191976.html"
]
}
]
}全エリアの完全なデータ(全規則)とデータバージョンを一度に返します。有料プラン限定です。
パラメータ
| 名前 | 型 | 必須 | 説明 |
|---|---|---|---|
X-API-Keyheader | string | 必須 | 有料プランのAPIキー(必須)。 |
リクエスト
curl https://yadozei.jp/v1/data \
-H "x-api-key: $YADOZEI_API_KEY"const res = await fetch("https://yadozei.jp/v1/data", {
headers: { "x-api-key": process.env.YADOZEI_API_KEY },
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import os
import requests
res = requests.get(
"https://yadozei.jp/v1/data",
headers={"x-api-key": os.environ["YADOZEI_API_KEY"]},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"dataVersion": "2026.10",
"areas": [
{
"id": "tokyo",
"name": {
"en": "Tokyo",
"ja": "東京都"
},
"prefecture": {
"en": "Tokyo",
"ja": "東京都"
},
"level": "prefecture",
"taxBase": "per_person",
"rules": [
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"effectiveFrom": "2002-10-01",
"effectiveUntil": "2027-03-31",
"type": "fixed",
"tiers": [
{
"min": 0,
"max": 9999,
"amount": 0
},
{
"min": 10000,
"max": 14999,
"amount": 100
},
{
"min": 15000,
"max": null,
"amount": 200
}
]
},
{
"authority": {
"en": "Tokyo Metropolitan Government",
"ja": "東京都"
},
"effectiveFrom": "2027-04-01",
"effectiveUntil": null,
"type": "percentage",
"rate": 0.03,
"cap": null,
"threshold": 13000
}
],
"exemptions": [
"school_trips"
],
"notes": "Revision consented by the Minister of Internal Affairs 2026-06-30, in effect from 2027-04-01: flat 3% of the nightly charge (no cap), exempt threshold raised to stays under 13,000 yen per person per night, and hostels (kan'i-shukusho) / minpaku added to the scope (their operators register as collection agents from 2026-07-01).",
"source": "https://www.tax.metro.tokyo.lg.jp/kazei/leisure/shuk"
}
]
}稼働状況とデータバージョンを返します。レート制限の対象外なので、監視にお使いください。
リクエスト
curl https://yadozei.jp/healthzconst res = await fetch("https://yadozei.jp/healthz");
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import requests
res = requests.get(
"https://yadozei.jp/healthz",
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")レスポンス
{
"status": "ok",
"dataVersion": "2026.10",
"db": "ok"
}エラー: unhealthy
計算の考え方
料金(1泊ごと・税抜)
- 料金は1泊ごとの金額です。
ratePerNightは全泊に同じ料金を使い、nightlyRatesは1泊目から1日ずつ、各日付の泊の料金を並べます(nightlyRates[0]がチェックイン日dateの泊、nightlyRates[i]がdate+ i 日の泊)。予約の総額や平均は送らないでください。 - 料金は消費税抜きの金額です(消費税・地方消費税の10%を含めません)。食事代は除き(素泊まり)、サービス料は含めます。
- 単位は1人あたりです。
per_unitが適用される場合は1室/1棟あたりになります(課税単位)。
税込の料金を送ると:京都市、1泊
| 送った料金 | 税額 |
|---|---|
| ¥19,000(税抜・正しい) | ¥400 |
| ¥20,900(税込・誤り) | ¥1,000 |
税込の料金を送ると、区分が上がって税額が過大になることがあります。税込の金額しかない場合は、税を加えたときと同じ端数処理で、整数演算で本体価格に戻してください。浮動小数点の割り算は1円ずれることがあり、Math.floor(6600 / 1.1) は 5,999 になります。京都市では¥400の泊が¥200になります。
泊ごとの課税
宿泊税は1人1泊ごとに課税されます。APIは各泊をその泊の日付の規則で計算して合計するため、課税開始日や税率改定をまたぐ宿泊も、1回の呼び出しで正しく計算できます。
課税開始をまたぐ:恩納村、2027-01-30から4泊
| 泊 | 日付 | 料金(税抜) | 税額 |
|---|---|---|---|
| 1泊目 | ¥10,500 | ¥0 | |
| 2泊目 | ¥10,500 | ¥0 | |
| 3泊目 | ¥10,500 | ¥200 | |
| 4泊目 | ¥10,500 | ¥200 |
課税は2027-02-01の泊から始まるため、それより前の泊は0円です。合計¥400。
料金が泊ごとに違う:nightlyRates
curl -X POST https://yadozei.jp/v1/calculate \
-H 'content-type: application/json' \
-d '{"areaId":"kyoto","nightlyRates":[18000,22000,51000],"date":"2026-12-01"}'const res = await fetch("https://yadozei.jp/v1/calculate", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
"areaId": "kyoto",
"nightlyRates": [
18000,
22000,
51000
],
"date": "2026-12-01"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error.code}: ${data.error.message}`);import requests
res = requests.post(
"https://yadozei.jp/v1/calculate",
json={"areaId": "kyoto", "nightlyRates": [18000, 22000, 51000], "date": "2026-12-01"},
timeout=10,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data['error']['code']}: {data['error']['message']}")| 泊 | 日付 | 料金(税抜) | 税額 |
|---|---|---|---|
| 1泊目 | ¥18,000 | ¥400 | |
| 2泊目 | ¥22,000 | ¥1,000 | |
| 3泊目 | ¥51,000 | ¥4,000 |
各泊をその料金の区分で課税するため、合計は¥5,400です。平均料金(¥30,333)を ratePerNight で送ると¥3,000になり、正しくありません。
宿泊中に規則が変わる:東京都、2027-03-31から2泊
| 泊 | 日付 | 料金(税抜) | 方式 | 税額 |
|---|---|---|---|---|
| 1泊目 | ¥20,000 | fixed | ¥200 | |
| 2泊目 | ¥20,000 | percentage | ¥600 |
泊ごとに方式が変わります(fixed → percentage)。stayTotal.breakdown の type は最後の泊の方式を示すため、泊ごとの方式は nightly[].breakdown で確認してください。
課税単位(basis)
各エリアの taxBase が、料金と税額の単位を決めます。per_unit が適用される場合、料金の項目と stayTotal.perPerson は1室/1棟あたりの意味になります。
| taxBase | 意味 | 対象エリア |
|---|---|---|
per_person | 1人1泊ごとに課税。合計に人数を掛けます。 | 全国64エリア |
per_unit | 1室/1棟ごとに課税。人数は掛けません。料金も1室/1棟あたりで送ります。 | 現在なし |
variable | 施設の料金設定による。basis で per_person / per_unit を指定します(既定は per_unit)。 | 倶知安町、山形市 |
日付と日本時間
- 日付はすべて日本の暦日です。
dateを省略すると、日本時間の今日(UTCではなく)になります。 dateはチェックイン日で、1泊目の日付です。n泊目はdate+ (n − 1) 日です。- 受け付けるチェックイン日は 2020-01-01〜2030-12-31 です。2泊目以降はこの範囲を越えてもかまいません。
- データは各エリアの最初に記録された規則から始まります(
/v1/areas/{id}のeffectiveFrom)。規則がない泊は0円・内訳なしになりますが、過去の日付では「税がかからなかった」ことの証明にはなりません。 - レート制限の枠も日本時間でリセットされます。
本番導入の準備はできましたか?
システム名と月間の想定リクエスト数をお知らせください。お見積りとAPIキーをお送りします。