API reference

API reference

Every endpoint with its parameters, an example and an excerpt of the real production response. The base URL is https://michiyomi.dev. No API key is needed. Observation text in responses is Japanese.

Generated from openapi.en.yaml (OpenAPI 3.1). Response examples were fetched from production on 2026-10-03 (release 2026-09-13-r1). The canonical Japanese definition is Japanese.

Basics

Base URL
https://michiyomi.dev
Auth
None. No sign-up and no API key.
Methods
Read-only. Besides GET, only POST /amenities/search (coordinates in the body) and POST /mcp. Write methods on /v1 return 405.
Format
JSON (UTF-8). Observation text is Japanese (data_language: "ja").
Rate limits
Per IP address: 300 REST requests and 120 MCP requests per 60 seconds. Over the limit you get 429 with retry-after: 60.
CORS
Open to all origins (access-control-allow-origin: *).
IDs
Keep Mapillary image IDs as strings. Converting them to numbers can lose digits.
Zero results
Zero results still return 200, usually with a note. Zero means not recorded, not absent in the real world.
Pagination
None. Nearby searches return at most 50 records. Move the center or change the radius to cover more ground.

Common fields

Successful /v1 responses share these fields. The per-endpoint examples below omit them.

FieldTypeDescription
api_version"v1"
data_languagestringLanguage of the observation text. Always "ja" for now (not yet in the OpenAPI file)
snapshotstring | nullrelease_id of the latest published release, or latest staged release if none is published
request_idstring(uuid)Generated by crypto.randomUUID(); included in every response and log entry
data_as_ofstring | null
quality_policyobject
licenseobjectConditions for each layer of the response. Values vary by product (scenes, streets and edges, town blocks, schools). See https://michiyomi.dev/docs/license/
notestringHonesty note covering experimental inclusion, zero results, sparse coverage, or data inconsistency. It never claims that zero records prove no real-world change occurred.
warningsstring[]Accepted but ignored legacy parameters and similar warnings
The start of a GET /v1/meta responseOpen raw ↗
{
  "api_version": "v1",
  "data_language": "ja",
  "snapshot": "2026-09-13-r1",
  "request_id": "b44f51c0-382e-445b-9013-a3f9e7ed500e",
  "data_as_of": "2026-09-13",
  "quality_policy": { "requested": "released", "generation": null, "experimental_included": false },
  "license": {
    "schema_version": 2,
    "id": "LicenseRef-michiyomi-layered",
    "url": "https://michiyomi.dev/docs/license/",
    "policy_version": "2026-10-03",
    "summary": "観測データ(本文・構造化JSON・機械層の値・経年変化)は CC BY 4.0 で使えます…",
    "summary_en": "Observation data (text, structured JSON, machine features, changes) is available under CC …",
    "obligations": {
      "use_in_results": ["none"],
      "display_or_quote_records": ["none"],
      "redistribute_as_data": ["attribution", "upstream_not_licensed_if_bulk", "source_notice_if_bulk"]
    },
    "notices": [
      "mapillary_reference_not_licensed",
      "photos_not_included",
      … 4 more
    ],
    "layers": {
      "observation": "CC-BY-4.0",
      "mapillary_reference": "NOASSERTION",
      "public_sector": "CC-BY-4.0"
    },
    "linked_only": { "photo": "CC-BY-SA-4.0" },
    "attribution": "出典: みちよみ(michiyomi.dev…",
    "attribution_en": "Source: michiyomi (michiyomi.dev), from Mapillary street-level photos, CC BY 4.0 (https://…",
    … 8 more fields
  }
}

Errors

4xx and 5xx responses use one JSON shape. Parameter errors name the parameter in field. Internal paths and SQL are never returned.

codeHTTPMeaning
invalid_parameter400Invalid parameter (out of range, unknown value, non-numeric string and so on)
not_found404No such record
method_not_allowed405The API is read-only, so that method is not allowed
payload_too_large413Body too large (64 KB for /mcp, 2048 bytes for /amenities/search)
rate_limited429Rate limit exceeded. Wait retry-after seconds
internal500Server-side problem. Contact us with the request_id
A real error: sending lat=135 · HTTP 400
{
  "error": {
    "code": "invalid_parameter",
    "message": "lat must be between -90 and 90",
    "request_id": "3c3760d3-c98e-4c66-bf6b-de444f8af988",
    "field": "lat"
  }
}

Scenes (one photo each)

The AI reading of each photo (scene). Check coverage first, find nearby photos with scenes/nearby, then read the full record with scenes/{id}.

GET/v1/coverage

Disclose data coverage at a point

Cache public, max-age=60

Reports how much evidence exists near a point. Zero results remain zero; missing dataset coverage must never be reinterpreted as evidence that a real-world feature or change is absent.

scenes_by_year, scenes_by_generation, and scenes_total are collapsed under the selected quality policy. released_count and experimental_count are actual verbalization counts within the radius, independent of the requested quality policy. n_changes counts only status='supported'. All exclude quarantine. year_from and year_to filter scene capture years only. n_changes includes all years; use the year parameters on /v1/changes/nearby to filter change periods.

Differs from the OpenAPI file (checked in production on 2026-10-03)
openapi.en.yaml sets the lower bound of year_from and year_to to 2000. Production accepts years from 1970.

Parameters

NameInTypeDescription
latrequiredquerynumberLatitude (WGS84), parsed strictly with /^-?\d+(\.\d+)?$/range -90–90
lonrequiredquerynumberLongitude (WGS84)range -180–180
radius_mqueryintegerdefault 300 · range 1–1000
qualityquerystringVerbalization-generation quality policy.
  • released (default): only generations with status='released'; highest version per location
  • include_experimental: one per location, preferring released by descending version, then experimental by descending version
  • experimental_only: experimental generations only
default "released" · values released include_experimental experimental_only
generationquerystringExplicit generation ID; takes precedence over quality; an unknown ID returns 400max 64 chars
year_fromqueryintegerrange 1970–2100
year_toqueryintegerReturns 400 unless year_from is less than or equal to year_torange 1970–2100

Legacy parameters accepted for compatibility (deprecated): radius (Legacy alias for radius_m; when both are present, radius_m takes precedence)

Example

curl "https://michiyomi.dev/v1/coverage?lat=35.6717&lon=139.7647"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "query": {
    "lat": 35.6717,
    "lon": 139.7647,
    "radius_m": 300,
    "year_from": null,
    "year_to": null
  },
  "scenes_total": 2312,
  "scenes_by_year": {
    "2010": 2,
    "2013": 4,
    "2015": 25,
    "2016": 324,
    "2017": 321,
    "2018": 581,
    "2019": 324,
    "2020": 51,
    "2022": 125,
    "2023": 206,
    "2024": 89,
    "2025": 67,
    "2026": 193
  },
  "scenes_by_generation": { "gen2-qwen-local": 1429, "gen1-codex": 883 },
  "released_count": 2312,
  "experimental_count": 0,
  "latest_year": 2026,
  "n_changes": 5,
  "candidate_truncated": false,
  "counting_notes": {
    "released_count": "この半径に released世代の言語化を持つシーン数(品質ポリシーに関わらず実数)",
    "experimental_count": "この半径に experimental世代の言語化を持つシーン数(同上)",
    "n_changes": "status='supported' の経年変化を全年で数えた件数(year_from/year_toはシーンの撮影年に…",
    "quarantine": "この地点クエリは capture_time_quality異常(quarantined=1)のシーンを全ての集計から除外…"
  }
}
Response fields
FieldTypeDescription
queryobject
scenes_totalinteger
scenes_by_yearobject<integer>Keys are capture years, or "unknown" when the capture year is unavailable
scenes_by_generationobject<integer>
released_countinteger
experimental_countinteger
latest_yearinteger | null
n_changesinteger
candidate_truncatedboolean
counting_notesobject<string>
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.

GET/v1/scenes/nearby

Search nearby scenes

alias /v1/nearbyCache public, max-age=60

