<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hiroki Sonoda</title>
    <description>The latest articles on DEV Community by Hiroki Sonoda (@endennn).</description>
    <link>https://dev.to/endennn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3938404%2Fee40b919-c1c6-4556-932d-dac2805c7d02.png</url>
      <title>DEV Community: Hiroki Sonoda</title>
      <link>https://dev.to/endennn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/endennn"/>
    <language>en</language>
    <item>
      <title>Date.parse() breaks on 5 imperial eras — I built a Japan locale API for AI agents</title>
      <dc:creator>Hiroki Sonoda</dc:creator>
      <pubDate>Wed, 20 May 2026 14:43:47 +0000</pubDate>
      <link>https://dev.to/endennn/dateparse-breaks-on-5-imperial-eras-i-built-a-japan-locale-api-for-ai-agents-2k5l</link>
      <guid>https://dev.to/endennn/dateparse-breaks-on-5-imperial-eras-i-built-a-japan-locale-api-for-ai-agents-2k5l</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Japanese locale support is full of edge cases that mainstream i18n libraries don't cover: imperial era dates, invoice check digits, corporate numbers, variable-length area codes, and reversed address order.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://torify.dev" rel="noopener noreferrer"&gt;Torify&lt;/a&gt; is a Japan locale API designed for AI agents — &lt;strong&gt;39 REST endpoints + 10 MCP tools&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Try it three ways: &lt;strong&gt;free MCP server (100 req/day/IP)&lt;/strong&gt;, &lt;strong&gt;free Trial key (100 calls/month)&lt;/strong&gt;, or &lt;strong&gt;x402 pay-per-call ($0.02/call, agent-autonomous)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why I wrote this
&lt;/h2&gt;

&lt;p&gt;Japanese locale issues are scattered across the issue trackers of every major library. &lt;code&gt;date-fns&lt;/code&gt; has &lt;a href="https://github.com/date-fns/date-fns/issues/2156" rel="noopener noreferrer"&gt;issue #2156&lt;/a&gt; about wareki formatting returning &lt;code&gt;1月 14 2021&lt;/code&gt; when it should return &lt;code&gt;1月14日2020年&lt;/code&gt;. &lt;code&gt;moment.js&lt;/code&gt; has &lt;a href="https://github.com/moment/moment/issues/5698" rel="noopener noreferrer"&gt;issue #5698&lt;/a&gt; — still open — about there being no token to parse the abbreviated &lt;code&gt;令2年1月1日&lt;/code&gt;. Even Electron had to &lt;a href="https://github.com/electron/electron/pull/17833" rel="noopener noreferrer"&gt;backport Reiwa support&lt;/a&gt; into ICU after the 2019 era change.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Intl.DateTimeFormat('ja-JP-u-ca-japanese')&lt;/code&gt; does render eras, but the standard API can't handle era-change boundaries (Showa 64 = Heisei 1, January 7, 1989) or abbreviated forms like &lt;code&gt;R6.5.1&lt;/code&gt;. Each of these is a small bug on its own. Pile them together and you get &lt;strong&gt;the AI agent persona that's been burning me out for months&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Foreign engineer rolling out a SaaS into the Japan market. A "trivial date validation" that takes 30 minutes back home has eaten three days because of Japan-specific rules.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the pain &lt;a href="https://torify.dev" rel="noopener noreferrer"&gt;Torify&lt;/a&gt; is built to remove.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every issue/PR linked above maps to a Torify endpoint:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;moment #5698 (no abbreviation token)&lt;/strong&gt; → &lt;code&gt;parseWarekiString&lt;/code&gt; handles all 5 forms: &lt;code&gt;R2.5.1&lt;/code&gt;, &lt;code&gt;令2年5月1日&lt;/code&gt;, &lt;code&gt;令和元年5月1日&lt;/code&gt;, &lt;code&gt;H31.4.30&lt;/code&gt;, &lt;code&gt;令6年5月1日&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;electron PR #17833 (era boundaries)&lt;/strong&gt; → strict &lt;code&gt;eraStart&lt;/code&gt; enforcement plus &lt;strong&gt;automatic rejection of dates that fall in the next era&lt;/strong&gt; (e.g. &lt;code&gt;H31.5.1&lt;/code&gt; is already Reiwa → 400).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;date-fns #2156 (incomplete formatter)&lt;/strong&gt; → ICU-independent implementation that returns a consistent schema across all 5 eras (&lt;code&gt;era&lt;/code&gt;, &lt;code&gt;eraRomaji&lt;/code&gt;, &lt;code&gt;eraYear&lt;/code&gt;, &lt;code&gt;eraYearLabel&lt;/code&gt;, &lt;code&gt;formatted&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One REST or MCP call — no library bugs, no runtime version pinning.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it in 60 seconds — get a free Trial key
&lt;/h2&gt;

