はじめに
住所と郵便番号を相互変換するAPIを、個人で作って公開しました。
Address to ZIP
設計から実装、セキュリティ、決済、本番デプロイまで、ほぼ全部をAIと一緒に進めました。これはその記録です。
なぜ作ったのか
郵便番号のデータは、日本郵便が無料で配っています。
だから本当は、自前で取り込めばタダです。先に言っておくと、自前で困っていない人にこのサービスは要りません。
ただ、いざプロダクトに乗せようとすると、地味な手間が積み上がる。
- 不定期に入る更新を、毎月チェックして差し替える
- 番地や建物名つきの住所も、町名まで解釈する
- 郵便番号からの逆引きも用意する
- そしてそれを「APIの形」にして、運用し続ける
一個ずつは大したことない。でも毎回これをやるのが、だるい。
「この面倒を一回だけ片付けて、誰でも叩ける形にしておきたい」。それだけでした。
AIと作りはじめる
今回、コードを書く中心はずっとAIです。(3日で作りました。)
使ったのは Claude Code。
それに gstackというスキル集を足しています。
/review で差分レビュー
/cso でセキュリティ点検
/qa で挙動テスト
/browse でブラウザ確認
/ship でデプロイ
という具合にワークフローが揃っていて、これがよく効いた。新しいモデルの Fable も併用しています。
(途中で何処かに旅立ってしまったので最後の方はOpusを使いました。)
住所マッチングのプロトタイプが最初にちゃんと動いて、番地つきの住所から郵便番号が出た時は、普通に「お、いけるじゃん」となりました。
作っていく中で、印象に残ったこと
〒マークで一回立ち止まった
最初、ロゴに郵便マーク(〒)を使っていました。見慣れてるし、それっぽいので。
でも念のため調べたら、あのマークは日本郵政の登録商標でした。商用サービスのロゴに使うと、郵便の公式と勘違いされたり、商標的にまずかったりする。
ここでロゴを ATZ(Address To Zip)に作り直しました。AIは「直そう」とは言えるけど、「これは商標的に危ない」と最初に立ち止まるのは、人間側の仕事でした。
なぜ無料じゃなく、課金にしたか
最初は無料も考えました。でもやめました。
無料で配ると、サーバー代も運用も全部自分に積もっていって、たぶんある日こっそり止まる。止まるサービスは、使う側からすると一番つらい。だったら小さく課金して、回り続ける方が誠実だなと。月1,980円、プランは一個だけにしました。
その代わり、サイト上の検索は無料のまま残しています。
決済を、本番で通しきる
地味にちゃんとやったのが決済の確認です。
テストモードで終わらせず、本番で実際に自分のカードで払って、キーが発行されて、APIが通って、解約でキーが止まって、最後に返金されるところまで、一通りAIと一緒に確認しました。お金が絡むところは、動いたつもりが一番こわいので。
技術スタック
バックエンド : 素のNode.js(フレームワークなし)
依存 : stripe と pg だけ
ホスティング : Railway
前段 : Cloudflare(DNS / WAF / メール)
メール : Resend
決済 : Stripe
開発 : Claude Code + gstack + Fable/Opus
監視 : UptimeRobot
ビルドツールなし。依存も最小。シンプルに倒しました。
今回、Railwayを初めて触りましたが、WEBサーバー+DBセットで構築できるのでvercel + supabaseよりAI駆動開発との相性は良いかもしれません。
使ってみる
認証は x-api-key ヘッダーに乗せるだけ。返ってくるのは全部JSONです。
curl --get "https://addresstozip.jp/api/v1/search" \
--data-urlencode "address=東京都千代田区丸の内" \
-H "x-api-key: YOUR_KEY"
逆引き(郵便番号→住所)は /api/v1/lookup?zipcode=100-0005。各言語のコード例はドキュメントに置いてあります。
ひとつだけ注意。URLに日本語を直書きするとCDNに400で弾かれるので、fetch / axios 等の自動エンコードを使うか、curlなら --data-urlencode を付けてください。
作って分かったこと
個人でも、相棒がAIならここまで作れる
正直、自分はJavaScriptの細かい構文をゼロからスラスラ書けるタイプではありません。でも「何をどう動かしたいか」を正確に言葉にできれば、AIがコードにしてくれる。
効いたのは文法の暗記より、やりたいことを厳密に言語化することと、一気に盛らず一個ずつ検証すること、そして動かない時にエラーをそのまま投げて粘ることでした。
でも、AIに渡せない判断があった
商標のマークを使っていいか。データの正確性をどこまで保証する(しない)か。いくらで売るのが誠実か。法務ページに何を書くか。
このあたりは、最終的に人間が決めるしかなかった。「実装とレビュー=AI」「プロダクトと責任の判断=自分」。この線引きがはっきりしてから、迷いが減りました。
正直なところ
稼働率保証(SLA)はありません。個人運用なのでベストエフォートです。データの中身も完全とは言い切れないので、配送みたいなクリティカルな用途では自前でも確認してください。
そして大事なこと。日本郵便の公式データは使っていますが、日本郵政・日本郵便とは無関係の、まったくの個人サービスです。ここだけは誤解されたくないので明記しておきます。
今後の展望
今は「住所⇄郵便番号」の相互変換に絞っています。が、作っていて一番手応えがあったのは、実は変換そのものより住所をどう解釈するかの部分でした。
番地つき・建物名つき・全角半角まじり・「丁目」と「-」の混在みたいな、人間が書くと当たり前にブレるやつを、町名まで噛み砕いて寄せる。ここがちゃんと動いた時が一番おもしろかった。
なので次にやれたらと思っているのが、この解釈の部分を独立させた 住所正規化です。表記ゆれを吸収して、整った住所に揃える。郵便番号を引くついでではなく、「住所をきれいにする」こと自体をAPIにできたら、フォーム入力やデータ名寄せみたいな場面でも使ってもらえるはず、と考えています。
まだ構想段階で、いつとは言えません。ただ、土台になる住所解釈はもう動いているので、ここから伸ばせる余地は一番大きいと思っています。
おわりに
「郵便番号API、地味に面倒」に心当たりがある人に向けて作りました。
コードの細部はAIに助けてもらいましたが、何を作るか・どこで線を引くかは、ぜんぶ自分で決めました。その両方があって、ようやく人に使ってもらえる形になった気がします。
触ってみて何かあれば、フィードバックもらえると嬉しいです。
- サイト: https://addresstozip.jp
- ドキュメント: https://addresstozip.jp/docs
- よくある質問: https://addresstozip.jp/faq