Retrieves grid-cell y-bands one at a time in order of proximity to the query latitude, then applies an exact circular Haversine filter. Results are ordered by unrounded Haversine distance ASC, capture_year DESC for equal distances, then id ASC. distance_m is rounded only for display.

When the candidate limit is reached (8,000 within a band or cumulatively), candidate_truncated=true. Truncation always removes bands farther from the query center, so the true nearest records are retained even in dense areas. Scenes with quarantined=1 are excluded.

Differs from the OpenAPI file (checked in production on 2026-10-03)
openapi.en.yaml sets the lower bound of year_from and year_to to 2000. Production accepts years from 1970.

Parameters

NameInTypeDescription
latrequiredquerynumberLatitude (WGS84), parsed strictly with /^-?\d+(\.\d+)?$/range -90–90
lonrequiredquerynumberLongitude (WGS84)range -180–180
radius_mqueryintegerSearch radius in meters; integer onlydefault 150 · range 1–1000
limitqueryintegerNumber of records to return; default 10 for scenes and 20 for changesrange 1–50
qualityquerystringVerbalization-generation quality policy.
  • released (default): only generations with status='released'; highest version per location
  • include_experimental: one per location, preferring released by descending version, then experimental by descending version
  • experimental_only: experimental generations only
default "released" · values released include_experimental experimental_only
generationquerystringExplicit generation ID; takes precedence over quality; an unknown ID returns 400max 64 chars
year_fromqueryintegerrange 1970–2100
year_toqueryintegerReturns 400 unless year_from is less than or equal to year_torange 1970–2100

Legacy parameters accepted for compatibility (deprecated): radius (Legacy alias for radius_m; when both are present, radius_m takes precedence); gen (Legacy alias for generation); era (Legacy parameter. It is accepted but does not affect results. The warnings array reports); min_score (Legacy parameter. Like era, it is accepted but does not affect results)

Example

curl "https://michiyomi.dev/v1/scenes/nearby?lat=35.6717&lon=139.7647&radius_m=150&limit=2"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "query": {
    "lat": 35.6717,
    "lon": 139.7647,
    "radius_m": 150,
    "limit": 2,
    "year_from": null,
    "year_to": null
  },
  "count": 2,
  "results": [
    {
      "id": "964535250779795",
      "distance_m": 3,
      "capture_year": 2019,
      "ward": "中央区",
      "view_class": "全方位(パノラマ)",
      "generation": { "id": "gen1-codex", "status": "released", "version": 1 },
      "model": "gpt-5.6-sol",
      "summary": "施設: 一般道路 / 歩道: 左=あり(分離歩道,5m), 右=あり(分離歩道,4m), 有効幅約4m, 点字ブロックあ…",
      "image_page": "https://www.mapillary.com/app/?pKey=964535250779795",
      … 8 more fields
    },
    {
      "id": "328331618839370",
      "distance_m": 4,
      "capture_year": 2018,
      "ward": "中央区",
      "view_class": "前方視",
      "generation": { "id": "gen1-codex", "status": "released", "version": 1 },
      "model": "gpt-5.6-terra",
      "summary": "施設: 一般道路 / 歩道: 左=あり(分離歩道,3m), 右=あり(分離歩道,4m), 有効幅約2.5m, 車道幅約1…",
      "image_page": "https://www.mapillary.com/app/?pKey=328331618839370",
      … 8 more fields
    }
  ],
  "candidate_truncated": false
}
Response fields
FieldTypeDescription
queryobject
query.latnumber
query.lonnumber
query.radius_minteger
query.limitinteger
query.year_frominteger | null
query.year_tointeger | null
countinteger
resultsobject[]
results[].idstringMapillary image ID. Do not convert it to a number.
results[].distance_minteger
results[].latnumber
results[].lonnumber
results[].position_sourcestringSource of the representative coordinate; computed is Mapillary-corrected, raw is GPSvalues mapillary_computed mapillary_raw
results[].capture_yearinteger | null
results[].yearinteger | nullAlias of capture_year for MCP and legacy-client compatibility
results[].wardstring | null
results[].view_classstring | null
results[].travel_bearingnumber | null
results[].is_panoboolean | null
results[].generationobject
results[].modelstring | null
results[].prompt_versionstring | null
results[].summarystringPrecomputed Japanese streetscape summary
results[].analysis_statusstringvalues ok invalid
results[].image_pagestring(uri)
candidate_truncatedboolean
Status codes
  • 200 OK (200 is returned even for zero results)
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

GET/v1/scenes/{id}

Scene detail

alias /v1/node/{id}Cache public, max-age=86400

When include is omitted, only analysis is requested (compatible with legacy /v1/node/{id}).

  • If no verbalization matches the selected quality policy, the endpoint still returns 200 with verbalization: null, a note, and available_generations; it never falls back automatically.
  • Invalid stored analysis returns analysis: null and analysis_status: "invalid", not a 500 response.
  • A quarantined scene is returned with 200 when looked up directly by ID, together with capture_time_quality and a note.

Parameters

NameInTypeDescription
idrequiredpathstringMapillary image ID(string)
includequerystringComma-separated layers to retrieve. Unknown values or an empty string return 400.default "analysis" · example analysis metadata,machine,analysis
qualityquerystringVerbalization-generation quality policy.
  • released (default): only generations with status='released'; highest version per location
  • include_experimental: one per location, preferring released by descending version, then experimental by descending version
  • experimental_only: experimental generations only
default "released" · values released include_experimental experimental_only
generationquerystringExplicit generation ID; takes precedence over quality; an unknown ID returns 400max 64 chars

Legacy parameters accepted for compatibility (deprecated): gen (Legacy alias for generation)

Example