&lt;p&gt;Every endpoint below requires an &lt;code&gt;X-Trial-Key&lt;/code&gt; header (or &lt;code&gt;X-Api-Key&lt;/code&gt; for Pro/Enterprise, or x402 wallet payment). The trial key is free, 100 calls/month, no credit card. One curl to claim it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://torify.dev/v1/trial/signup"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"email": "you@example.com", "consent": true}'&lt;/span&gt;
&lt;span class="c"&gt;# { ok: true, data: { key: "trial_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", monthlyLimit: 100, message: "..." } }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the &lt;code&gt;key&lt;/code&gt; value. Every subsequent curl in this article uses it as &lt;code&gt;X-Trial-Key&lt;/code&gt;. (Pro/Enterprise customers swap in &lt;code&gt;X-Api-Key&lt;/code&gt;. Agents using x402 pay $0.02/call autonomously — no key needed; see Section C below.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-auth curls return 402 Payment Required&lt;/strong&gt;, not the JSON shown. That's the x402 protocol challenge for agent-autonomous payment. Use the trial key or x402 wallet to get actual data.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The 5 ways AI agents silently fail on Japanese locale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Wareki dates — &lt;code&gt;Date.parse()&lt;/code&gt; dies on 5 imperial eras
&lt;/h3&gt;

&lt;p&gt;Japan uses an imperial era calendar. The current era is &lt;strong&gt;Reiwa&lt;/strong&gt; (since May 1, 2019). Before that came Heisei, Showa, Taisho, and Meiji — each with its own start date.&lt;/p&gt;

&lt;p&gt;Government APIs, invoices, and forms routinely return strings like &lt;code&gt;令和6年5月1日&lt;/code&gt; or &lt;code&gt;R6.5.1&lt;/code&gt;. &lt;code&gt;Date.parse()&lt;/code&gt; won't touch them. And then there's the edge case from hell: &lt;strong&gt;January 7, 1989 is &lt;em&gt;both&lt;/em&gt; Showa 64 and the first day of Heisei&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# All curls in this section need: -H "X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;

curl &lt;span class="s2"&gt;"https://torify.dev/v1/wareki/convert?direction=g2w&amp;amp;date=2024-05-01"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# { era: "令和", eraRomaji: "Reiwa", eraYear: 6, eraYearLabel: "6年", formatted: "令和6年5月1日" }&lt;/span&gt;

curl &lt;span class="s2"&gt;"https://torify.dev/v1/wareki/convert?direction=w2g&amp;amp;era=showa&amp;amp;eraYear=64&amp;amp;month=1&amp;amp;day=7"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# { year: 1989, month: 1, day: 7, formatted: "1989-01-07" }  &amp;lt;- Showa's final day, handled correctly&lt;/span&gt;

&lt;span class="c"&gt;# Abbreviations: R6.5.1 / 令和6年5月1日 / 令6年5月1日 all accepted as free-form input&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://torify.dev/v1/wareki/convert?direction=w2g&amp;amp;input=R6.5.1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# { year: 2024, month: 5, day: 1, formatted: "2024-05-01" }&lt;/span&gt;

