Documentation
Base URL: https://api.example.jp — authenticate with the x-api-key header. All responses are JSON (UTF-8). New here? The quick-start guide gets you running in about 5 minutes.
Endpoints
GET /api/v1/search — address to postal code
| Parameter | Required | Description |
|---|---|---|
address | required | Address string (up to 256 chars) in kanji, kana, or romaji. Real-world input like “Marunouchi 1-2-3, Chiyoda-ku, Tokyo” is interpreted down to the town level automatically — building names and block numbers are stripped. |
limit | optional | Number of results, 1–50. Default 10. |
lang | optional | Language of error messages. en for English (defaults to the Accept-Language header). Error codes never change with language. |
curl --get "https://api.example.jp/api/v1/search" \
--data-urlencode "address=Marunouchi, Chiyoda-ku, Tokyo" \
-H "x-api-key: YOUR_KEY"
{
"query": "Marunouchi, Chiyoda-ku, Tokyo",
"count": 1,
"results": [
{ "zipcode": "100-0005", "prefecture": "東京都",
"city": "千代田区", "town": "丸の内",
"address": "東京都千代田区丸の内", "kana": "...",
"prefecture_romaji": "Tokyo", "city_romaji": "Chiyoda-ku",
"town_romaji": "Marunochi", "romaji": "Marunochi, Chiyoda-ku, Tokyo",
"score": 93 }
]
}GET /api/v1/lookup — postal code to address
| Parameter | Required | Description |
|---|---|---|
zipcode | required | 100-0005 or 1000005 (exact match). |
lang | optional | Same as above. |
curl "https://api.example.jp/api/v1/lookup?zipcode=100-0005" \
-H "x-api-key: YOUR_KEY"GET /api/v1/health — status and data freshness (no auth)
Returns record count, data timestamp, and datastore reachability. During an outage it returns 503 {"status":"degraded"}. Handy for monitoring.
Romanization
Every result includes prefecture_romaji / city_romaji / town_romaji, plus a composed romaji field in Western order (town, city, prefecture) — safe to store in Latin-1 systems.
- Output follows Japan Post's official romanization. That occasionally differs from common usage — e.g. Japan Post spells 丸の内 as
Marunochi, while the district is commonly written Marunouchi. Both are the same place; we return the official form. - Input is forgiving: searches accept common spellings and variants —
Marunouchi/Marunochi,Shimbashi/Shinbashi,Ōsaka/Osaka,Tokyo/Tokyo-to— in any order, with or without commas.
Code examples
Calling address → postal code (/api/v1/search). Replace YOUR_KEY with your API key. For reverse lookup, switch to /api/v1/lookup with a zipcode parameter.
curl --get "https://api.example.jp/api/v1/search" \
--data-urlencode "address=Marunouchi, Chiyoda-ku, Tokyo" \
-H "x-api-key: YOUR_KEY"
const url = new URL("https://api.example.jp/api/v1/search");
url.searchParams.set("address", "Marunouchi, Chiyoda-ku, Tokyo");
const res = await fetch(url, {
headers: { "x-api-key": "YOUR_KEY" },
});
const data = await res.json();
console.log(data.results);
import requests
res = requests.get(
"https://api.example.jp/api/v1/search",
params={"address": "Marunouchi, Chiyoda-ku, Tokyo"},
headers={"x-api-key": "YOUR_KEY"},
)
res.raise_for_status()
print(res.json()["results"])
<?php
$query = http_build_query(["address" => "Marunouchi, Chiyoda-ku, Tokyo"]);
$ch = curl_init("https://api.example.jp/api/v1/search?$query");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-api-key: YOUR_KEY"]);
$body = curl_exec($ch);
curl_close($ch);
$data = json_decode($body, true);
print_r($data["results"]);
require "net/http"
require "json"
require "uri"
uri = URI("https://api.example.jp/api/v1/search")
uri.query = URI.encode_www_form(address: "Marunouchi, Chiyoda-ku, Tokyo")
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = "YOUR_KEY"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)["results"]
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
)
func main() {
u, _ := url.Parse("https://api.example.jp/api/v1/search")
q := u.Query()
q.Set("address", "Marunouchi, Chiyoda-ku, Tokyo")
u.RawQuery = q.Encode()
req, _ := http.NewRequest("GET", u.String(), nil)
req.Header.Set("x-api-key", "YOUR_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]any
json.NewDecoder(res.Body).Decode(&data)
fmt.Println(data["results"])
}
MCP (for AI agents)
AI agents such as Claude and Cursor can call the API directly as tools via the Model Context Protocol. The endpoint is https://api.example.jp/mcp, authenticated with the same x-api-key header. Two tools are exposed: search_address (address → postal code) and lookup_zipcode (postal code → address). Usage counts toward the same rate limits and billing as the regular API.
Claude Code (CLI) — replace YOUR_KEY with your API key.
claude mcp add address-to-zip \
--transport http \
--url https://api.example.jp/mcp \
--header "x-api-key: YOUR_KEY"Claude Desktop / Cursor (config file)
{
"mcpServers": {
"address-to-zip": {
"url": "https://api.example.jp/mcp",
"headers": { "x-api-key": "YOUR_KEY" }
}
}
}The server is listed in the official MCP Registry as jp.addresstozip/address-to-zip.
Errors
Add lang=en (or send Accept-Language: en) to get error messages in English. The error codes below are stable across languages.
| HTTP | error | Meaning and what to do |
|---|---|---|
| 400 | invalid_parameter | Bad parameter. The reason is in message. |
| 401 | unauthorized | Missing or invalid key. After a reissue, the old key stops working immediately. |
| 403 | key_suspended | Suspended because payment could not be confirmed. Update your payment method in the Stripe portal and the key resumes automatically. |
| 403 | origin_not_allowed | Browser call from an origin that is not on the allow list (see CORS below). |
| 429 | rate_limited | Rate limit exceeded. Wait until x-ratelimit-reset (unix seconds) and retry. |
| 503 | service_unavailable | Temporary outage. Retry after retry-after seconds. |
Rate limits
Each key has a rate limit. The effective values are returned on every response in the x-ratelimit-limit / remaining / reset headers — read them at runtime. There is no monthly cap.
CORS (calling directly from a browser)
Server-side calls are never origin-restricted. Origin checks only apply to requests that carry a browser-set Origin header. With the recommended setup (calling the API through your own server), you don't need to register any origins.
For direct browser calls, requests are accepted from the allowed origins registered with your key (exact scheme+host+port match, up to 10, wildcard https://*.example.com supported). Browser calls from unregistered origins get 403. You can edit allowed origins anytime from My Page (Japanese UI).
Live console (no sign-up)
Runs the same search engine through the site's public search (10 requests/min).
…Service terms
- The source of truth is Japan Post's official postal code data (checked monthly, applied automatically; the data timestamp is public at
/api/v1/health). Romanization follows Japan Post's official romanized dataset, with Hepburn-style transliteration as a fallback for entries the official dataset hasn't caught up with. - No SLA or uptime guarantee — the service is provided best-effort.
- Breaking changes will ship under a new version path (
/api/v2/). - Terms of service and other legal notices are provided in Japanese, which is the governing language.