curl "https://michiyomi.dev/v1/scenes/1499911054492109?include=metadata,machine,analysis"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "scene": {
    "id": "1499911054492109",
    "lat": 35.688942434653,
    "lon": 139.72195407201,
    "position_source": "mapillary_computed",
    "capture_year": 2025,
    "capture_time_quality": "ok",
    "ward": "新宿区",
    "quarantined": false
  },
  "image_page": "https://www.mapillary.com/app/?pKey=1499911054492109",
  "available_generations": [
    { "id": "gen2-qwen-local", "status": "released", "version": 2 }
  ],
  "include": ["analysis", "machine", "metadata"],
  "verbalization": {
    "generation": { "id": "gen2-qwen-local", "status": "released", "version": 2 },
    "model": "sakamakismile/Qwen3.8-27B-MTP-NVFP4",
    "prompt_version": "v3.5a-tf-nothink",
    "generated_at": "2026-08-15T19:53:11Z",
    "summary": "施設: 一般道路 / 歩道: 左=あり(路側帯,1.5m), 右=画角外不明, 有効幅約1.5m, 車道幅約4m / 舗…",
    "analysis_status": "ok",
    "content_sha256": "d4b3fc750fc0542d5df071c7cfa54a65e9aa9801af02dfacd11846e06c6d…",
    "analysis": {
      "image_file": "image.png",
      "capture_meta": {…},
      "road_context": "両側に木造の店舗・住居が立ち並ぶ狭い市街地の路地…",
      "road_structure": { "type": "平面", "facility_type": "一般道路", "grade_separated_crossing": "なし" },
      "geometry": {…},
      "pavement": {…},
      "markings_wear": […],
      "infrastructure": {…},
      "mobility": {…},
      "accessibility": {…},
      … 9 more fields
    }
  },
  "metadata": {
    "raw_lat": 35.6889384,
    "raw_lon": 139.7219968,
    "computed_lat": 35.688942434653,
    "computed_lon": 139.72195407201,
    "position_source": "mapillary_computed",
    "position_offset_m": 3.9,
    "raw_compass": 264.84407438728863,
    "computed_compass": 262.94484333912,
    "travel_bearing": 224.9,
    "view_class": "前方視",
    … 11 more fields
  },
  "machine": {
    "node_id": "1499911054492109",
    "feature_version": "ml-2026-09-13",
    "month": 10,
    "weekday": "火",
    "hour": 15,
    "season": "秋",
    "time_bucket": "昼",
    "heading": 262.94484333912,
    "heading8": "西",
    "left_side8": "南東",
    … 7 more fields
  },
  "machine_note": "機械層(画像処理由来の客観指標)…"
}
Response fields
FieldTypeDescription
sceneobject
scene.idstring
scene.latnumber
scene.lonnumber
scene.position_sourcestringvalues mapillary_computed mapillary_raw
scene.capture_yearinteger | null
scene.capture_time_qualitystringvalues ok epoch_anomaly unknown
scene.wardstring | null
scene.quarantinedboolean
image_pagestring(uri)
available_generationsobject[]
available_generations[].idstring
available_generations[].statusstringvalues experimental released deprecated
available_generations[].versioninteger
includestring[]values metadata machine analysis
verbalizationnull | object
verbalization.generationobject
verbalization.modelstring | null
verbalization.prompt_versionstring | null
verbalization.generated_atstring | null
verbalization.summarystring
verbalization.analysis_statusstringvalues ok invalid
verbalization.content_sha256string
verbalization.analysisobject | nullFull Japanese verbalization as structured JSON. Present only when include contains analysis. It is null, rather than causing a 500 response, when analysis_status = "invalid".
metadataobjectPresent only when include=metadata
metadata.raw_latnumber | null
metadata.raw_lonnumber | null
metadata.computed_latnumber | null
metadata.computed_lonnumber | null
metadata.position_sourcestring
metadata.position_offset_mnumber | nullDistance in meters between raw and computed coordinates; null if either is missing
metadata.raw_compassnumber | null
metadata.computed_compassnumber | null
metadata.travel_bearingnumber | null
metadata.view_classstring | null
metadata.sequence_idstring | null
metadata.is_panoboolean | null
metadata.quality_scorenumber | null
metadata.camera_typestring | null
metadata.widthinteger | null
metadata.heightinteger | null
metadata.captured_at_msinteger | null
metadata.captured_at_jststring | null
metadata.capture_time_qualitystring
metadata.cell_250minteger
metadata.position_notestring
machinenull | objectPresent only when include=machine. Contains objective indicators derived from image processing and is null when no machine row exists. This is a separate namespace from VLM verbalization and should not be blended with it during interpretation.
machine.node_idstring
machine.feature_versionstring
machine.monthinteger | null
machine.weekdaystring | null
machine.hourinteger | null
machine.seasonstring | null
machine.time_bucketstring | null
machine.headingnumber | null
machine.heading8string | null
machine.left_side8string | null
machine.right_side8string | null
machine.abs_objects
machine.colorfulnessnumber | null
machine.green_rationumber | null
machine.warm_rationumber | null
machine.dominant_colors
machine.color_statusstring | null
machine_notestring
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 404 The requested resource does not exist
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

Streets (lines)

Street kartes for named streets, and numbers for unnamed road segments. Karte text is Japanese. See Reading the data.

GET/v1/streets/nearby

Nearest named streets (lines) and unnamed edges

Cache public, max-age=60

Finds road edges (OSM ways cut at intersections, >=15 scenes) within radius_m and groups them by named street (same-name edges within a ward), nearest first. Unnamed roads are returned as unnamed_edges. Karte text is at /v1/streets/{street_id}.

Parameters

NameInTypeDescription
latrequiredquerynumberLatitude (WGS84), parsed strictly with /^-?\d+(\.\d+)?$/range -90–90
lonrequiredquerynumberLongitude (WGS84)range -180–180
radius_mqueryintegerdefault 60 · range 1–500
limitqueryintegerdefault 5 · range 1–20

Example

curl "https://michiyomi.dev/v1/streets/nearby?lat=35.6717&lon=139.7647"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "la_release": "2026-10-03-la2",
  "la_counts": {
    "streets": 6248,
    "areas": 5256,
    "edges": 30362,
    "karte_streets": 3563,
    "karte_areas": 4734
  },
  "query": { "lat": 35.6717, "lon": 139.7647, "radius_m": 60, "limit": 5 },
  "streets": [
    {
      "street_id": 799,
      "name": "晴海通り",
      "ward": "中央区",
      "highway_class": "幹線",
      "length_m": 4480,
      "coverage_grade": "A",
      "n_scenes": 1739,
      "n_sequences": 121,
      "year_span": [2013, 2026],
      "bbox": [35.6575946, 139.7622352, 35.6730203, 139.7794593],
      "has_karte": true,
      "nearest_edge": { "edge_id": "884274229_3", "dist_m": 29 }
    },
    {
      "street_id": 720,
      "name": "中央通り",
      "ward": "中央区",
      "highway_class": "幹線",
      "length_m": 5337,
      "coverage_grade": "A",
      "n_scenes": 2244,
      "n_sequences": 222,
      "year_span": [2010, 2026],
      "bbox": [35.6674922, 139.7611031, 35.6899098, 139.7746484],
      "has_karte": true,
      "nearest_edge": { "edge_id": "1026056857_1", "dist_m": 54.1 }
    }
  ],
  "unnamed_edges": [
    {
      "edge_id": "522859644_1",
      "highway_class": "歩道・歩行者路",
      "length_m": 71,
      "n_scenes": 16,
      "dist_m": 50.5,
      "town_key": "13102003004",
      "ward": "中央区"
    }
  ],
  "n_edges_considered": 3,
  "notes": {
    "grade": "coverage_grade は被覆等級…",
    "rates": "率(sidewalk.rate など)は判定できた件数(judged)が分母…",
    "years": "統計は複数年の集計…",
    "sides": "通りの sides は軸に対する絶対方位の側(例: 北東側)…",
    "versions": "karte は主版(karte_provenance.model)…",
    "license": "通り・町丁目の骨格は © OpenStreetMap contributors(ODbL 1.0)…"
  }
}
Response fields
FieldTypeDescription
queryobject
streetsobject[]
streets[].street_idinteger
streets[].namestring
streets[].wardstring | null
streets[].highway_classstring | null幹線 (arterial)
streets[].length_minteger | null
streets[].coverage_gradestringvalues A B C D
streets[].n_scenesinteger
streets[].n_sequencesinteger | null
streets[].year_spaninteger | null[]
streets[].bboxnumber | null[]min_lat, min_lon, max_lat, max_lon の順
streets[].has_karteboolean
streets[].nearest_edgeobject
unnamed_edgesobject[]
n_edges_consideredinteger
notesobject
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 404 The requested resource does not exist
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

GET/v1/streets/{street_id}

Street karte and aggregated profile

Cache public, max-age=86400

Street-level verbalization. karte is Japanese text synthesized by a local LLM only from profile (aggregated scene observations; rates use judged counts as denominators, with year spans) and machine-checked so that numbers, years and proper nouns exist in the profile. coverage_grade D has no karte. include=profile,axis,edges adds the profile, the axis polyline and the edge list.

Parameters

NameInTypeDescription
street_idrequiredpathintegermin 1
includequerystringcomma-separated list of profile, axis, edges, versions (versions = karte text of other model versions)

Example