curl &lt;span class="s2"&gt;"https://torify.dev/v1/wareki/convert?direction=w2g&amp;amp;input=%E4%BB%A4%E5%92%8C6%E5%B9%B45%E6%9C%881%E6%97%A5"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# Same result — passing 令和6年5月1日 raw also works.&lt;/span&gt;

&lt;span class="c"&gt;# Era boundaries enforced both ways: Heisei 31.5.1 is actually Reiwa 1.5.1, so it's rejected&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://torify.dev/v1/wareki/convert?direction=w2g&amp;amp;input=H31.5.1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# 400 INVALID_INPUT: H31.5.1 は次の元号が始まった日付のため無効です。正しい元号で指定してください。&lt;/span&gt;
&lt;span class="c"&gt;# (Note: Heisei ended 2019-04-30 — use "R1.5.1" instead. Error messages are currently&lt;/span&gt;
&lt;span class="c"&gt;# returned in Japanese only; see /openapi.json for the English schema.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Invoice numbers — the NTA's own check digit (Luhn-like, but mod 9) + registry lookup
&lt;/h3&gt;

&lt;p&gt;Since October 2023, Japan's &lt;strong&gt;qualified invoice system&lt;/strong&gt; (適格請求書等保存方式) requires every B2B invoice to reference a 13-digit &lt;code&gt;T&lt;/code&gt;-prefixed number.&lt;/p&gt;

&lt;p&gt;The check digit looks like Luhn at first glance — but it isn't. The 12-digit base is multiplied by &lt;code&gt;[2,1,2,1,...]&lt;/code&gt; right-to-left, summed, and the check digit is &lt;code&gt;9 - (sum % 9)&lt;/code&gt;. Luhn is &lt;strong&gt;mod 10 with digit-splitting&lt;/strong&gt;; this is &lt;strong&gt;mod 9 without digit-splitting&lt;/strong&gt;. &lt;strong&gt;Drop in a Luhn implementation from a foreign payments library and you will get a 100% failure rate.&lt;/strong&gt; Reverse the multiplier direction, and real invoice numbers fail validation.&lt;/p&gt;

&lt;p&gt;This isn't a UX issue. It's a tax compliance failure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Format check + check digit (offline, no network call)&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://torify.dev/v1/invoice/validate?number=T7000012050002"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# { valid: true, format: "valid", checkDigit: { expected: 7, actual: 7, match: true }, type: "corporate" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A live registry lookup is also available via &lt;code&gt;/v1/invoice/verify&lt;/code&gt; (same auth header, NTA Web-API backed, returns &lt;code&gt;registered&lt;/code&gt;, &lt;code&gt;registrantName&lt;/code&gt;, &lt;code&gt;registrationDate&lt;/code&gt;, cancellation date). Subject to NTA Web-API availability and registrant state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Corporate numbers — 13 digits + the NTA API
&lt;/h3&gt;