curl "https://michiyomi.dev/v1/streets/799"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "la_release": "2026-10-03-la2",
  "street_id": 799,
  "name": "晴海通り",
  "ward": "中央区",
  "highway_class": "幹線",
  "length_m": 4480,
  "coverage_grade": "A",
  "n_scenes": 1739,
  "year_span": [2013, 2026],
  "has_karte": true,
  "karte": {
    "street_id": "799",
    "name": "晴海通り(中央区)",
    "character": "区全体より幅の広い複数車線の車道が北西へ延び…",
    "tsuranari": "2013…",
    "sides": "南西側・北東側とも歩道がほぼ途切れずに続き…",
    "streetscape": "高層ビルの多くは築年の新しい外観で…",
    "walking": "判定できた1,906側のうち約98%に車道と分離された歩道があり…",
    "notable": "観測文には…",
    "changes_summary": "裁定済みの変化は記録にない…",
    "coverage_note": "被覆はA(2013…",
    "evidence_ids": [
      "1516117756754071",
      … 4 more
    ]
  },
  "karte_provenance": {
    "model": "opus55-v12-xhigh",
    "prompt": "prompt_street_v1_2.md",
    "generated_at": "2026-09-24 20:04:34",
    "note": "素材束(profile)だけから生成し…"
  },
  "karte_versions": [
    {
      "tag": "fable-low",
      "model": "fable-low",
      "prompt": "prompt_street_v1_1.md",
      "generated_at": "2026-09-22 13:35:28"
    },
    … 2 more
  ],
  … 4 more fields
}
Response fields
FieldTypeDescription
street_idinteger
namestring
wardstring | null
highway_classstring | null幹線 (arterial)
length_minteger | null
coverage_gradestringvalues A B C D
n_scenesinteger
n_sequencesinteger | null
year_spaninteger | null[]
bboxnumber | null[]min_lat, min_lon, max_lat, max_lon の順
has_karteboolean
karteobject | nullStreet karte (Japanese; keys name/character/tsuranari/sides/streetscape/walking/notable/changes_summary/coverage_note/evidence_ids). null for grade D.
karte_provenanceobject | null
karte_versionsobject[]Karte versions (tag/model/prompt/generated_at; include=versions adds each karte text)
profileobjectAggregated profile (include=profile). Rates use judged as denominator; judged_rate is the share of scenes that could be judged.
axisnumber[][]Axis polyline; each element is lat, lon (include=axis)
edgesobject[]
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 404 The requested resource does not exist
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

GET/v1/edges/{edge_id}

Numbers for an unnamed road edge

Cache public, max-age=86400

Aggregated numbers for one road edge (OSM way cut at intersections, >=15 scenes). Karte text is provided at street and area level only.

Parameters

NameInTypeDescription
edge_idrequiredpathstring^[0-9]+_[0-9]+$

Example

curl "https://michiyomi.dev/v1/edges/522859644_1"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "la_release": "2026-10-03-la2",
  "la_counts": {…},
  "edge_id": "522859644_1",
  "street_id": null,
  "town_key": "13102003004",
  "name": null,
  "ward": "中央区",
  "highway_class": "歩道・歩行者路",
  "length_m": 71,
  "n_scenes": 16,
  "geom": [
    [35.6720502, 139.7657558],
    [35.6715701, 139.7652352]
  ],
  "profile": {
    "edge_id": "522859644_1",
    "street_id": null,
    "name": null,
    "ward": "中央区",
    "town_key": "13102003004",
    "highway": "footway",
    "highway_class": "歩道・歩行者路",
    "length_m": 71,
    "stats": {…},
    "evidence": […]
  },
  … 1 more fields
}
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 404 The requested resource does not exist
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

Town blocks (areas)

Area kartes for 2020 census small areas (town blocks). Karte text is Japanese.

GET/v1/areas/at

Town block (2020 census small area) containing a point

Cache public, max-age=60

Returns the 2020 census small area (town block) that contains the point. Area karte is at /v1/areas/{town_key}.

Parameters

NameInTypeDescription
latrequiredquerynumberLatitude (WGS84), parsed strictly with /^-?\d+(\.\d+)?$/range -90–90
lonrequiredquerynumberLongitude (WGS84)range -180–180

Example

curl "https://michiyomi.dev/v1/areas/at?lat=35.6717&lon=139.7647"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "la_release": "2026-10-03-la2",
  "la_counts": {…},
  "query": { "lat": 35.6717, "lon": 139.7647 },
  "area": {
    "town_key": "13102003004",
    "name": "銀座四丁目",
    "ward": "中央区",
    "coverage_grade": "A",
    "n_scenes": 1001,
    "n_sequences": 115,
    "year_span": [2010, 2026],
    "center": { "lat": 35.671029, "lon": 139.766331 },
    "bbox": [35.66845943310958, 139.7626621643848, 35.67364263757046, 139.7695740383911],
    "has_karte": true
  },
  "notes": {…}
}
Response fields
FieldTypeDescription
queryobject
areaobject | null
area.town_keystring2020 census small-area key
area.namestring
area.wardstring
area.coverage_gradestringvalues A B C D
area.n_scenesinteger
area.n_sequencesinteger | null
area.year_spaninteger | null[]
area.centerobject
area.bboxnumber | null[]
area.has_karteboolean
Status codes
  • 200 OK (area is null when no town block contains the point)
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

GET/v1/areas/nearby

Town blocks whose centers are near a point

Cache public, max-age=60

Parameters

NameInTypeDescription
latrequiredquerynumberLatitude (WGS84), parsed strictly with /^-?\d+(\.\d+)?$/range -90–90
lonrequiredquerynumberLongitude (WGS84)range -180–180
radius_mqueryintegerdefault 800 · range 1–3000
limitqueryintegerdefault 5 · range 1–20

Example

curl "https://michiyomi.dev/v1/areas/nearby?lat=35.6717&lon=139.7647&limit=2"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "la_release": "2026-10-03-la2",
  "la_counts": {…},
  "query": { "lat": 35.6717, "lon": 139.7647, "radius_m": 800, "limit": 2 },
  "count": 2,
  "results": [
    {
      "town_key": "13102003004",
      "name": "銀座四丁目",
      "ward": "中央区",
      "coverage_grade": "A",
      "n_scenes": 1001,
      "n_sequences": 115,
      "year_span": [2010, 2026],
      "center": { "lat": 35.671029, "lon": 139.766331 },
      "bbox": [35.66845943310958, 139.7626621643848, 35.67364263757046, 139.7695740383911],
      "has_karte": true,
      "center_dist_m": 165
    },
    {
      "town_key": "13102003005",
      "name": "銀座五丁目",
      "ward": "中央区",
      "coverage_grade": "A",
      "n_scenes": 991,
      "n_sequences": 131,
      "year_span": [2010, 2026],
      "center": { "lat": 35.670158, "lon": 139.765335 },
      "bbox": [35.667463339979385, 139.76039842376687, 35.67296422354896, 139.7683763995818],
      "has_karte": true,
      "center_dist_m": 181
    }
  ],
  "notes": {…}
}
Response fields
FieldTypeDescription
queryobject
countinteger
resultsobject[]
results[].town_keystring2020 census small-area key
results[].namestring
results[].wardstring
results[].coverage_gradestringvalues A B C D
results[].n_scenesinteger
results[].n_sequencesinteger | null
results[].year_spaninteger | null[]
results[].centerobject
results[].bboxnumber | null[]
results[].has_karteboolean
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

GET/v1/areas/{town_key}

Area karte and aggregated profile

Cache public, max-age=86400

Area-level verbalization; karte generation and grade handling are the same as /v1/streets/{street_id}. include=profile,geometry adds the profile and the simplified GeoJSON geometry.

Parameters

NameInTypeDescription
town_keyrequiredpathstring^[0-9]{9,12}$
includequerystring

Example

curl "https://michiyomi.dev/v1/areas/13102003004"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "la_release": "2026-10-03-la2",
  "town_key": "13102003004",
  "name": "銀座四丁目",
  "ward": "中央区",
  "coverage_grade": "A",
  "n_scenes": 1001,
  "year_span": [2010, 2026],
  "has_karte": true,
  "karte": {
    "town_key": "13102003004",
    "name": "銀座四丁目(中央区)",
    "character": "ガラス張りの高層オフィスビルと商業ビルが広い幹線沿いに連なり…",
    "skeleton": "晴海通り・中央通り・昭和通りの幹線が骨格をなし…",
    "streetscape": "2010…",
    "walking": "判定できた1,224側のうち約99%に歩道があり…",
    "notable": "観測文には…",
    "changes_summary": "裁定済みの変化は記録にない…",
    "compared_to": "車道幅の中央値は約12.0mで中央区・都全体のいずれより広く…",
    "coverage_note": "等級A…",
    "evidence_ids": [
      "1244325431140140",
      … 4 more
    ]
  },
  "karte_provenance": {
    "model": "opus55-v12-xhigh",
    "prompt": "prompt_area_v1_2.md",
    "generated_at": "2026-09-25 10:43:56",
    "note": "素材束(profile)だけから生成し…"
  },
  "karte_versions": [
    {
      "tag": "fable-low",
      "model": "fable-low",
      "prompt": "prompt_area_v1_1.md",
      "generated_at": "2026-09-22 19:32:08"
    },
    … 2 more
  ],
  … 5 more fields
}
Response fields
FieldTypeDescription
town_keystring2020 census small-area key
namestring
wardstring
coverage_gradestringvalues A B C D
n_scenesinteger
n_sequencesinteger | null
year_spaninteger | null[]
centerobject
center.latnumber
center.lonnumber
bboxnumber | null[]
has_karteboolean
karteobject | nullArea karte (Japanese; keys name/character/skeleton/streetscape/walking/notable/changes_summary/compared_to/coverage_note/evidence_ids). null for grade D.
karte_provenanceobject | null
profileobject
geometryobjectSimplified GeoJSON geometry (include=geometry)
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 404 The requested resource does not exist
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

Changes over time

Changes found by comparing photos of the same place from different years, returned only if they survived an attempt to refute them.

GET/v1/changes/nearby

Search nearby adjudicated longitudinal changes

Cache public, max-age=60

The default is status=supported, meaning the claim survived falsification-oriented re-evaluation. evidence is truncated to 200 Japanese characters and sets evidence_truncated; use the detail endpoint for the full text. Coordinates are the center of the road group (group_id), not the exact changed object. Ordering is distance_m ASC, then year_b DESC, then change_id ASC.

quality and generation are validated as strictly as on other endpoints (unknown values return 400), but longitudinal changes are a separate layer from verbalization generations, so these parameters do not filter results; they are reflected only in quality_policy and field_notes.quality.

Differs from the OpenAPI file (checked in production on 2026-10-03)
openapi.en.yaml sets the lower bound of year_from and year_to to 2000. Production accepts years from 1970.

Parameters

NameInTypeDescription
latrequiredquerynumberLatitude (WGS84), parsed strictly with /^-?\d+(\.\d+)?$/range -90–90
lonrequiredquerynumberLongitude (WGS84)range -180–180
radius_mqueryintegerdefault 500 · range 1–3000
limitqueryintegerNumber of records to return; default 10 for scenes and 20 for changesrange 1–50
categoryquerystringJapanese change category. Values mean equipment, building, road marking, pavement, roadside use, vegetation, and other.values 設備 建物 区画線・標示 舗装 沿道用途 植栽 その他
statusquerystringdefault "supported" · values supported refuted unverifiable withdrawn
year_fromqueryintegerrange 1970–2100
year_toqueryintegerReturns 400 unless year_from is less than or equal to year_torange 1970–2100
qualityquerystringVerbalization-generation quality policy.
  • released (default): only generations with status='released'; highest version per location
  • include_experimental: one per location, preferring released by descending version, then experimental by descending version
  • experimental_only: experimental generations only
default "released" · values released include_experimental experimental_only
generationquerystringExplicit generation ID; takes precedence over quality; an unknown ID returns 400max 64 chars

Legacy parameters accepted for compatibility (deprecated): radius (Legacy alias for radius_m; when both are present, radius_m takes precedence)

Example

curl "https://michiyomi.dev/v1/changes/nearby?lat=35.6717&lon=139.7647&radius_m=500&limit=2"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "query": {
    "lat": 35.6717,
    "lon": 139.7647,
    "radius_m": 500,
    "limit": 2,
    "category": null,
    "status": "supported",
    "year_from": null,
    "year_to": null
  },
  "count": 2,
  "results": [
    {
      "change_id": "chg_4424424a5b4f",
      "group_id": 1670,
      "distance_m": 233,
      "lat": 35.669806875,
      "lon": 139.763595175,
      "year_a": 2017,
      "year_b": 2026,
      "category": "設備",
      "subject": "GINZA SIX前のタクシー関連標識",
      "evidence": "右側のGINZA SIX緑色外壁前にあり…",
      "evidence_truncated": false,
      "segment_priority_score": 10,
      "status": "supported"
    },
    {
      "change_id": "chg_e9d920b5c524",
      "group_id": 1670,
      "distance_m": 233,
      "lat": 35.669806875,
      "lon": 139.763595175,
      "year_a": 2017,
      "year_b": 2026,
      "category": "植栽",
      "subject": "GINZA SIX前を含む両側歩道の街路樹",
      "evidence": "2017年のフレーム1…",
      "evidence_truncated": false,
      "segment_priority_score": 10,
      "status": "supported"
    }
  ],
  "candidate_truncated": false,
  "field_notes": {
    "segment_priority_score": "道路区間の点検優先度ヒューリスティック(変化自体の危険度ではない)…",
    "change_position": "lat/lon は変化地点そのものではなく…",
    "verification": "同一モデル系列の文脈分離した別セッションによる反証優先の再検証を通過した(verdict=supported)所見のみを…",
    "quality": "経年変化は言語化世代(generation)とは別レイヤ…"
  }
}
Response fields
FieldTypeDescription
queryobject
countinteger
resultsobject[]
results[].change_idstring
results[].group_idintegerRoad-group ID, formerly gid
results[].distance_minteger
results[].latnumberRoad-group center coordinate, not the exact changed-object location
results[].lonnumber
results[].year_ainteger
results[].year_binteger
results[].categorystringJapanese enum value for equipment, building, road marking, pavement, roadside use, vegetation, or othervalues 設備 建物 区画線・標示 舗装 沿道用途 植栽 その他
results[].subjectstringJapanese change subject, formerly what
results[].evidencestring | nullJapanese evidence truncated to 200 characters
results[].evidence_truncatedboolean
results[].segment_priority_scoreinteger | nullRoad-segment inspection-priority heuristic, formerly max_risk. This is not the danger or severity of the change itself. It is null for many rows.
results[].statusstringvalues supported refuted unverifiable withdrawn
candidate_truncatedboolean
field_notesobject<string>
Status codes
  • 200 OK
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.

GET/v1/changes/{change_id}

Longitudinal-change detail

Cache public, max-age=86400

Returns full Japanese evidence and verification metadata from falsification-oriented re-evaluation. scene_ids_a and scene_ids_b are null for every row in this release because the source data does not contain them. The service does not fabricate IDs and discloses this in note.

Parameters

NameInTypeDescription
change_idrequiredpathstring^chg_[0-9a-f]{12}$

Example

curl "https://michiyomi.dev/v1/changes/chg_4424424a5b4f"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "change": {
    "change_id": "chg_4424424a5b4f",
    "group_id": 1670,
    "lat": 35.669806875,
    "lon": 139.763595175,
    "cell_1km": 174101796,
    "year_a": 2017,
    "year_b": 2026,
    "category": "設備",
    "subject": "GINZA SIX前のタクシー関連標識",
    "evidence": "右側のGINZA SIX緑色外壁前にあり…",
    "scene_ids_a": null,
    "scene_ids_b": null,
    "segment_priority_score": 10,
    "status": "supported",
    "verification": {
      "method": "same-model independent-context adversarial review",
      "method_ja": "同一モデル系列の文脈分離した別セッションによる反証優先の再検証",
      "detector_model": "gpt-5.6-sol",
      "reviewer_model": "gpt-5.6-sol",
      "same_model_family": true,
      "verdict": "supported",
      "limitations": ["shared systematic errors may remain", "supported率は反証パスの生存率であり精度の下限保証ではない"]
    }
  },
  "field_notes": {
    "segment_priority_score": "道路区間の点検優先度ヒューリスティック(変化自体の危険度ではない)…",
    "change_position": "lat/lon は変化地点そのものではなく…",
    "verification": "同一モデル系列の文脈分離した別セッションによる反証優先の再検証を通過した(verdict=supported)所見のみを…"
  }
}
Response fields
FieldTypeDescription
changeobject
change.change_idstring
change.group_idintegerRoad-group ID, formerly gid
change.distance_minteger
change.latnumberRoad-group center coordinate, not the exact changed-object location
change.lonnumber
change.year_ainteger
change.year_binteger
change.categorystringJapanese enum value for equipment, building, road marking, pavement, roadside use, vegetation, or othervalues 設備 建物 区画線・標示 舗装 沿道用途 植栽 その他
change.subjectstringJapanese change subject, formerly what
change.evidencestring | nullFull Japanese evidence text
change.evidence_truncatedboolean
change.segment_priority_scoreinteger | nullRoad-segment inspection-priority heuristic, formerly max_risk. This is not the danger or severity of the change itself. It is null for many rows.
change.statusstringvalues supported refuted unverifiable withdrawn
change.cell_1kminteger
change.scene_ids_astring[] | nullAlways null in this release because the source data does not contain these IDs
change.scene_ids_bstring[] | null
change.verificationobject | nullAdjudication metadata. method_ja contains the Japanese method label meaning a falsification-oriented re-evaluation by a separate, context-isolated session from the same model family.
field_notesobject<string>
Status codes
  • 200 OK
  • 404 The requested resource does not exist
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.