&lt;p&gt;Every Japanese corporation has a 13-digit &lt;strong&gt;corporate number&lt;/strong&gt; (法人番号) assigned by the National Tax Agency. Unlike US EINs (9 digits) or EU VAT numbers, the only official way to verify one is the dedicated NTA API at &lt;code&gt;houjin-bangou.nta.go.jp&lt;/code&gt;. The endpoint returns XML, and the counter-intuitive part: &lt;code&gt;type=11&lt;/code&gt; is invalid (use &lt;code&gt;type=12&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://torify.dev/v1/houjin/lookup?number=7000012050002"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# {&lt;/span&gt;
&lt;span class="c"&gt;#   name: "国税庁",&lt;/span&gt;
&lt;span class="c"&gt;#   address: {&lt;/span&gt;
&lt;span class="c"&gt;#     full: "東京都千代田区霞が関3丁目1番1号",&lt;/span&gt;
&lt;span class="c"&gt;#     prefecture: "東京都", city: "千代田区", rest: "霞が関3丁目1番1号"&lt;/span&gt;
&lt;span class="c"&gt;#   },&lt;/span&gt;
&lt;span class="c"&gt;#   kind: { code: "101", ja: "国の機関", en: "Government Agency" },&lt;/span&gt;
&lt;span class="c"&gt;#   status: "active",&lt;/span&gt;
&lt;span class="c"&gt;#   confidence: 0.99&lt;/span&gt;
&lt;span class="c"&gt;# }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Phone numbers — area codes are 2-5 digits, variable length
&lt;/h3&gt;

&lt;p&gt;Japanese area codes aren't fixed length:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Region&lt;/th&gt;
&lt;th&gt;Area code&lt;/th&gt;
&lt;th&gt;Subscriber part&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tokyo&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;03&lt;/code&gt; (2 digits)&lt;/td&gt;
&lt;td&gt;8 digits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Osaka&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;06&lt;/code&gt; (2 digits)&lt;/td&gt;
&lt;td&gt;8 digits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nagano / Suwa&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0266&lt;/code&gt; (4 digits)&lt;/td&gt;
&lt;td&gt;6 digits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toll-free&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0120&lt;/code&gt; (4 digits)&lt;/td&gt;
&lt;td&gt;6 digits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Generic E.164 parsers either fail outright or produce wrong results. We've seen libraries silently split &lt;code&gt;0266-22-2611&lt;/code&gt; as &lt;code&gt;02-6622-2611&lt;/code&gt; because they assumed a 2-digit area code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://torify.dev/v1/phone/validate?phone=0266-22-2611"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# { valid: true, type: "fixed", typeEn: "Landline (fixed)", normalized: "0266222611", e164: "+81266222611" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Addresses — largest-first ordering + full-width/half-width digit mix
&lt;/h3&gt;

&lt;p&gt;Japanese addresses go &lt;code&gt;prefecture → city → town → block&lt;/code&gt; — the exact reverse of &lt;code&gt;street → city → state&lt;/code&gt; in the West. Worse, half-width and full-width digits are mixed freely in real data, and postal codes don't map to a single address — they map to a &lt;strong&gt;town area&lt;/strong&gt;, and the building/unit number comes after.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://torify.dev/v1/address/normalize?address=東京都千代田区霞が関3丁目1番1号"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# { prefecture: "東京都", prefectureEn: "Tokyo", city: "千代田区", town: "霞が関3丁目1番1号", normalized: "東京都千代田区霞が関3丁目1番1号", streetNumberHyphen: "3-1-1" }&lt;/span&gt;

curl &lt;span class="s2"&gt;"https://torify.dev/v1/postal/lookup?zipcode=1000013"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;span class="c"&gt;# { zipcode: "100-0013", prefecture: "東京都", prefectureEn: "Tokyo", city: "千代田区", town: "霞が関", full: "東京都千代田区霞が関" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Torify is
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://torify.dev" rel="noopener noreferrer"&gt;Torify&lt;/a&gt; packages all of the above into a single Japan locale API designed for AI agents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;39 REST endpoints&lt;/strong&gt; — wareki, invoice, corporate lookup, addresses, phone numbers, kanji↔kana, consumption tax, holidays, bank codes, coordinate conversion, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10 MCP tools&lt;/strong&gt; — drop straight into Claude Desktop / Cursor / Cline / Continue.dev / Zed / Windsurf / Goose / 5ire.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 auth tiers&lt;/strong&gt; — MCP (free) / Trial key (free) / Pro / Enterprise / x402 pay-per-call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every response uses the same envelope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Three ways to try it right now
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A) MCP server — 1 line of config, free, 100 req/day/IP
&lt;/h3&gt;