Amenities

Capture points of photos in which a vending machine, toilet or bench was seen.

GET/v1/amenities/nearby

Nearby amenity observations (vending machines, toilets, benches)

Cache no-store

Returns capture points of photos in which the amenity (kind) was seen, nearest first by straight-line distance. Coordinates and distances refer to where the photo was taken. The amenity position, whether it is still there and whether it is usable are not verified. Omitting year_from includes all years. To keep a visitor location out of URLs, use POST /amenities/search.

Differs from the OpenAPI file (checked in production on 2026-10-03)
openapi.en.yaml lists only vending_machine for kind. Production also accepts toilet and bench.

Parameters

NameInTypeDescription
latrequiredquerynumberLatitude (WGS84), parsed strictly with /^-?\d+(\.\d+)?$/range -90–90
lonrequiredquerynumberLongitude (WGS84)range -180–180
kindquerystringAmenity kind: vending_machine, toilet or benchdefault "vending_machine" · values vending_machine toilet bench
radius_mqueryintegerdefault 1000 · range 100–3000
limitqueryintegerdefault 3 · range 1–10
year_fromqueryintegerrange 2000–2100

Example

curl "https://michiyomi.dev/v1/amenities/nearby?lat=35.6717&lon=139.7647&kind=bench&limit=2"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "count": 2,
  "results": [
    {
      "id": "bn_1470fb07087f1e7c",
      "lat": 35.67205272116,
      "lon": 139.76419890994,
      "position_basis": "capture_location",
      "scene_id": "529346588414766",
      "capture_year": 2019,
      "evidence": "ベンチ:良好",
      "object_position": "右",
      "object_distance_m_est": 10,
      "confidence": "high",
      "image_page": "https://www.mapillary.com/app/?pKey=529346588414766",
      "generation_id": "gen2-qwen-local",
      "ward": "中央区",
      "evidence_count": 1,
      "distance_m": 60
    },
    {
      "id": "bn_235844e9fd8e40d2",
      "lat": 35.672235417637,
      "lon": 139.76394183294,
      "position_basis": "capture_location",
      "scene_id": "2910127179305154",
      "capture_year": 2019,
      "evidence": "ベンチ:良好",
      "object_position": "中央",
      "object_distance_m_est": 5,
      "confidence": "high",
      "image_page": "https://www.mapillary.com/app/?pKey=2910127179305154",
      "generation_id": "gen2-qwen-local",
      "ward": "中央区",
      "evidence_count": 1,
      "distance_m": 91
    }
  ],
  "dataset": {
    "kind": "bench",
    "source_snapshot": "2026-09-13-r1",
    "built_at": "2026-09-17T17:43:39.549691Z",
    "total_candidates": 16849,
    "min_year": 2006,
    "max_year": 2026
  },
  "query": {
    "lat": 35.6717,
    "lon": 139.7647,
    "radius_m": 1000,
    "limit": 2,
    "year_from": null,
    "kind": "bench"
  }
}
Response fields
FieldTypeDescription
countinteger
queryobject
datasetobject
dataset.source_snapshotstring
dataset.built_atstring
dataset.total_candidatesinteger
dataset.min_yearinteger | null
dataset.max_yearinteger | null
resultsobject[]
results[].idstring
results[].scene_idstring
results[].latnumber
results[].lonnumber
results[].position_basis"capture_location"
results[].distance_minteger
results[].capture_yearinteger
results[].evidencestring
results[].object_positionstring | null
results[].object_distance_m_estnumber | null
results[].confidencestringvalues high medium
results[].image_pagestring(uri)
results[].generation_idstring
results[].wardstring | null
results[].evidence_countinteger
Status codes
  • 200 OK (Cache-Control is no-store)
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

POST/amenities/search

Amenity search with coordinates in the body

alias /vending/searchCache no-store

Returns the same result as GET /v1/amenities/nearby. Coordinates travel in the JSON body (2048 bytes at most), so they stay out of URLs. Nothing is written.

Differs from the OpenAPI file (checked in production on 2026-10-03)
openapi.en.yaml lists this endpoint under its alias /vending/search. Both return the same result, and kind also accepts toilet and bench.

Body (JSON)

NameInTypeDescription
latrequiredbodynumberrange -90–90
lonrequiredbodynumberrange -180–180
radius_mbodyintegerdefault 1000 · range 100–3000
limitbodyintegerdefault 3 · range 1–10
kindbodystringdefault "vending_machine" · values vending_machine toilet bench
year_frombodyinteger | nullrange 2000–2100

Example

curl -X POST "https://michiyomi.dev/amenities/search" -H "content-type: application/json" \ -d '{"lat":35.6717,"lon":139.7647,"kind":"bench","limit":2}'
Response (excerpt) · HTTP 200
// common fields (snapshot, license and so on) omitted
{
  "count": 2,
  "results": [
    {
      "id": "bn_1470fb07087f1e7c",
      "lat": 35.67205272116,
      "lon": 139.76419890994,
      "position_basis": "capture_location",
      "scene_id": "529346588414766",
      "capture_year": 2019,
      "evidence": "ベンチ:良好",
      "object_position": "右",
      "object_distance_m_est": 10,
      "confidence": "high",
      "image_page": "https://www.mapillary.com/app/?pKey=529346588414766",
      "generation_id": "gen2-qwen-local",
      "ward": "中央区",
      "evidence_count": 1,
      "distance_m": 60
    },
    … 1 more
  ],
  "dataset": {
    "kind": "bench",
    "source_snapshot": "2026-09-13-r1",
    "built_at": "2026-09-17T17:43:39.549691Z",
    "total_candidates": 16849,
    "min_year": 2006,
    "max_year": 2026
  },
  "query": {
    "lat": 35.6717,
    "lon": 139.7647,
    "radius_m": 1000,
    "limit": 2,
    "year_from": null,
    "kind": "bench"
  }
}
Response fields
FieldTypeDescription
countinteger
queryobject
datasetobject
dataset.source_snapshotstring
dataset.built_atstring
dataset.total_candidatesinteger
dataset.min_yearinteger | null
dataset.max_yearinteger | null
resultsobject[]
results[].idstring
results[].scene_idstring
results[].latnumber
results[].lonnumber
results[].position_basis"capture_location"
results[].distance_minteger
results[].capture_yearinteger
results[].evidencestring
results[].object_positionstring | null
results[].object_distance_m_estnumber | null
results[].confidencestringvalues high medium
results[].image_pagestring(uri)
results[].generation_idstring
results[].wardstring | null
results[].evidence_countinteger
Status codes
  • 200 OK (Cache-Control is no-store)
  • 400 Invalid parameter (negative value, NaN, Infinity, empty string, nonnumeric text, unknown enum, or out of range)
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.
  • 413 Request body exceeds 2048 bytes
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.
  • 500 Internal error. Responses never expose stack traces, SQL, or internal paths. Details are recorded only in server logs with the request_id.

Schools

Tokyo elementary-school locations (National Land Numerical Information P29), useful for turning a school name into coordinates.

Catalog

Release, counts, generations and provenance: information about the data itself.

GET/v1/meta

Release counts and generation catalog

Cache public, max-age=300

Returns the published release, counts and the generation catalog. Counts come from release_stats, fixed at release time, so nothing is recounted per request. processed_total and machine_feature_rows include quarantined scenes. The other counts and year_min and year_max exclude them (see counting_notes).

Differs from the OpenAPI file (checked in production on 2026-10-03)
Unlike the description in openapi.en.yaml, processed_total and machine_feature_rows include quarantined scenes (see counting_notes in the response).

Example

curl "https://michiyomi.dev/v1/meta"
Response (excerpt) · HTTP 200Open raw ↗
{
  "api_version": "v1",
  "data_language": "ja",
  "snapshot": "2026-09-13-r1",
  "request_id": "b44f51c0-382e-445b-9013-a3f9e7ed500e",
  "data_as_of": "2026-09-13",
  "quality_policy": { "requested": "released", "generation": null, "experimental_included": false },
  "license": {
    "schema_version": 2,
    "id": "LicenseRef-michiyomi-layered",
    "url": "https://michiyomi.dev/docs/license/",
    "policy_version": "2026-10-03",
    "summary": "観測データ(本文・構造化JSON・機械層の値・経年変化)は CC BY 4.0 で使えます…",
    "summary_en": "Observation data (text, structured JSON, machine features, c…",
    "obligations": {
      "use_in_results": ["none"],
      "display_or_quote_records": ["none"],
      "redistribute_as_data": ["attribution", "upstream_not_licensed_if_bulk", "source_notice_if_bulk"]
    },
    "notices": [
      "mapillary_reference_not_licensed",
      … 5 more
    ],
    "layers": {
      "observation": "CC-BY-4.0",
      "mapillary_reference": "NOASSERTION",
      "public_sector": "CC-BY-4.0"
    },
    "linked_only": { "photo": "CC-BY-SA-4.0" },
    "attribution": "出典: みちよみ(michiyomi.dev…",
    "attribution_en": "Source: michiyomi (michiyomi.dev), from Mapillary street-lev…",
    "public_sector_sources": ["…"],
    "mapillary": "https://www.mapillary.com",
    "ui_requirements": "テキストや数値を表示するだけなら…",
    "ui_requirements_en": "No logo or credit is needed to display text or values. Only …",
    … 4 more fields
  },
  "release": {
    "release_id": "2026-09-13-r1",
    "status": "published",
    "created_at": "2026-09-12T20:42:08.414276Z",
    "published_at": "2026-09-12T22:00:00Z",
    "data_as_of": "2026-09-13"
  },
  "counts": {
    "processed_total": 1914490,
    "served_total": 1914451,
    "released_total": 1914451,
    "experimental_total": 0,
    "changes_total": 2522,
    "schools_total": 1323,
    "quarantined_total": 39,
    "machine_feature_rows": 1914490,
    "position_source": { "mapillary_computed": 1899940, "mapillary_raw": 14511 }
  },
  "machine_feature_coverage": {
    "rows": { "count": 1914490, "denominator": 1914490, "ratio": 1 },
    "served_columns": {
      "travel_bearing": { "count": 1907664, "denominator": 1914451, "ratio": 0.996455 },
      "abs_objects": { "count": 1650371, "denominator": 1914451, "ratio": 0.86206 },
      "color_status_ok": { "count": 1914412, "denominator": 1914451, "ratio": 0.99998 },
      "green_ratio": { "count": 1914412, "denominator": 1914451, "ratio": 0.99998 }
    }
  },
  "years": { "min": 1986, "max": 2026 },
  "sharding": {
    "active": true,
    "shard_count": 4,
    "shards": ["s002", "s003", "s004", "s005"],
    "routing": "longitude bands on cell_250m edges"
  },
  "generations": [
    {
      "id": "gen2-qwen-local",
      "status": "released",
      "version": 2,
      "gen_id": "gen2-qwen-local",
      "model_family": "qwen-local",
      "model": "sakamakismile/Qwen3.8-27B-MTP-NVFP4 / nvidia/Qwen3.6-27B-NVF…",
      "prompt_version": null,
      "output_contract": "v2: 純粋視覚・カメラ基準左右・image_file付きJSON",
      "released_at": "2026-08-22",
      "notes": "ローカルVLMによる言語化…",
      "evidence": null,
      "stats": {…}
    },
    … 1 more
  ],
  "metrics": {
    "processed_total": 1914490,
    "served_total": 1914451,
    "released_total": 1914451,
    "experimental_total": 0,
    "changes_total": 2522,
    "schools_total": 1323,
    "position_source_computed": 1899940,
    "position_source_raw": 14511,
    "computed_discarded_outside_service": 183,
    "machine_feature_rows": 1914490,
    "machine_travel_bearing_nonnull": 1907664,
    "machine_abs_objects_nonnull": 1650371,
    "machine_color_status_ok": 1914412,
    "machine_green_ratio_nonnull": 1914412,
    "year_min": 1986,
    "year_max": 2026,
    … 3 more fields
  },
  "counting_notes": {
    "source": "件数は release_stats(リリース時に確定した正本)から返す…",
    "quarantine": "processed_total / machine_feature_rows は隔離を含む処理済み総数…",
    "search_vs_release": "近傍検索・coverage は隔離シーンを常に除外するため…"
  }
}
Response fields
FieldTypeDescription
releaseobject | null
release.release_idstring
release.statusstringvalues building staged published withdrawn
release.created_atstring
release.published_atstring | null
release.data_as_ofstring
countsobject
counts.processed_totalinteger | null
counts.served_totalinteger | null
counts.released_totalinteger | null
counts.experimental_totalinteger | null
counts.changes_totalinteger | null
counts.schools_totalinteger | null
counts.quarantined_totalinteger | null
counts.machine_feature_rowsinteger | null
counts.position_sourceobject
machine_feature_coverageobjectRow coverage and populated-field rates for major machine features in served records
yearsobject
years.mininteger | null
years.maxinteger | null
generationsobject[]
generations[].idstring
generations[].statusstringvalues experimental released deprecated
generations[].versioninteger
generations[].gen_idstring
generations[].model_familystring | null
generations[].modelstring | null
generations[].prompt_versionstring | null
generations[].output_contractstring
generations[].released_atstring | null
generations[].notesstring | null
generations[].evidenceobject | null
generations[].statsobject
metricsobject<integer>Raw metric-to-value map from release_stats
counting_notesobject<string>
Status codes
  • 200 OK
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.

GET/v1/generations

Verbalization-generation catalog and governance

Cache public, max-age=300

Example

curl "https://michiyomi.dev/v1/generations"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "default_generation": "gen2-qwen-local",
  "governance": "3層管理: ①行来歴(model/prompt_version/generated_at=不変の事実) ②世代(出力契約…",
  "generations": [
    {
      "id": "gen2-qwen-local",
      "status": "released",
      "version": 2,
      "gen_id": "gen2-qwen-local",
      "model_family": "qwen-local",
      "model": "sakamakismile/Qwen3.8-27B-MTP-NVFP4 / nvidia/Qwen3.6-27B-NVF…",
      "prompt_version": null,
      "output_contract": "v2: 純粋視覚・カメラ基準左右・image_file付きJSON",
      "released_at": "2026-08-22",
      "notes": "ローカルVLMによる言語化…",
      "evidence": null,
      "stats": {…}
    },
    … 1 more
  ]
}
Response fields
FieldTypeDescription
default_generationstring | null
governancestring
generationsobject[]
generations[].idstring
generations[].statusstringvalues experimental released deprecated
generations[].versioninteger
generations[].gen_idstring
generations[].model_familystring | null
generations[].modelstring | null
generations[].prompt_versionstring | null
generations[].output_contractstring
generations[].released_atstring | null
generations[].notesstring | null
generations[].evidenceobject | null
generations[].statsobject
Status codes
  • 200 OK
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.

GET/v1/provenance

Release manifest and provenance

alias /v1/provCache public, max-age=300

provenance is the Rootline node chain. It records only the released gen1-codex generation and does not apply to gen2-qwen-local, as disclosed by provenance_scope.

Example