&lt;p&gt;Works in every MCP-capable client: Claude Desktop, &lt;strong&gt;Cursor&lt;/strong&gt;, &lt;strong&gt;Cline (VS Code)&lt;/strong&gt;, &lt;strong&gt;Continue.dev&lt;/strong&gt;, &lt;strong&gt;Zed&lt;/strong&gt;, &lt;strong&gt;Windsurf&lt;/strong&gt;, &lt;strong&gt;Goose&lt;/strong&gt;, &lt;strong&gt;5ire&lt;/strong&gt;. Just add one entry to your config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"torify"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://torify-mcp.torify.workers.dev"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rate limit (MCP):&lt;/strong&gt; no authentication required, but limited to &lt;strong&gt;100 req/day/IP&lt;/strong&gt;. Ask Claude Desktop "what year is Reiwa 6 in the Gregorian calendar?" — that's a working smoke test.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also listed on Smithery: &lt;a href="https://smithery.ai/servers/endenibrk/torify" rel="noopener noreferrer"&gt;smithery.ai/servers/endenibrk/torify&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  B) Trial key — email signup, free, 100 calls/month
&lt;/h3&gt;

&lt;p&gt;Same &lt;code&gt;POST /v1/trial/signup&lt;/code&gt; as shown at the top (or use the LP form at &lt;a href="https://torify.dev" rel="noopener noreferrer"&gt;torify.dev&lt;/a&gt;). Pass the returned &lt;code&gt;key&lt;/code&gt; value as the &lt;code&gt;X-Trial-Key&lt;/code&gt; header.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rate limit (Trial):&lt;/strong&gt; &lt;strong&gt;100 calls/month&lt;/strong&gt;, independent of the MCP day-limit. No credit card, no wallet.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://torify.dev/v1/wareki/convert?direction=g2w&amp;amp;date=2024-05-01"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Trial-Key: trial_YOUR_KEY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  C) x402 pay-per-call — $0.02/call, wallet only
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://x402.org" rel="noopener noreferrer"&gt;x402&lt;/a&gt; is an HTTP-native payment protocol on Base L2 (USDC). AI agents can pay autonomously, no API key signup needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;wrapFetchWithPayment&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x402-fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createWalletClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;viem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;viem/chains&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;privateKeyToAccount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;viem/accounts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createWalletClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;privateKeyToAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="s2"&gt;`0x&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;http&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetch402&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrapFetchWithPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// The agent pays $0.02 USDC on every call, on its own&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch402&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://torify.dev/v1/invoice/verify?number=T7000012050002&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No subscription. No API key rotation. The agent handles payment end-to-end.&lt;/p&gt;




&lt;h2&gt;
  
  
  All 39 endpoints at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Date &amp;amp; calendar&lt;/td&gt;
&lt;td&gt;Wareki conversion, public holidays, legal holidays, age &amp;amp; school year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tax &amp;amp; corporate&lt;/td&gt;
&lt;td&gt;Invoice validate/verify (incl. bulk), corporate number lookup, consumption tax, eLTAX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Address &amp;amp; phone&lt;/td&gt;
&lt;td&gt;Postal → address, address normalization, phone validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Kanji → kana, text normalization, name romanization (Hepburn) / split / validate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payments &amp;amp; finance&lt;/td&gt;
&lt;td&gt;Bank codes, Zengin transfer validation, Japan Post (Yucho) conversion, 3D Secure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDs &amp;amp; numbers&lt;/td&gt;
&lt;td&gt;Corporate number, My Number, passport, driver's license, insurance card&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geo &amp;amp; misc.&lt;/td&gt;
&lt;td&gt;Coordinates (WGS84 ↔ JGD2011, GSI), JSIC industry codes, license plates, JAN barcodes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Full spec: &lt;a href="https://torify.dev/docs" rel="noopener noreferrer"&gt;torify.dev/docs&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design choices (the short version)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why Cloudflare Workers?&lt;/strong&gt; AI agents are distributed globally. Cloudflare's edge minimizes round-trips to Japan's NTA API while keeping latency low for agents anywhere in the world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why three protocols (MCP / A2A / x402)?&lt;/strong&gt; MCP for today's Claude/Cursor users. A2A (Agent-to-Agent) for next-gen inter-agent communication. x402 for autonomous agent payment. Running all three in parallel means we can ride the protocol transition without breaking anyone.&lt;/p&gt;

&lt;p&gt;The A2A Agent Card is already live: &lt;a href="https://torify.dev/.well-known/agent.json" rel="noopener noreferrer"&gt;torify.dev/.well-known/agent.json&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Production-grade: verified against real inputs
&lt;/h2&gt;

&lt;p&gt;Every endpoint was exercised against real production data before launch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1,535 automated tests&lt;/strong&gt; passing (unit + integration + consistency)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;117 live curl checks&lt;/strong&gt; on testnet (41 happy-path + 76 edge cases), 100% pass rate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;39 mainnet checks&lt;/strong&gt; via Trial key, after URL-encoding — all passed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;16 bugs fixed&lt;/strong&gt; from real-traffic detection plus code/security review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two resilience features that came directly from real failure modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mock fallback for external APIs.&lt;/strong&gt; If the NTA corporate registry or Japan's GSI geocoding service returns 5xx, the endpoint still returns 200 with a cached/estimated result and &lt;code&gt;confidence: 0.5&lt;/code&gt;. Your agent won't crash because a Japanese government API had a bad afternoon. Kanji-to-kana now runs on Cloudflare Workers AI (Llama 3.3 70B inference) — no external API dependency, zero ToS risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forgiving input aliases.&lt;/strong&gt; Coordinate conversion accepts &lt;code&gt;wgs84-to-jgd2011&lt;/code&gt;, &lt;code&gt;wgs84_jgd2011&lt;/code&gt;, and the canonical form interchangeably. Bank transfer type accepts &lt;code&gt;ordinary&lt;/code&gt;, &lt;code&gt;futsu&lt;/code&gt;, or &lt;code&gt;普通&lt;/code&gt;. When an LLM generates a semantically correct value with surface-level variance, we accept it instead of throwing.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Endpoint-specific pricing once traffic justifies it (external API endpoints like NTA cost more to run; kanji-to-kana stays flat because Workers AI absorbs the cost).&lt;/li&gt;
&lt;li&gt;As the A2A ecosystem grows, positioning Torify as the Japan locale &lt;strong&gt;primitive&lt;/strong&gt; that other agents can call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback welcome — &lt;strong&gt;which endpoint would you use first?&lt;/strong&gt; Drop a comment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP (free)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100 req/day/IP&lt;/td&gt;
&lt;td&gt;Add one entry to your MCP config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trial (free)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100 calls/month&lt;/td&gt;
&lt;td&gt;Email signup at &lt;a href="https://torify.dev" rel="noopener noreferrer"&gt;torify.dev&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10,000 calls/month&lt;/td&gt;
&lt;td&gt;$49/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enterprise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,000,000 calls/month (Fair Use Policy)&lt;/td&gt;
&lt;td&gt;from $499/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;x402 pay-per-call&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.02/call, wallet only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://torify.dev/pricing" rel="noopener noreferrer"&gt;torify.dev/pricing&lt;/a&gt; — no credit card required to start.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Torify: &lt;a href="https://torify.dev" rel="noopener noreferrer"&gt;torify.dev&lt;/a&gt; | MCP: &lt;a href="https://smithery.ai/servers/endenibrk/torify" rel="noopener noreferrer"&gt;Smithery&lt;/a&gt; (100/100), &lt;a href="https://mcp.so/server/torify-%E2%80%94-japanese-locale-apis-for-ai-agents/hiroki-sonoda" rel="noopener noreferrer"&gt;MCP.so&lt;/a&gt; | x402: &lt;a href="https://www.x402scan.com" rel="noopener noreferrer"&gt;x402scan&lt;/a&gt; | A2A: &lt;a href="https://a2aregistry.org/agents/8ae07cab-ccf7-4e6b-8a6f-45ff64c9fa98" rel="noopener noreferrer"&gt;a2aregistry.org&lt;/a&gt;, &lt;a href="https://torify.dev/.well-known/agent.json" rel="noopener noreferrer"&gt;Agent Card&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Author: Hiroki Sonoda · License: MIT&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>api</category>
      <category>japan</category>
    </item>
  </channel>
</rss>