curl "https://michiyomi.dev/v1/provenance"
Response (excerpt) · HTTP 200Open raw ↗
// common fields (snapshot, license and so on) omitted
{
  "release": {
    "release_id": "2026-09-13-r1",
    "status": "published",
    "data_as_of": "2026-09-13",
    "published_at": "2026-09-12T22:00:00Z",
    "manifest": {…}
  },
  "provenance": {
    "dataset_node": "dc263171b410",
    "repository": "rootline (追記型来歴リポジトリ…",
    "nodes": […]
  },
  "provenance_scope": "src/prov.json の来歴連鎖(Rootlineノード)は released世代 gen1-codex に限った…",
  "verification_method": "経年変化(changes)の裁定は…"
}
Response fields
FieldTypeDescription
releaseobject | null
provenanceobject
provenance_scopestring
verification_methodstring
Status codes
  • 200 OK
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.

GET/v1

API self-description JSON

Cache public, max-age=300

Returns the endpoint catalog, aliases, serving policies, and license as machine-readable JSON.

Example

curl "https://michiyomi.dev/v1"
Response (excerpt) · HTTP 200Open raw ↗
{
  "api_version": "v1",
  "name": "michiyomi API",
  "description": "Read-only API for structured VLM descriptions of Mapillary s…",
  "description_ja": "Mapillary街路画像をVLMで構造化テキスト化した…",
  "data_language": "ja",
  "endpoints": {
    "GET /v1/meta": "Authoritative release counts and verbalization-generation ca…",
    "GET /v1/scenes/nearby": "Nearby scenes. Requires lat/lon; supports radius_m, limit, q…",
    "GET /v1/amenities/nearby": "Nearby amenity observations (kind=vending_machine|toilet|ben…",
    "POST /amenities/search": "Same amenity search with coordinates in a JSON body (keeps v…",
    "GET /v1/scenes/{id}": "Scene detail. Select metadata, deterministic machine feature…",
    "GET /v1/coverage": "Honest coverage report around a coordinate; zero means no re…",
    "GET /v1/changes/nearby": "Nearby adjudicated longitudinal change observations with cat…",
    "GET /v1/changes/{change_id}": "Full change evidence and verification metadata",
    "GET /v1/schools/search": "Partial-name search for elementary schools (NFKC normalized;…",
    "GET /v1/generations": "Verbalization-generation catalog and governance metadata",
    "GET /v1/provenance": "Release manifest and gen1 provenance chain",
    "POST /mcp": "Stateless MCP Streamable HTTP endpoint (2025-06-18 compatibl…"
  },
  "aliases": {
    "GET /v1/nearby": "GET /v1/scenes/nearby",
    "GET /v1/node/{id}": "GET /v1/scenes/{id}",
    "GET /v1/prov": "GET /v1/provenance"
  },
  "policies": [
    "The default is quality=released. Experimental generations ar…",
    "Scenes with anomalous capture timestamps (quarantined=1) are…",
    … 2 more
  ],
  "policies_ja": [
    "既定は quality=released…",
    "撮影時刻が異常なシーン(quarantined=1)は近傍検索・統計から除外され…",
    … 2 more
  ],
  "request_id": "71eea11c-97ba-4f03-bc98-0dc10136ac00",
  "license": {
    "schema_version": 2,
    "id": "LicenseRef-michiyomi-layered",
    "url": "https://michiyomi.dev/docs/license/",
    "policy_version": "2026-10-03",
    "summary": "観測データ(本文・構造化JSON・機械層の値・経年変化)は CC BY 4.0 で使えます…",
    "summary_en": "Observation data (text, structured JSON, machine features, c…",
    "obligations": {
      "use_in_results": ["none"],
      "display_or_quote_records": ["none"],
      "redistribute_as_data": ["attribution", "upstream_not_licensed_if_bulk", "source_notice_if_bulk"]
    },
    "notices": [
      "mapillary_reference_not_licensed",
      "photos_not_included",
      … 4 more
    ],
    "layers": {
      "observation": "CC-BY-4.0",
      "mapillary_reference": "NOASSERTION",
      "public_sector": "CC-BY-4.0"
    },
    "linked_only": { "photo": "CC-BY-SA-4.0" },
    "attribution": "出典: みちよみ(michiyomi.dev…",
    "attribution_en": "Source: michiyomi (michiyomi.dev), from Mapillary street-lev…",
    "public_sector_sources": ["…"],
    "mapillary": "https://www.mapillary.com",
    … 6 more fields
  }
}
Response fields
FieldTypeDescription
namestring
descriptionstring
endpointsobject<string>
aliasesobject<string>
policiesstring[]
Status codes
  • 200 OK

MCP

The MCP server for AI agents that looks up places. See Use from AI for setup and tool usage. Scenery search by impression is a separate MCP server (/explore/mcp) and is not part of this definition.

POST/mcp

MCP (Model Context Protocol) Streamable HTTP

Cache no-store

Stateless Streamable HTTP. The endpoint returns one JSON response and uses neither SSE nor session IDs. It is compatible with protocol version 2025-06-18.

Tools (11): get_metadata, find_school, coverage, describe_location, get_scene, changes_near, find_amenities, describe_street, describe_area, find_street, find_area. See Use from AI.

initialize echoes a requested version only when it is one the server actually supports: 2025-06-18, 2025-03-26, or 2024-11-05. Otherwise it returns 2025-06-18 and does not claim support for unverified future specifications.

Limits:

ConditionResponse
body > 64KBHTTP 413 payload_too_large
malformed JSONHTTP 400 / JSON-RPC -32700
empty batchHTTP 400 / JSON-RPC -32600
batch > 20HTTP 400 / JSON-RPC -32600
N tools/call entries in a batchcounts N times against the MCP rate limit; HTTP 429 if any call exceeds the limit
no id member (notification)HTTP 202 with no body; the tool is not executed
unknown methodJSON-RPC -32601
unknown toolresult.isError = true; the database is not queried

Errors never expose stack traces, SQL, or internal paths.

Differs from the OpenAPI file (checked in production on 2026-10-03)
The description in openapi.en.yaml lists only five tools. Production has 11 (the list above comes from the live tools/list).

Body (JSON)

NameInTypeDescription
jsonrpcrequiredbody"2.0"
idbodystring | integer | nullA message without an id member is a notification under JSON-RPC 2.0 §4.1. The server returns no JSON-RPC response and does not execute the tool, even for tools/call (HTTP 202, empty body). "id": null still has an id member and is therefore a request; null is echoed in the response.
methodrequiredbodystringexample initialize ping tools/list tools/call notifications/initialized
paramsbodyobject

Example

curl -X POST "https://michiyomi.dev/mcp" -H "content-type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Response (excerpt) · HTTP 200
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "get_metadata",
        "description": "Read the current published snapshot, authoritative counts, r…",
        "inputSchema": {…},
        "annotations": { "readOnlyHint": true, "destructiveHint": false, "openWorldHint": true },
        "outputSchema": {…}
      },
      {
        "name": "find_school",
        "description": "Search the recorded Tokyo elementary-school name catalog, in…",
        "inputSchema": {…},
        "annotations": { "readOnlyHint": true, "destructiveHint": false, "openWorldHint": true },
        "outputSchema": {…}
      },
      … 9 more
    ]
  }
}
Status codes
  • 200 JSON-RPC response (single request or batch)
  • 202 No response body because the request contained notifications only
  • 400 Parse error or invalid request in JSON-RPC error form
  • 405 Read-only API. POST, PUT, DELETE, and PATCH to /v1, and GET /mcp, always return 405. No administrative or write endpoint exists.
  • 413 Request body exceeds 64 KB
  • 429 Rate limit exceeded. REST allows 300 requests per 60 seconds per IP; MCP allows 120.

Aliases

These older names still work for existing clients. Use the name on the right in new code.

AliasSame as
GET /v1/nearbyGET /v1/scenes/nearby
GET /v1/node/{id}GET /v1/scenes/{id}
GET /v1/provGET /v1/provenance

This page was generated by tools/gen_api_reference.py from api/openapi.en.yaml and live production responses.