openapi: 3.1.0
x-tagGroups:
  - name: API Reference
    tags:
      - Guides
      - Basemap
      - Business Layer
      - Navigation
      - Address & POI
      - Parcels

info:
  title: GMap Cloud API
  version: "1.1"
  description: |
    # GMap Cloud API

    A comprehensive suite of APIs providing mapping, geocoding, routing, satellite imagery, administrative boundaries, and land parcel data for Vietnam.

    **Base URL:** `https://cloud.gmap.vn`
    **Authentication:** Authenticate all requests by including an `x-api-key` header or `x-api-key` query parameter.

    A demo API key is available for evaluation purposes: `public-gmap-cloud-x-api-key-demo` (rate-limited).

    ## Integration — MapLibre GL JS

    The recommended approach is to load the pre-configured style descriptor from `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=public-gmap-cloud-x-api-key-demo`:

    ```js
    const KEY = 'public-gmap-cloud-x-api-key-demo';
    new maplibregl.Map({
      container: 'map',
      center: [105.83416, 21.02776],
      zoom: 12,
      style: `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=${KEY}`,
    });
    ```

    Alternatively, construct a custom style referencing individual tile sources:

    ```html
    <link href="https://unpkg.com/maplibre-gl@^5.24.0/dist/maplibre-gl.css" rel="stylesheet" />
    <script src="https://unpkg.com/maplibre-gl@^5.24.0/dist/maplibre-gl.js"></script>
    <div id="map" style="width:100%;height:400px;"></div>
    <script>
    new maplibregl.Map({
      container: 'map', center: [105.83416, 21.02776], zoom: 12,
      style: {
        version: 8, layers: [],
        sources: { vietnam: { type: 'vector',
          tiles: [`https://cloud.gmap.vn/api/tiles/vietnam/{z}/{x}/{y}?x-api-key=${KEY}`] }}
      }
    });
    </script>
    ```

    ## Services Overview

    | Category | Capabilities |
    |----------|--------------|
    | **Basemap** | Vietnam base vector (PBF), satellite raster, street vector, street-level thumbnails, sprites, and font glyphs |
    | **Business Layer** | Parcel view & density vector tiles, combined parcel styles, GADM34 & GADM63 administrative boundary tiles and detail API with VN2000 projections |
    | **Navigation** | OSRM-based routing (car, motorbike, pedestrian) and TSP multi-stop optimization |
    | **Address & POI** | Forward geocoding (search/autocomplete), reverse geocoding, coordinate CRS transform (WGS84 ↔ VN2000), vpostcode lookup, and detailed POI/address information |
    | **Parcels** | Land parcel lookup (coordinate & cadastral), planning/zoning overlays, land-use code reference, and legacy commune code reference |

  x-i18n:
    vi:
      title: GMap Cloud API
      description: |
        # GMap Cloud API

        Hệ thống API toàn diện cung cấp các dịch vụ bản đồ, geocoding, định tuyến, ảnh vệ tinh, ranh giới hành chính và tra cứu thửa đất tại Việt Nam.

        **Base URL:** `https://cloud.gmap.vn`
        **Xác thực:** Tất cả yêu cầu phải kèm `x-api-key` trong header hoặc query parameter `x-api-key=`.

        Khóa API dùng thử dành cho mục đích đánh giá: `public-gmap-cloud-x-api-key-demo` (có giới hạn lưu lượng).

        ## Tích hợp — MapLibre GL JS

        Cách tiếp cận được khuyến nghị là sử dụng style descriptor có sẵn từ `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=public-gmap-cloud-x-api-key-demo`:

        ```js
        const KEY = 'public-gmap-cloud-x-api-key-demo';
        new maplibregl.Map({
          container: 'map',
          center: [105.83416, 21.02776],
          zoom: 12,
          style: `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=${KEY}`,
        });
        ```

        Hoặc tự xây dựng style tham chiếu đến từng tile source:

        ```html
        <link href="https://unpkg.com/maplibre-gl@^5.24.0/dist/maplibre-gl.css" rel="stylesheet" />
        <script src="https://unpkg.com/maplibre-gl@^5.24.0/dist/maplibre-gl.js"></script>
        <div id="map" style="width:100%;height:400px;"></div>
        <script>
        new maplibregl.Map({
          container: 'map', center: [105.83416, 21.02776], zoom: 12,
          style: { version: 8,
            sources: { vietnam: { type: 'vector',
              tiles: [`https://cloud.gmap.vn/api/tiles/vietnam/{z}/{x}/{y}?x-api-key=${KEY}`] }},
            layers: []
          }
        });
        </script>
        ```

        ## Tổng quan dịch vụ

        | Danh mục | Khả năng cung cấp |
        |----------|--------------------|
        | **Basemap** | Bản đồ nền vector (PBF), ảnh vệ tinh raster, bản đồ đường phố vector, hình ảnh đường phố, biểu tượng & phông chữ |
        | **Business Layer** | Ô vector chi tiết & mật độ thửa đất, style tổng hợp, ranh giới hành chính GADM34 & GADM63 và API chi tiết với hệ quy chiếu VN2000 |
        | **Navigation** | Định tuyến dựa trên OSRM (ô tô, xe máy, đi bộ), tối ưu hóa đa điểm TSP |
        | **Address & POI** | Geocoding xuôi (tìm kiếm/autocomplete), geocoding ngược, chuyển đổi hệ tọa độ (WGS84 ↔ VN2000), tra cứu vpostcode, thông tin chi tiết POI & địa chỉ |
        | **Parcels** | Tra cứu thửa đất (tọa độ & cadastral), lớp phủ quy hoạch/phân khu, danh mục mã loại đất, danh mục mã xã cũ |

servers:
  - url: https://cloud.gmap.vn
    description: Production
    x-i18n:
      vi:
        description: Máy chủ chính thức

tags:
  - name: Guides
    description: |
      ## Getting Started

      All API endpoints require authentication via the `x-api-key` header or `?x-api-key=` query parameter.
      For evaluation and testing, use the demo key `public-gmap-cloud-x-api-key-demo` (rate-limited).

      ### MapLibre GL JS Integration

      The recommended approach is to load the pre-configured style descriptor:

      ```js
      new maplibregl.Map({
        container: 'map',
        style: `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=${KEY}`
      });
      ```

      ### Interactive Resources

      - <a href="sample-style.html" target="_blank">Basemap style demo — interactive MapLibre preview</a>
      - Satellite imagery + planning overlay: `GET /api/satellite/demo/`
      - [Upcoming] Parcel raster overlays: current land-use status and parcel boundaries

      ### SDK & Tools
      [Upcoming] SDK packages and CLI tools documentation.
    x-i18n:
      vi:
        name: Hướng dẫn
        description: |
          ## Bắt đầu

          Tất cả endpoint yêu cầu xác thực qua header `x-api-key` hoặc query parameter `?x-api-key=`.
          Dùng khóa demo `public-gmap-cloud-x-api-key-demo` để thử nghiệm và đánh giá (có giới hạn lưu lượng).

          ### Tích hợp MapLibre GL JS

          Cách tiếp cận được khuyến nghị là sử dụng style descriptor có sẵn:

          ```js
          new maplibregl.Map({
            container: 'map',
            style: `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=${KEY}`
          });
          ```

          ### Tài nguyên tương tác

          - <a href="sample-style.html" target="_blank">Demo bản đồ nền — xem trước MapLibre tương tác</a>
          - Ảnh vệ tinh + lớp quy hoạch: `GET /api/satellite/demo/`
          - [Sắp ra mắt] Lớp raster thửa đất: hiện trạng sử dụng đất và ranh giới thửa đất

          ### SDK & Công cụ
          [Sắp ra mắt] Tài liệu hướng dẫn SDK và CLI tools.

  - name: Basemap
    description: |
      Vector PBF tiles, raster satellite imagery, POI layers, street-level imagery, sprites, and font glyphs for building interactive maps with MapLibre GL JS, Leaflet, or any Web Mercator tile client.

      All endpoints accept `?x-api-key=` for authentication.

      ### Vietnam Base Vector Tile — `/api/tiles/vietnam/{z}/{x}/{y}`

      The base vector tile provides 12 source layers with full attribution for Trường Sa (Spratly) and Hoàng Sa (Paracel) archipelagos:

      | Source Layer | Key Properties | Description |
      |-------------|---------------|-------------|
      | `aerodrome_label` | `name`, `name:en`, `class`, `icao` | Airport labels |
      | `aeroway` | `class`, `ref` | Runways |
      | `boundary` | `admin_level`, `maritime` | Administrative boundaries (includes maritime) |
      | `landcover` | `class`, `subclass` | Land cover |
      | `landuse` | `class` | Land use |
      | `park` | `name`, `class` | Parks and protected areas |
      | `place` | `name`, `name:en`, `class`, `capital` | Place names |
      | `poi` | `name`, `name:en`, `class`, `subclass`, `rank` | Points of interest |
      | `transportation` | `class`, `subclass`, `oneway`, `service` | Road network |
      | `transportation_name` | `name`, `ref`, `class`, `network` | Road names and highway numbers |
      | `water` | `class`, `intermittent` | Water bodies |
      | `waterway` | `name`, `name:en`, `class` | Rivers and streams |

      ### POI Vector Tile — `/api/tiles/poi_point/{z}/{x}/{y}`

      Single `poi_point` layer:

      | Key | Type | Description |
      |-----|------|-------------|
      | `id` | int8 | Unique identifier |
      | `name` | text | Vietnamese name |
      | `name_en` | text | English name |
      | `class` | text | Category (e.g., `shop`, `tourism`) |
      | `subclass` | text | Subcategory (e.g., `supermarket`, `hotel`) |
      | `rank` | int4 | Display priority |
      | `mapping_key` | text | Mapping key |
      | `place_address` | text | Address string |

      ### Vietnam Satellite Raster — `/api/satellite/tiles/{z}/{x}/{y}`

      Raster PNG/JPEG tiles at zoom levels 0–16. Pre-rendered tiles served from PMTiles.

      ### Vietnam Street Vector — `/api/satellite/street/{z}/{x}/{y}`

      High-detail PBF tiles containing the road network and building footprints.

      ### Street-Level Imagery — `/api/satellite/streetimage/{image_id}`

      Panoramic street-level imagery. Append `?thumb=original` for full resolution.

      ### MapLibre Style JSON

      A pre-configured MapLibre style descriptor is available at `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=public-gmap-cloud-x-api-key-demo`. It composes all basemap layers (landcover, landuse, water, parks, buildings, transportation, aeroways, boundaries, places, POIs — 116 layers total) with the appropriate sprite and glyph endpoints. This is the recommended integration path for most use cases.

      [Upcoming] Style customization options (language, layer toggles).

      [Upcoming] High-resolution panorama / 360° viewer endpoint.
    x-i18n:
      vi:
        name: Bản đồ
        description: |
          Ô vector PBF, ảnh vệ tinh raster, điểm POI, hình ảnh đường phố, biểu tượng và phông chữ phục vụ xây dựng bản đồ tương tác với MapLibre GL JS, Leaflet hoặc bất kỳ tile client Web Mercator nào.

          Tất cả endpoint chấp nhận `?x-api-key=` để xác thực.

          ### Vietnam Base Vector — `/api/tiles/vietnam/{z}/{x}/{y}`

          Ô vector nền cung cấp 12 lớp dữ liệu, bao gồm đầy đủ quần đảo Trường Sa và Hoàng Sa:

          | Source Layer | Thuộc tính chính | Mô tả |
          |-------------|-----------------|-------|
          | `aerodrome_label` | `name`, `name:en`, `class` | Nhãn sân bay |
          | `boundary` | `admin_level`, `maritime` | Ranh giới hành chính (bao gồm biển đảo) |
          | `landcover` | `class`, `subclass` | Phủ bề mặt |
          | `place` | `name`, `name:en`, `class` | Địa danh |
          | `poi` | `name`, `name:en`, `class` | Điểm quan tâm |
          | `transportation` | `class`, `subclass`, `oneway` | Mạng lưới đường |
          | `transportation_name` | `name`, `ref`, `network` | Tên đường và quốc lộ |
          | `water` | `class`, `intermittent` | Mặt nước |
          | `waterway` | `name`, `name:en`, `class` | Sông suối |

          ### POI Vector — `/api/tiles/poi_point/{z}/{x}/{y}`

          | Thuộc tính | Mô tả |
          |-----------|-------|
          | `name` | Tên tiếng Việt |
          | `name_en` | Tên tiếng Anh |
          | `class` | Phân loại (shop, tourism, v.v.) |
          | `subclass` | Phân loại chi tiết |
          | `rank` | Độ ưu tiên hiển thị |
          | `place_address` | Địa chỉ |

          ### Ảnh vệ tinh — `/api/satellite/tiles/{z}/{x}/{y}`

          Ô raster PNG/JPEG, mức zoom 0–16. Dữ liệu được render sẵn từ PMTiles.

          ### Bản đồ đường phố — `/api/satellite/street/{z}/{x}/{y}`

          Ô vector PBF chi tiết cao chứa mạng lưới đường và hình khối tòa nhà.

          ### Hình ảnh đường phố — `/api/satellite/streetimage/{image_id}`

          Ảnh toàn cảnh cấp đường phố. Thêm `?thumb=original` để lấy độ phân giải gốc.

          ### MapLibre Style JSON

          Style descriptor MapLibre có sẵn tại `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=public-gmap-cloud-x-api-key-demo`. Tổ hợp tất cả lớp bản đồ nền (phủ bề mặt, sử dụng đất, mặt nước, công viên, tòa nhà, giao thông, sân bay, ranh giới, địa danh, POI — tổng 116 lớp) với sprite và glyph endpoint phù hợp. Đây là phương thức tích hợp được khuyến nghị cho hầu hết trường hợp sử dụng.

          [Sắp ra mắt] Tùy chọn tùy chỉnh style (ngôn ngữ, bật/tắt lớp).

          [Sắp ra mắt] Endpoint ảnh panorama / 360° độ phân giải cao.

  - name: Business Layer
    description: |
      Vector tile layers for land parcel visualization — individual parcel polygons at high zoom and aggregated density grids for regional overviews.

      ### Parcel Detail — `/api/tiles/parcels-view/{z}/{x}/{y}`

      Vector (PBF) tiles displaying individual parcel polygons at zoom level 17. Delivers boundary-accurate geometries suitable for inspection-level map views. Served from `martin-cp` with gzip compression.

      ### Parcel Density — `/api/tiles/parcels-density/{z}/{x}/{y}`

      Vector (PBF) tiles providing an aggregated parcel density grid at zoom levels 0–16. Each grid cell includes a `parcel_count` property for choropleth and heatmap rendering, enabling regional overviews of parcel distribution.

      | Key | Type | Description |
      |-----|------|-------------|
      | `parcel_count` | number | Number of parcels within the grid cell |

      ### Parcel Style — `/api/tiles/style/parcels`

      A pre-composed MapLibre style JSON that combines both parcel sources into a ready-to-use layer stack:

      - **Parcel density fill** (z0–17): color ramp from light to dark blue based on `parcel_count`, with adaptive opacity.
      - **Parcel fill** (z17+): semi-transparent blue polygon fill for individual parcels.
      - **Parcel outline** (z17+): bright boundary lines whose width scales with zoom level.
      - **Light basemap**: CartoDB Positron raster tiles for geographic context.

      Integrate with MapLibre GL JS via:

      ```js
      new maplibregl.Map({
        container: 'map',
        style: `https://cloud.gmap.vn/api/tiles/style/parcels?x-api-key=${KEY}`,
      });
      ```

      [Upcoming] Address density grid tiles — aggregated address point density at zoom levels 0–16.
      [Upcoming] POI density grid tiles — aggregated point-of-interest density at zoom levels 0–16.

      ### Administrative Boundaries — GADM

      Administrative boundary data sourced from GADM (Database of Global Administrative Areas) for Vietnam. Coordinate detail is available through Hasura REST, and boundary tiles are available as vector tiles in GADM34 and GADM63 resolutions.

      | Endpoint | Description |
      |----------|-------------|
      | `GET /api/tiles/gadm34/{z}/{x}/{y}` | GADM34 vector tiles — 34-province boundaries, supports VN2000 |
      | `GET /api/tiles/gadm63/{z}/{x}/{y}` | GADM63 vector tiles — 63-province boundaries, supports VN2000 |
      | `GET /api/hasura/gql/gadm/get-gadm-detail-by-coordinate` | Administrative unit detail GADM by coordinate |
      | `GET /api/hasura/gql/gadm/get-gadm-detail-by-id` | Administrative unit detail GADM by ID |

      > **Data sensitivity notice:** PBF vector tiles and coordinate-detail responses expose detailed boundary geometries. Access control and rate limiting apply.
    x-i18n:
      vi:
        name: Dữ liệu nghiệp vụ
        description: |
          Lớp vector tile phục vụ hiển thị thửa đất — đa giác từng thửa ở mức zoom cao và lưới mật độ tổng hợp cho cái nhìn toàn cảnh.

          ### Chi tiết thửa đất — `/api/tiles/parcels-view/{z}/{x}/{y}`

          Ô vector (PBF) hiển thị đa giác từng thửa đất ở mức zoom 17. Cung cấp hình học chính xác theo ranh giới, phù hợp cho chế độ xem chi tiết. Dữ liệu từ `martin-cp`, nén gzip.

          ### Mật độ thửa đất — `/api/tiles/parcels-density/{z}/{x}/{y}`

          Ô vector (PBF) cung cấp lưới mật độ thửa đất tổng hợp ở mức zoom 0–16. Mỗi ô lưới chứa thuộc tính `parcel_count` phục vụ hiển thị choropleth và heatmap, cho phép quan sát phân bố thửa đất trên diện rộng.

          | Thuộc tính | Kiểu | Mô tả |
          |-----------|------|-------|
          | `parcel_count` | number | Số lượng thửa đất trong ô lưới |

          ### Style tổng hợp — `/api/tiles/style/parcels`

          Style JSON MapLibre được tổ hợp sẵn, tích hợp cả hai nguồn dữ liệu thửa đất thành một bộ lớp hoàn chỉnh:

          - **Lớp tô mật độ** (z0–17): dải màu từ xanh nhạt đến xanh đậm theo `parcel_count`, độ mờ thích ứng.
          - **Lớp tô thửa đất** (z17+): tô đa giác màu xanh bán trong suốt cho từng thửa.
          - **Lớp viền thửa đất** (z17+): đường ranh sáng màu, độ dày tăng theo mức zoom.
          - **Bản đồ nền**: raster CartoDB Positron cho ngữ cảnh địa lý.

          Tích hợp với MapLibre GL JS:

          ```js
          new maplibregl.Map({
            container: 'map',
            style: `https://cloud.gmap.vn/api/tiles/style/parcels?x-api-key=${KEY}`,
          });
          ```

          [Sắp ra mắt] Ô mật độ địa chỉ — lưới mật độ điểm địa chỉ tổng hợp ở mức zoom 0–16.
          [Sắp ra mắt] Ô mật độ POI — lưới mật độ điểm quan tâm tổng hợp ở mức zoom 0–16.

          ### Ranh giới hành chính — GADM

          Dữ liệu ranh giới hành chính từ GADM (Database of Global Administrative Areas) cho Việt Nam. API chi tiết theo tọa độ đã khả dụng qua Hasura REST; các ô ranh giới khả dụng dưới dạng vector tile ở độ phân giải GADM34 và GADM63.

          | Endpoint | Mô tả |
          |----------|-------|
          | `GET /api/tiles/gadm34/{z}/{x}/{y}` | Vector tiles GADM34 — ranh giới 34 tỉnh, hỗ trợ VN2000 |
          | `GET /api/tiles/gadm63/{z}/{x}/{y}` | Vector tiles GADM63 — ranh giới 63 tỉnh, hỗ trợ VN2000 |
          | `GET /api/hasura/gql/gadm/get-gadm-detail-by-coordinate` | Chi tiết đơn vị hành chính GADM theo tọa độ |
          | `GET /api/hasura/gql/gadm/get-gadm-detail-by-id` | Chi tiết đơn vị hành chính GADM theo mã |

          > **Lưu ý về độ nhạy cảm dữ liệu:** Ô vector PBF và phản hồi chi tiết theo tọa độ có thể tiết lộ ranh giới chi tiết. Áp dụng kiểm soát truy cập và giới hạn lưu lượng.

  - name: Navigation
    description: |
      Routing engines for Vietnam — OSRM for basic turn-by-turn navigation and Valhalla for advanced routing scenarios.

      ### Basic — OSRM Routing

      | Endpoint | Modes | Description |
      |----------|-------|-------------|
      | `GET /api/route/v1/{mode}/{coords}` | `car`, `bike`, `foot` | Turn-by-turn route between two or more points |

      ### Advanced — Valhalla Routing

      High-precision routing engine (v3.6.3) supporting TSP optimization, time-distance matrices, isochrones, map matching, and elevation queries. All Valhalla endpoints use `POST` with JSON request bodies and are served from `https://cloud.gmap.vn/api/tsp/route/`.

      | Endpoint | Description |
      |----------|-------------|
      | `POST /route` | Turn-by-turn route with detailed maneuver instructions |
      | `POST /optimized_route` | TSP multi-stop route optimization |
      | `POST /sources_to_targets` | Time-distance matrix between origins and destinations |
      | `POST /isochrone` | Reachability isochrone / isodistance polygons |
      | `POST /trace_route` | Map-matched route from GPS traces |
      | `POST /trace_attributes` | Map-matched edge attributes from GPS traces |
      | `POST /height` | Elevation at points or along a path |
      | `GET /locate` | Graph metadata for nearby edges and nodes |
      | `GET /status` | Service health and tileset information |
    x-i18n:
      vi:
        name: Chỉ đường OSRM
        description: |
          Công cụ định tuyến cho Việt Nam — OSRM cho tìm đường cơ bản và Valhalla cho các kịch bản nâng cao.

          ### Cơ bản — Tìm đường OSRM

          | Endpoint | Chế độ | Mô tả |
          |----------|--------|-------|
          | `GET /api/route/v1/{mode}/{coords}` | `car`, `bike`, `foot` | Đường đi giữa hai hoặc nhiều điểm |

          ### Nâng cao — Tìm đường Valhalla

          Công cụ định tuyến chính xác cao (v3.6.3) hỗ trợ tối ưu TSP, ma trận thời gian-khoảng cách, isochrone, map matching và truy vấn độ cao. Tất cả endpoint Valhalla dùng `POST` với body JSON, truy cập qua `https://cloud.gmap.vn/api/tsp/route/`.

          | Endpoint | Mô tả |
          |----------|-------|
          | `POST /route` | Đường đi kèm hướng dẫn chi tiết từng bước |
          | `POST /optimized_route` | Tối ưu tuyến đa điểm TSP |
          | `POST /sources_to_targets` | Ma trận thời gian-khoảng cách giữa điểm đi và điểm đến |
          | `POST /isochrone` | Đa giác vùng phủ isochrone / isodistance |
          | `POST /trace_route` | Đường đi khớp bản đồ từ vết GPS |
          | `POST /trace_attributes` | Thuộc tính cạnh khớp bản đồ từ vết GPS |
          | `POST /height` | Độ cao tại điểm hoặc dọc theo đường đi |
          | `GET /locate` | Thông tin đồ thị cho cạnh và nút lân cận |
          | `GET /status` | Thông tin trạng thái dịch vụ và tileset |

  - name: Address & POI
    description: |
      Geocoding, postal code resolution, and place information services for Vietnam.
      All Idunn responses return GADM34/GADM63 dataset variants where applicable — each
      item carries a `subtype` (`addr34`/`addr63`/`poi34`/`poi63`) and `meta.dataset`.

      | Endpoint | Description |
      |----------|-------------|
      | `GET /api/idunn/v1/autocomplete` | Search places and addresses |
      | `GET /api/idunn/v1/search` | Full-text search across addresses and POIs |
      | `GET /api/idunn/v1/reverse/{lat}:{lon}` | Reverse geocoding — nearest place per GADM dataset |
      | `GET /api/idunn/v1/places/latlon:{lat}:{lon}` | Coordinate detail lookup |
      | `GET /api/idunn/v1/places/{id}` | Place detail lookup (POI or address) |
      | `GET /api/idunn/v1/places/vpostcode:{vpostcode}` | Vpostcode detail lookup |
      | `GET /api/idunn/v1/places?bbox=...` | List places inside a bounding box |
      | `GET /api/idunn/v1/categories` | List all POI categories |
      | `GET /api/idunn/v1/transform` | CRS coordinate transform (WGS84 ↔ VN2000) |
      | `GET /api/idunn/v1/projections` | List supported VN2000 projections |
      | `GET /api/idunn/v1/projections/resolve` | Resolve VN2000 projection by province |
      | `GET /api/idunn/v1/instant_answer` | Instant answer for a natural-language query |
      | `GET /api/idunn/v1/directions` | Directions between two place IDs |
    x-i18n:
      vi:
        name: Địa chỉ & POI
        description: |
          Dịch vụ geocoding, tra cứu mã bưu chính và thông tin địa điểm tại Việt Nam.
          Các phản hồi Idunn đều trả về biến thể dữ liệu GADM34/GADM63 khi áp dụng — mỗi phần tử
          mang `subtype` (`addr34`/`addr63`/`poi34`/`poi63`) và `meta.dataset`.

          | Endpoint | Mô tả |
          |----------|-------|
          | `GET /api/idunn/v1/autocomplete` | Tìm kiếm địa điểm và địa chỉ |
          | `GET /api/idunn/v1/search` | Tìm kiếm toàn văn địa chỉ và POI |
          | `GET /api/idunn/v1/reverse/{lat}:{lon}` | Geocoding ngược — địa điểm gần nhất theo từng dataset GADM |
          | `GET /api/idunn/v1/places/latlon:{lat}:{lon}` | Tra cứu chi tiết tọa độ |
          | `GET /api/idunn/v1/places/{id}` | Tra cứu chi tiết địa điểm (POI hoặc địa chỉ) |
          | `GET /api/idunn/v1/places/vpostcode:{vpostcode}` | Tra cứu chi tiết Vpostcode |
          | `GET /api/idunn/v1/places?bbox=...` | Danh sách địa điểm trong bounding box |
          | `GET /api/idunn/v1/categories` | Danh sách toàn bộ phân loại POI |
          | `GET /api/idunn/v1/transform` | Chuyển đổi hệ tọa độ (WGS84 ↔ VN2000) |
          | `GET /api/idunn/v1/projections` | Danh sách hệ chiếu VN2000 được hỗ trợ |
          | `GET /api/idunn/v1/projections/resolve` | Xác định hệ chiếu VN2000 theo tỉnh |
          | `GET /api/idunn/v1/instant_answer` | Trả lời tức thời cho câu truy vấn tự nhiên |
          | `GET /api/idunn/v1/directions` | Chỉ đường giữa hai mã địa điểm |

  - name: Parcels
    description: |
      Land parcel (thửa đất) lookup with planning overlay, land-use code reference, and legacy commune code reference.

      ### Available Endpoints

      - **Lookup by coordinate** — retrieve every parcel covering a specified lat/lon point, ordered by confidence and recency.
      - **Lookup by cadastral number** — retrieve a parcel by map sheet (số tờ), parcel number (số thửa), and legacy commune code (mã xã cũ).
      - **Parcel vector tiles** — individual parcel polygons (`/api/tiles/parcels-view/{z}/{x}/{y}`, z17) and aggregated density grids (`/api/tiles/parcels-density/{z}/{x}/{y}`, z0–16); raw parcel table also served at `/api/tiles/prop_planning_parcel/{z}/{x}/{y}`.
      - **Planning raster tiles (QHSDD)** — pre-rendered land-use planning overlay tiles served from PMTiles.
      - **Land-use code reference** *(planned, not yet available)* — retrieve the full land-use code tree (`ma_su_dung_dat`) with parent codes and levels via Hasura REST (`get-land-use`).
      - **Legacy commune code reference** — browse administrative units by parent ID.
      - **Planning PDF download** — retrieve the planning decision document PDF (`/api/satellite/planning/download_pdf/{id}`).
      - **HCM-specific raster tiles** — `planning_hcm`, `planning_hcm_all`, `thuduc_parcel_borders`, `land_use_plan_paper` under `/api/satellite/`.

      ### Upcoming

      - [Upcoming] Current land-use raster tiles — current land-use status overlay (`/api/satellite/re-qhht/{z}/{x}/{y}`) with an interactive demo page.
      - [Upcoming] Parcel boundary raster tiles — parcel boundary outlines (`/api/satellite/re-boundary/{z}/{x}/{y}`) with an interactive demo page.
      - [Upcoming] Fuzzy search — free-text search by map sheet, parcel number, or province/city name for rapid parcel discovery.
    x-i18n:
      vi:
        name: Thửa đất
        description: |
          Tra cứu thửa đất với lớp phủ quy hoạch, danh mục mã loại đất và danh mục mã xã cũ.

          ### Endpoint hiện có

          - **Tra cứu theo tọa độ** — trả về thửa đất chứa điểm lat/lon được chỉ định.
          - **Tra cứu theo cadastral** — tra cứu thửa đất theo số tờ, số thửa và mã phường/xã cũ.
          - **Ô vector thửa đất** — đa giác từng thửa (`/api/tiles/parcels-view/{z}/{x}/{y}`, z17) và lưới mật độ tổng hợp (`/api/tiles/parcels-density/{z}/{x}/{y}`, z0–16); bảng thửa đất gốc cũng được phục vụ tại `/api/tiles/prop_planning_parcel/{z}/{x}/{y}`.
          - **Ô raster quy hoạch (QHSDD)** — ô raster quy hoạch sử dụng đất đai được render sẵn, dữ liệu từ PMTiles.
          - **Danh mục mã loại đất** *(dự kiến, chưa khả dụng)* — endpoint Hasura REST (`get-land-use`) liệt kê cây mã sử dụng đất (`ma_su_dung_dat`) kèm mã cha và cấp độ.
          - **Danh mục mã xã cũ** — duyệt các đơn vị hành chính theo mã đơn vị cha.
          - **Tải PDF quy hoạch** — tải tài liệu PDF quyết định quy hoạch (`/api/satellite/planning/download_pdf/{id}`).
          - **Ô raster riêng cho HCM** — `planning_hcm`, `planning_hcm_all`, `thuduc_parcel_borders`, `land_use_plan_paper` dưới `/api/satellite/`.

          ### Sắp ra mắt

          - [Sắp ra mắt] Raster quy hoạch hiện trạng — lớp phủ hiện trạng sử dụng đất (`/api/satellite/re-qhht/{z}/{x}/{y}`) kèm trang demo tương tác.
          - [Sắp ra mắt] Raster ranh giới thửa đất — đường ranh thửa đất (`/api/satellite/re-boundary/{z}/{x}/{y}`) kèm trang demo tương tác.
          - [Sắp ra mắt] Tìm kiếm tương đối — tìm kiếm tự do theo số tờ, số thửa hoặc tên tỉnh/thành để tra cứu nhanh.

security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key for GMap Cloud services. Use `public-gmap-cloud-x-api-key-demo` for evaluation and testing.
      x-i18n:
        vi:
          description: Khóa API cho dịch vụ GMap Cloud. Sử dụng `public-gmap-cloud-x-api-key-demo` để thử nghiệm và đánh giá.

  schemas:
    Feature:
      type: object
      description: A GeoJSON Feature object representing a place or point of interest.
      x-i18n:
        vi:
          description: Đối tượng GeoJSON Feature đại diện cho một địa điểm hoặc điểm quan tâm.
      properties:
        type:
          type: string
          enum: [Feature]
          description: Geometry type — always `Feature`.
          x-i18n:
            vi:
              description: Kiểu hình học — luôn là `Feature`.
        geometry:
          $ref: "#/components/schemas/Point"
        properties:
          type: object
          description: Place metadata including name, display label, type, and distance.
          x-i18n:
            vi:
              description: Thông tin địa điểm bao gồm tên, nhãn hiển thị, loại và khoảng cách.
          properties:
            label:
              type: string
              description: Full display label for the place.
              x-i18n:
                vi:
                  description: Nhãn hiển thị đầy đủ của địa điểm.
            name:
              type: string
              description: Place name.
              x-i18n:
                vi:
                  description: Tên địa điểm.
            type:
              type: string
              description: Place type (city, street, poi, etc.).
              x-i18n:
                vi:
                  description: Loại địa điểm (city, street, poi, v.v.).
            distance:
              type: number
              description: Distance from the query point, in meters.
              x-i18n:
                vi:
                  description: Khoảng cách từ điểm truy vấn, đơn vị mét.

    FeatureCollection:
      type: object
      description: GeoJSON FeatureCollection containing autocomplete results.
      x-i18n:
        vi:
          description: GeoJSON FeatureCollection chứa kết quả autocomplete.
      properties:
        type:
          type: string
          enum: [FeatureCollection]
        features:
          type: array
          items:
            $ref: "#/components/schemas/Feature"

    Point:
      type: object
      description: GeoJSON Point geometry.
      x-i18n:
        vi:
          description: Hình học GeoJSON Point.
      properties:
        type:
          type: string
          enum: [Point]
        coordinates:
          type: array
          minItems: 2
          maxItems: 2
          items:
            type: number
          description: "[longitude, latitude]"
          x-i18n:
            vi:
              description: "[kinh độ, vĩ độ]"

    GadmGeometry:
      type: object
      description: GeoJSON geometry returned for a GADM administrative unit.
      x-i18n:
        vi:
          description: Hình học GeoJSON trả về cho một đơn vị hành chính GADM.
      properties:
        type:
          type: string
          enum: [Point, Polygon, MultiPolygon]
          description: GeoJSON geometry type.
          x-i18n:
            vi:
              description: Kiểu hình học GeoJSON.
        coordinates:
          type: array
          description: Geometry coordinates in [longitude, latitude] order.
          items: {}
          x-i18n:
            vi:
              description: Tọa độ hình học theo thứ tự [kinh độ, vĩ độ].

    GadmUnit:
      type: object
      description: GADM administrative unit with its geometry and parent hierarchy.
      x-i18n:
        vi:
          description: Đơn vị hành chính GADM kèm hình học và phân cấp đơn vị cha.
      properties:
        id:
          type: integer
          format: int64
          description: Administrative unit identifier.
          x-i18n:
            vi:
              description: Mã định danh đơn vị hành chính.
        osm_id:
          type: string
          description: OpenStreetMap relation identifier.
          x-i18n:
            vi:
              description: Mã relation trên OpenStreetMap.
        admin_level:
          type: integer
          description: GADM administrative level.
          x-i18n:
            vi:
              description: Cấp hành chính GADM.
        zone_type:
          type: string
          description: Administrative unit type.
          x-i18n:
            vi:
              description: Loại đơn vị hành chính.
        name:
          type: string
          description: Administrative unit name.
          x-i18n:
            vi:
              description: Tên đơn vị hành chính.
        loc_name:
          type: string
          nullable: true
          description: Localized or local administrative unit name.
          x-i18n:
            vi:
              description: Tên địa phương hoặc tên bản địa của đơn vị hành chính.
        div_code:
          type: string
          nullable: true
          description: Administrative division code.
          x-i18n:
            vi:
              description: Mã đơn vị hành chính.
        parent_id:
          type: integer
          format: int64
          nullable: true
          description: Identifier of the parent administrative unit.
          x-i18n:
            vi:
              description: Mã đơn vị hành chính cha.
        wikidata:
          type: string
          nullable: true
          description: Wikidata entity identifier, when available.
          x-i18n:
            vi:
              description: Mã thực thể Wikidata, nếu có.
        country_code:
          type: string
          nullable: true
          description: Country code associated with the source record.
          x-i18n:
            vi:
              description: Mã quốc gia gắn với bản ghi nguồn.
        postal_codes:
          nullable: true
          description: Postal code or postal-code list, when available.
          oneOf:
            - type: string
            - type: array
              items:
                type: string
          x-i18n:
            vi:
              description: Mã bưu chính hoặc danh sách mã bưu chính, nếu có.
        key:
          type: string
          nullable: true
          description: Administrative lookup key, when available.
          x-i18n:
            vi:
              description: Khóa tra cứu hành chính, nếu có.
        epsg_code:
          type: string
          nullable: true
          description: Coordinate reference system code, when available.
          x-i18n:
            vi:
              description: Mã hệ quy chiếu tọa độ, nếu có.
        center_point:
          $ref: "#/components/schemas/Point"
        bbox:
          $ref: "#/components/schemas/GadmGeometry"
        geometry:
          $ref: "#/components/schemas/GadmGeometry"
        parent:
          oneOf:
            - $ref: "#/components/schemas/GadmUnit"
            - type: "null"
          description: Parent unit, recursively including its own parent.
          x-i18n:
            vi:
              description: Đơn vị cha, lồng đệ quy đến cấp cao hơn.

    GadmDetailResult:
      type: object
      description: GADM34 and GADM63 administrative unit detail result.
      x-i18n:
        vi:
          description: Kết quả chi tiết đơn vị hành chính GADM34 và GADM63.
      required: [gadm34, gadm63]
      properties:
        gadm34:
          $ref: "#/components/schemas/GadmUnit"
        gadm63:
          $ref: "#/components/schemas/GadmUnit"

    GadmCoordinateDetailResponse:
      type: object
      description: Hasura REST response for GADM34/GADM63 lookup by coordinate.
      x-i18n:
        vi:
          description: Phản hồi Hasura REST khi tra cứu GADM34/GADM63 theo tọa độ.
      required: [geo_get_gadm_detail_by_coordinate]
      properties:
        geo_get_gadm_detail_by_coordinate:
          type: array
          description: Matching GADM administrative detail records.
          x-i18n:
            vi:
              description: Danh sách bản ghi chi tiết đơn vị hành chính GADM khớp.
          items:
            $ref: "#/components/schemas/GadmDetailResult"

    GadmByIdDetailResponse:
      type: object
      description: Hasura REST response for GADM34/GADM63 lookup by administrative unit ID.
      x-i18n:
        vi:
          description: Phản hồi Hasura REST khi tra cứu GADM34/GADM63 theo mã đơn vị hành chính.
      required: [geo_vnsdi_get_gadm_detail_by_id]
      properties:
        geo_vnsdi_get_gadm_detail_by_id:
          type: array
          description: Matching GADM administrative detail records.
          x-i18n:
            vi:
              description: Danh sách bản ghi chi tiết đơn vị hành chính GADM khớp.
          items:
            $ref: "#/components/schemas/GadmDetailResult"

    LatLonPlace:
      type: object
      description: |
        Reverse geocoding result for a geographic coordinate. Returned as one item per
        GADM dataset variant (`addr34`/`addr63`); `subtype` and `meta.dataset` identify the
        variant. Includes VN2000 coordinates via `coord_vn2000`.
      x-i18n:
        vi:
          description: |
            Kết quả geocoding ngược cho một tọa độ địa lý. Trả về một phần tử cho mỗi biến thể
            dataset GADM (`addr34`/`addr63`); `subtype` và `meta.dataset` xác định biến thể.
            Kèm tọa độ VN2000 qua `coord_vn2000`.
      properties:
        id:
          type: string
          description: 'Place identifier (e.g., "latlon:21.05:105.74").'
          x-i18n:
            vi:
              description: "Mã định danh địa điểm (vd: 'latlon:21.05:105.74')."
        type:
          type: string
          description: Result type — always `latlon`.
          x-i18n:
            vi:
              description: Kiểu kết quả — luôn là `latlon`.
        name:
          type: string
          description: Place name (coordinate string for latlon places).
          x-i18n:
            vi:
              description: Tên địa điểm (chuỗi tọa độ đối với địa điểm latlon).
        subtype:
          type: string
          enum: [addr34, addr63]
          description: GADM dataset variant.
          x-i18n:
            vi:
              description: Biến thể dataset GADM.
        geometry:
          $ref: "#/components/schemas/Point"
        coord_vn2000:
          type: object
          description: VN2000 projected coordinates for the place.
          x-i18n:
            vi:
              description: Tọa độ VN2000 của địa điểm.
          properties:
            x:
              type: number
            y:
              type: number
            epsg:
              type: string
            zone_key:
              type: string
            central_meridian:
              type: number
        address:
          type: object
          description: Structured address components.
          x-i18n:
            vi:
              description: Các thành phần địa chỉ có cấu trúc.
          properties:
            id:
              type: string
            label:
              type: string
              description: Full address label.
              x-i18n:
                vi:
                  description: Nhãn địa chỉ đầy đủ.
            name:
              type: string
              description: Place name.
              x-i18n:
                vi:
                  description: Tên địa điểm.
            housenumber:
              type: string
            street:
              type: object
              properties:
                id:
                  type: string
                name:
                  type: string
                label:
                  type: string
                postcodes:
                  type: array
                  items:
                    type: string
            postcode:
              type: string
            vpostcode:
              type: string
            admins:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  label:
                    type: string
                  class_name:
                    type: string
        meta:
          type: object
          properties:
            dataset:
              type: string
              description: Source dataset (addr34, addr63, ...).
              x-i18n:
                vi:
                  description: Dataset nguồn (addr34, addr63, ...).
            maps_directions_url:
              type: string
            maps_place_url:
              type: string

    RouteResponse:
      type: object
      description: Routing response containing path geometry, distance, and estimated travel duration.
      x-i18n:
        vi:
          description: Kết quả định tuyến chứa hình học đường đi, khoảng cách và thời gian di chuyển ước tính.
      properties:
        code:
          type: string
          description: Status code — typically `Ok`.
          x-i18n:
            vi:
              description: Mã trạng thái — thường là `Ok`.
        routes:
          type: array
          items:
            type: object
            properties:
              geometry:
                type: object
                description: GeoJSON LineString representing the route path.
                x-i18n:
                  vi:
                    description: GeoJSON LineString biểu diễn tuyến đường.
                properties:
                  type:
                    type: string
                    enum: [LineString]
                  coordinates:
                    type: array
                    items:
                      type: array
                      items:
                        type: number
              distance:
                type: number
                description: Total route distance, in meters.
                x-i18n:
                  vi:
                    description: Tổng chiều dài tuyến đường, đơn vị mét.
              duration:
                type: number
                description: Estimated travel time, in seconds.
                x-i18n:
                  vi:
                    description: Thời gian di chuyển ước tính, đơn vị giây.
              legs:
                type: array
                description: Individual legs of the route.
                x-i18n:
                  vi:
                    description: Các chặng đường riêng lẻ.
              steps:
                type: array
                description: Turn-by-turn navigation instructions (populated when `steps=true`).
                x-i18n:
                  vi:
                    description: Hướng dẫn từng bước (được trả về khi `steps=true`).

    GeoJSON:
      type: object
      description: Generic GeoJSON geometry object.
      x-i18n:
        vi:
          description: Đối tượng hình học GeoJSON.

    ParcelResponse:
      type: object
      description: |
        Details for one land parcel. The Hasura REST response returns one or more parcel records
        inside an array property named after the function.
      x-i18n:
        vi:
          description: |
            Thông tin chi tiết của một thửa đất. Phản hồi Hasura REST chứa một hoặc nhiều bản ghi
            trong thuộc tính mảng mang tên hàm.
      properties:
        parcel_id:
          type: string
          format: uuid
          description: Unique parcel identifier
          x-i18n:
            vi:
              description: UUID định danh thửa đất
        so_to:
          type: string
          description: Map sheet number
          x-i18n:
            vi:
              description: Số tờ bản đồ
        so_thua:
          type: string
          description: Parcel number within the sheet
          x-i18n:
            vi:
              description: Số thửa trong tờ bản đồ
        ma_thua_dat:
          type: string
          description: Full parcel code (commune code + sheet + parcel number)
          x-i18n:
            vi:
              description: Mã thửa đầy đủ (mã xã + số tờ + số thửa)
        dien_tich_m2:
          type: number
          description: Parcel area in square meters
          x-i18n:
            vi:
              description: Diện tích thửa đất (m²)
        thong_tin_su_dung_dat:
          type: array
          description: Land-use information associated with the parcel.
          x-i18n:
            vi:
              description: Thông tin sử dụng đất của thửa đất.
          items:
            type: object
            properties:
              ma_su_dung_dat:
                type: string
                description: Current land use code
                x-i18n:
                  vi:
                    description: Mã sử dụng đất hiện trạng
              ten_su_dung_dat:
                type: string
                description: Current land use type name
                x-i18n:
                  vi:
                    description: Tên loại đất hiện trạng
              muc_dich_su_dung_dat:
                type: string
                description: Land use purpose description
                x-i18n:
                  vi:
                    description: Mô tả mục đích sử dụng đất
        ma_tinh_tp:
          type: string
          description: Current province/city code (gadm34)
          x-i18n:
            vi:
              description: Mã tỉnh/TP hiện tại (gadm34)
        ten_tinh_tp:
          type: string
          description: Current province/city name
          x-i18n:
            vi:
              description: Tên tỉnh/TP hiện tại
        ma_phuong_xa:
          type: string
          description: Current ward/commune code (gadm34)
          x-i18n:
            vi:
              description: Mã phường/xã hiện tại (gadm34)
        ten_phuong_xa:
          type: string
          description: Current ward/commune name
          x-i18n:
            vi:
              description: Tên phường/xã hiện tại
        ma_tinh_tp_cu:
          type: string
          description: Legacy province/city code (gadm63)
          x-i18n:
            vi:
              description: Mã tỉnh/TP cũ (gadm63)
        ten_tinh_tp_cu:
          type: string
          description: Legacy province/city name
          x-i18n:
            vi:
              description: Tên tỉnh/TP cũ
        ma_quan_huyen_cu:
          type: string
          description: Legacy district code (gadm63)
          x-i18n:
            vi:
              description: Mã quận/huyện cũ (gadm63)
        ten_quan_huyen_cu:
          type: string
          description: Legacy district name
          x-i18n:
            vi:
              description: Tên quận/huyện cũ
        ma_phuong_xa_cu:
          type: string
          description: Legacy ward/commune code (gadm63) — used for cadastral lookup
          x-i18n:
            vi:
              description: Mã phường/xã cũ (gadm63) — dùng để tra cứu cadastral
        ten_phuong_xa_cu:
          type: string
          description: Legacy ward/commune name
          x-i18n:
            vi:
              description: Tên phường/xã cũ
        center_geojson:
          $ref: "#/components/schemas/Point"
          description: Parcel center point
          x-i18n:
            vi:
              description: Tâm thửa đất
        geometry_geojson:
          $ref: "#/components/schemas/GeoJSON"
          description: Parcel geometry (MultiPolygon GeoJSON)
          x-i18n:
            vi:
              description: Hình học thửa đất (MultiPolygon GeoJSON)
        overlays:
          type: object
          description: |
            Planning overlays grouped by planning layer type (qh_phan_khu, qh_chi_tiet,
            qh_kien_truc, ...). The value of each key is an **array** of planning-layer
            entries, each carrying the layer metadata (`plan_code`, `loai_quy_hoach`,
            `ten_quy_hoach`, `mo_ta`, `nam_cap_phep`, `giay_to_phap_ly`) plus
            `projects[]` and `architecture_rules[]`.
          x-i18n:
            vi:
              description: |
                Các lớp quy hoạch giao cắt, nhóm theo loại quy hoạch (qh_phan_khu, qh_chi_tiet,
                qh_kien_truc, ...). Giá trị của mỗi key là một **mảng** các bản ghi lớp quy hoạch,
                mỗi bản ghi mang metadata của lớp (`plan_code`, `loai_quy_hoach`, `ten_quy_hoach`,
                `mo_ta`, `nam_cap_phep`, `giay_to_phap_ly`) cùng `projects[]` và `architecture_rules[]`.
          additionalProperties:
            type: array
            items:
              type: object
              properties:
                plan_code:
                  type: string
                  description: Planning layer code (e.g. `qh_phan_khu_da_nang`)
                  x-i18n:
                    vi:
                      description: "Mã lớp quy hoạch (vd: `qh_phan_khu_da_nang`)"
                loai_quy_hoach:
                  type: string
                  description: Planning layer type
                  x-i18n:
                    vi:
                      description: Loại quy hoạch
                ten_quy_hoach:
                  type: string
                  description: Planning layer name
                  x-i18n:
                    vi:
                      description: Tên quy hoạch
                mo_ta:
                  type: string
                  nullable: true
                nam_cap_phep:
                  type: string
                  nullable: true
                giay_to_phap_ly:
                  type: string
                  nullable: true
                projects:
                  type: array
                  items:
                    type: object
                    properties:
                      project_id:
                        type: string
                        format: uuid
                      project_name:
                        type: string
                      chu_dau_tu:
                        type: string
                        nullable: true
                      tinh_trang:
                        type: string
                      dien_tich_ha:
                        type: number
                      so_quyet_dinh:
                        type: string
                      ngay_phe_duyet:
                        type: string
                        nullable: true
                      nam_quy_hoach:
                        type: string
                      project_overlay:
                        type: object
                      zones:
                        type: array
                        items:
                          type: object
                architecture_rules:
                  type: array
                  items:
                    type: object
        thong_tin_khac:
          type: object
          description: Additional information about ownership, road frontage, and parcel shape.
          x-i18n:
            vi:
              description: Thông tin bổ sung về chủ sở hữu, mặt tiền đường và hình dạng thửa đất.
          properties:
            chu_so_huu:
              type: string
              nullable: true
              description: Owner name, when available.
              x-i18n:
                vi:
                  description: Tên chủ sở hữu, nếu có
            do_rong_duong_m:
              type: number
              nullable: true
              description: Road frontage width in metres, when available.
              x-i18n:
                vi:
                  description: Độ rộng đường tính bằng mét, nếu có
            khoang_cach_m:
              type: number
              nullable: true
              description: Distance in metres, when available.
              x-i18n:
                vi:
                  description: Khoảng cách tính bằng mét, nếu có
            so_mat_tien:
              type: number
              nullable: true
              description: Number of frontages, when available
              x-i18n:
                vi:
                  description: Số mặt tiền, nếu có
            huong_mat_tien:
              type: string
              nullable: true
              description: Direction of the parcel frontage, when available.
              x-i18n:
                vi:
                  description: Hướng mặt tiền, nếu có
            hinh_dang:
              type: string
              nullable: true
              description: Shape of the parcel, when available.
              x-i18n:
                vi:
                  description: Hình dạng thửa đất, nếu có
        confidence_score:
          type: number
          description: Data confidence score (0–1)
          x-i18n:
            vi:
              description: Độ tin cậy dữ liệu (0–1)
        data_source:
          type: string
          description: Data source name
          x-i18n:
            vi:
              description: Nguồn dữ liệu
        updated_at:
          type: string
          format: date-time
          description: Last update timestamp
          x-i18n:
            vi:
              description: Thời điểm cập nhật gần nhất

paths:
  # =========================================================================
  # Basemap
  # =========================================================================
  /api/tiles/{layer}/{z}/{x}/{y}:
    get:
      tags: [Basemap]
      operationId: getTile
      summary: "[Vector] Basemap"
      description: |
        Vector (PBF) or raster (PNG) map tiles.

        Available vector tile layers: `vietnam` (base map), `poi_point` (points of interest),
        `gadm34`, `gadm63` (administrative boundaries), `prop_planning_parcel` (land parcels),
        `parcels-view`, `parcels-density`, and `planning` (pre-rendered raster planning overlay).

        Icon sprites are served separately at `/api/tiles/sprite/icons.{json,png}`, and font glyphs
        at `/api/tiles/font/{fontstack}/{range}` (note: no `.pbf` extension on the range segment).
        Both require the same `x-api-key`.

        A `.pbf` suffix on the tile path is optional and is redirected to the extension-less path.
      x-i18n:
        vi:
          summary: "[Vector] Bản đồ nền"
          description: |
            Ô bản đồ vector (PBF) hoặc raster (PNG).

            Các lớp ô vector có sẵn: `vietnam` (bản đồ nền), `poi_point` (điểm quan tâm),
            `gadm34`, `gadm63` (ranh giới hành chính), `prop_planning_parcel` (thửa đất),
            `parcels-view`, `parcels-density`, và `planning` (lớp quy hoạch raster render sẵn).

            Sprite biểu tượng được phục vụ riêng tại `/api/tiles/sprite/icons.{json,png}`, và glyph
            phông chữ tại `/api/tiles/font/{fontstack}/{range}` (lưu ý: không có đuôi `.pbf` ở đoạn range).
            Cả hai đều yêu cầu cùng `x-api-key`.

            Đuôi `.pbf` trên đường dẫn ô bản đồ là tùy chọn và được chuyển hướng về đường dẫn không có đuôi.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: layer
          in: path
          required: true
          schema:
            type: string
          description: Tile layer name
          example: vietnam
          x-i18n:
            vi:
              description: Tên lớp ô bản đồ
        - name: z
          in: path
          required: true
          schema:
            type: integer
          description: Zoom level
          example: 12
          x-i18n:
            vi:
              description: Mức thu phóng
        - name: x
          in: path
          required: true
          schema:
            type: integer
          description: Tile X coordinate (Web Mercator)
          example: 3596
          x-i18n:
            vi:
              description: Tọa độ X của ô (Web Mercator)
        - name: y
          in: path
          required: true
          schema:
            type: integer
          description: Tile Y coordinate (Web Mercator)
          example: 2171
          x-i18n:
            vi:
              description: Tọa độ Y của ô (Web Mercator)
      responses:
        "200":
          description: Tile binary data
          x-i18n:
            vi:
              description: Dữ liệu nhị phân ô bản đồ
          content:
            application/vnd.mapbox-vector-tile:
              schema:
                type: string
                format: binary
            image/png:
              schema:
                type: string
                format: binary

  /api/satellite/tiles/{z}/{x}/{y}:
    get:
      tags: [Basemap]
      operationId: getSatelliteTile
      summary: "[Raster] Satellite imagery"
      description: |
        Raster (PNG/JPEG) satellite imagery tiles at the specified zoom level and coordinates.
        Pre-rendered tiles served from PMTiles.

        > **Path note:** the path segments use standard slippy-map `z/x/y` order (`{z}/{x}/{y}`).
      x-i18n:
        vi:
          summary: "[Raster] Bản đồ vệ tinh"
          description: |
            Ô ảnh vệ tinh raster (PNG/JPEG) tại mức zoom và tọa độ được chỉ định.
            Ô được render sẵn từ PMTiles.

            > **Lưu ý đường dẫn:** thứ tự các đoạn đường dẫn theo chuẩn slippy-map `z/x/y` (`{z}/{x}/{y}`).
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
          description: Zoom level (0–16)
          example: 14
          x-i18n:
            vi:
              description: Mức thu phóng (0–16)
        - name: x
          in: path
          required: true
          schema:
            type: integer
          description: Tile X (Web Mercator)
          example: 13008
          x-i18n:
            vi:
              description: Tọa độ X ô (Web Mercator)
        - name: y
          in: path
          required: true
          schema:
            type: integer
          description: Tile Y (Web Mercator)
          example: 7211
          x-i18n:
            vi:
              description: Tọa độ Y ô (Web Mercator)
      responses:
        "200":
          description: Raster tile image
          x-i18n:
            vi:
              description: Ảnh ô raster
          content:
            image/png:
              schema:
                type: string
                format: binary

  /api/satellite/street/{z}/{x}/{y}:
    get:
      tags: [Basemap]
      operationId: getStreetTile
      summary: "[Vector] Street map"
      description: |
        Vector (PBF) street-level tiles containing the road network and building footprint data.
      x-i18n:
        vi:
          summary: "[Vector] Bản đồ đường phố"
          description: |
            Ô vector (PBF) cấp đường phố chứa dữ liệu mạng lưới đường và hình khối tòa nhà.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
          example: 12
          description: Zoom level
          x-i18n:
            vi:
              description: Mức thu phóng
        - name: x
          in: path
          required: true
          schema:
            type: integer
          example: 1803
          description: Tile X (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ X ô (Web Mercator)
        - name: y
          in: path
          required: true
          schema:
            type: integer
          example: 3250
          description: Tile Y (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ Y ô (Web Mercator)
      responses:
        "200":
          description: Vector tile (PBF)
          x-i18n:
            vi:
              description: Ô vector (PBF)
          content:
            application/vnd.mapbox-vector-tile:
              schema:
                type: string
                format: binary

  /api/satellite/streetimage/{image_id}:
    get:
      tags: [Basemap]
      operationId: getStreetImage
      summary: "[API] Street-level imagery"
      description: |
        Street-level thumbnail and panorama images for the specified image identifier.
        Supports thumbnail size selection via the `thumb` query parameter.
      x-i18n:
        vi:
          summary: "[API] Hình ảnh đường phố"
          description: |
            Ảnh thumbnail và toàn cảnh cấp đường phố cho mã định danh ảnh được chỉ định.
            Hỗ trợ chọn kích thước thumbnail qua tham số `thumb`.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: image_id
          in: path
          required: true
          schema:
            type: string
          example: "6768646546567146"
          description: Street-level image identifier
          x-i18n:
            vi:
              description: Mã định danh hình ảnh đường phố
        - name: thumb
          in: query
          schema:
            type: string
          example: original
          description: Thumbnail size (e.g. "original", "1024", "512")
          x-i18n:
            vi:
              description: 'Kích thước thumbnail (vd: "original", "1024", "512")'
      responses:
        "200":
          description: Street image
          x-i18n:
            vi:
              description: Hình ảnh đường phố
          content:
            image/jpeg:
              schema:
                type: string
                format: binary

  /api/satellite/demo/:
    get:
      tags: [Basemap]
      operationId: getSatelliteDemo
      summary: "[Page] Satellite & planning demo"
      description: |
        Interactive Leaflet demo page for satellite imagery and the QHSDD planning overlay.
        Accepts the `x-api-key` as a query parameter. Both `/demo/` and `/demo` work.
      x-i18n:
        vi:
          summary: "[Trang] Demo vệ tinh & quy hoạch"
          description: |
            Trang demo Leaflet tương tác cho ảnh vệ tinh và lớp quy hoạch QHSDD.
            Chấp nhận `x-api-key` dưới dạng query parameter. Cả `/demo/` và `/demo` đều hoạt động.
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Interactive demo HTML page
          x-i18n:
            vi:
              description: Trang demo HTML tương tác
          content:
            text/html:
              schema:
                type: string

  /api/idunn/v1/redirect:
    get:
      tags: [Address & POI]
      operationId: resolveRedirect
      summary: "[API] Resolve a shortlink redirect"
      description: |
        Follows an Idunn-generated redirect. Callers obtain `url` and `hash` from place metadata
        (e.g. `maps_directions_url`/`maps_place_url`). Returns `307` on success, `403` on bad hash,
        and `404` when the target does not redirect.
      x-i18n:
        vi:
          summary: "[API] Phân giải redirect ngắn"
          description: |
            Theo một redirect do Idunn sinh ra. Người gọi nhận `url` và `hash` từ metadata địa điểm
            (vd: `maps_directions_url`/`maps_place_url`). Trả `307` khi thành công, `403` khi sai hash,
            `404` khi đích không redirect.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: url
          in: query
          required: true
          schema:
            type: string
          description: Target URL to follow
          x-i18n:
            vi:
              description: URL đích cần theo
        - name: hash
          in: query
          required: true
          schema:
            type: string
          description: HMAC hash of the URL provided by Idunn
          x-i18n:
            vi:
              description: HMAC hash của URL do Idunn cung cấp
      responses:
        "307":
          description: Redirect to the target
          x-i18n:
            vi:
              description: Chuyển hướng tới đích
        "403":
          description: Wrong URL hash
          x-i18n:
            vi:
              description: Sai hash URL
        "404":
          description: The URL does not redirect
          x-i18n:
            vi:
              description: URL không redirect

  /api/satellite/landlotdetailsimage/{imageurl}:
    get:
      tags: [Basemap]
      operationId: getLandlotDetailsImage
      summary: "[API] Land-lot detail image"
      description: |
        Returns a land-lot detail image. The identifier maps to an S3 object under
        `landlotdetailsimage/...`; when absent the request is proxied from an external CDN.
      x-i18n:
        vi:
          summary: "[API] Ảnh chi tiết thửa đất"
          description: |
            Trả về ảnh chi tiết thửa đất. Mã định danh ánh xạ tới object S3 dưới
            `landlotdetailsimage/...`; nếu chưa có, yêu cầu được proxy từ CDN bên ngoài.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: imageurl
          in: path
          required: true
          schema:
            type: string
          description: Image object path (may include sub-paths)
          x-i18n:
            vi:
              description: Đường dẫn object ảnh (có thể gồm nhiều cấp)
      responses:
        "200":
          description: Land-lot detail image
          x-i18n:
            vi:
              description: Ảnh chi tiết thửa đất
          content:
            image/png:
              schema:
                type: string
                format: binary

  /api/satellite/planning_hcm/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getPlanningHcmTile
      summary: "[Raster] HCM planning overlay (Thủ Đức)"
      description: |
        Raster (PNG) tile of the HCM (Thủ Đức) planning overlay.
        Returns `204 No Content` when no data covers the tile.
      x-i18n:
        vi:
          summary: "[Raster] Lớp quy hoạch HCM (Thủ Đức)"
          description: |
            Ô raster (PNG) lớp quy hoạch HCM (Thủ Đức).
            Trả `204 No Content` khi không có dữ liệu cho ô.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
        - name: x
          in: path
          required: true
          schema:
            type: integer
        - name: y
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Raster tile image
          x-i18n:
            vi:
              description: Ảnh ô raster
          content:
            image/png:
              schema:
                type: string
                format: binary
        "204":
          description: No data for tile
          x-i18n:
            vi:
              description: Không có dữ liệu cho ô

  /api/satellite/thuduc_parcel_borders/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getThuducParcelBordersTile
      summary: "[Raster] Thủ Đức parcel borders"
      description: |
        Raster (PNG) tile of parcel border outlines for Thủ Đức.
        Returns `204 No Content` when no data covers the tile.
      x-i18n:
        vi:
          summary: "[Raster] Ranh giới thửa đất Thủ Đức"
          description: |
            Ô raster (PNG) đường ranh thửa đất Thủ Đức.
            Trả `204 No Content` khi không có dữ liệu cho ô.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
        - name: x
          in: path
          required: true
          schema:
            type: integer
        - name: y
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Raster tile image
          x-i18n:
            vi:
              description: Ảnh ô raster
          content:
            image/png:
              schema:
                type: string
                format: binary
        "204":
          description: No data for tile
          x-i18n:
            vi:
              description: Không có dữ liệu cho ô

  /api/satellite/planning_hcm_all/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getPlanningHcmAllTile
      summary: "[Raster] HCM planning overlay (all)"
      description: |
        Raster (PNG) tile of the full HCM planning overlay.
        Returns `204 No Content` when no data covers the tile.
      x-i18n:
        vi:
          summary: "[Raster] Lớp quy hoạch HCM (toàn bộ)"
          description: |
            Ô raster (PNG) lớp quy hoạch HCM toàn bộ.
            Trả `204 No Content` khi không có dữ liệu cho ô.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
        - name: x
          in: path
          required: true
          schema:
            type: integer
        - name: y
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Raster tile image
          x-i18n:
            vi:
              description: Ảnh ô raster
          content:
            image/png:
              schema:
                type: string
                format: binary
        "204":
          description: No data for tile
          x-i18n:
            vi:
              description: Không có dữ liệu cho ô

  /api/satellite/land_use_plan_paper/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getLandUsePlanPaperTile
      summary: "[Raster] Land-use plan (paper) tiles"
      description: |
        Raster (PNG) tile of scanned land-use planning (paper) maps.
        Returns `204 No Content` when no data covers the tile.
      x-i18n:
        vi:
          summary: "[Raster] Bản đồ quy hoạch sử dụng đất (bản giấy)"
          description: |
            Ô raster (PNG) bản đồ quy hoạch sử dụng đất (bản giấy quét).
            Trả `204 No Content` khi không có dữ liệu cho ô.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
        - name: x
          in: path
          required: true
          schema:
            type: integer
        - name: y
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Raster tile image
          x-i18n:
            vi:
              description: Ảnh ô raster
          content:
            image/png:
              schema:
                type: string
                format: binary
        "204":
          description: No data for tile
          x-i18n:
            vi:
              description: Không có dữ liệu cho ô

  /api/satellite/planning/download_pdf/{id}:
    get:
      tags: [Business Layer]
      operationId: downloadPlanningPdf
      summary: "[API] Download planning PDF"
      description: |
        Downloads a planning decision PDF document by identifier.
      x-i18n:
        vi:
          summary: "[API] Tải PDF quy hoạch"
          description: |
            Tải tài liệu PDF quyết định quy hoạch theo mã định danh.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: Planning PDF document identifier
          example: "002_2012_6692"
          x-i18n:
            vi:
              description: Mã định danh tài liệu PDF quy hoạch
      responses:
        "200":
          description: PDF document
          x-i18n:
            vi:
              description: Tài liệu PDF
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        "404":
          description: No PDF with this identifier
          x-i18n:
            vi:
              description: Không có PDF với mã định danh này

  /api/tiles/style/basemap:
    get:
      tags: [Basemap]
      operationId: getBasemapStyle
      summary: "[TileJson] Basemap light style"
      description: |
        Pre-composed MapLibre style descriptor combining 116 layers across
        landcover, landuse, water, parks, buildings (with 3D extrusion), transportation
        (roads, tunnels, bridges, railways, ferries), aeroways, administrative boundaries,
        place labels, and POI markers. Sources `basemap` (vector) and `poi` (vector),
        with sprite and font glyph endpoints for text rendering.

        | Source | Type | Source Layers |
        |--------|------|---------------|
        | `basemap` | vector | `landcover`, `landuse`, `park`, `water`, `waterway`, `water_name`, `building`, `transportation`, `transportation_name`, `aeroway`, `aerodrome_label`, `boundary`, `place` |
        | `poi` | vector | `poi`, `poi_point` |

        Integrate with MapLibre GL JS via:

        ```js
        new maplibregl.Map({
          container: 'map',
          style: `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=${KEY}`,
        });
        ```
      x-i18n:
        vi:
          summary: "[TileJson] Style bản đồ nền sáng"
          description: |
            Style descriptor MapLibre được tổ hợp sẵn, gồm 116 lớp bao phủ
            phủ bề mặt, sử dụng đất, mặt nước, công viên, tòa nhà (có đùn 3D),
            giao thông (đường bộ, hầm, cầu, đường sắt, phà), sân bay, ranh giới hành chính,
            nhãn địa danh và điểm POI. Nguồn `basemap` (vector) và `poi` (vector),
            kèm sprite và font glyph endpoint để hiển thị văn bản.

            | Nguồn | Kiểu | Lớp dữ liệu |
            |-------|------|-------------|
            | `basemap` | vector | `landcover`, `landuse`, `park`, `water`, `waterway`, `water_name`, `building`, `transportation`, `transportation_name`, `aeroway`, `aerodrome_label`, `boundary`, `place` |
            | `poi` | vector | `poi`, `poi_point` |

            Tích hợp với MapLibre GL JS:

            ```js
            new maplibregl.Map({
              container: 'map',
              style: `https://cloud.gmap.vn/api/tiles/style/basemap?x-api-key=${KEY}`,
            });
            ```
      security:
        - ApiKeyAuth: []
      parameters:
        - name: x-api-key
          in: query
          schema:
            type: string
          example: public-gmap-cloud-x-api-key-demo
          description: API key for authentication
          x-i18n:
            vi:
              description: Khóa API để xác thực
      responses:
        "200":
          description: MapLibre style JSON
          x-i18n:
            vi:
              description: MapLibre style JSON
          content:
            application/json:
              schema:
                type: object

  /api/tiles/style/darkmap:
    get:
      tags: [Basemap]
      operationId: getDarkmapStyle
      summary: "[TileJson] Basemap dark style"
      description: |
        Dark-theme variant of the MapLibre style descriptor. Same 116-layer
        composition — landcover, landuse, water, parks, buildings (with 3D extrusion),
        transportation (roads, tunnels, bridges, railways, ferries), aeroways,
        administrative boundaries, place labels, and POI markers — rendered with
        a dark color scheme optimized for low-light environments.

        | Source | Type | Source Layers |
        |--------|------|---------------|
        | `darkmap` | vector | `landcover`, `landuse`, `park`, `water`, `waterway`, `water_name`, `building`, `transportation`, `transportation_name`, `aeroway`, `aerodrome_label`, `boundary`, `place` |
        | `poi` | vector | `poi`, `poi_point` |

        Switch to the dark style at runtime:

        ```js
        map.setStyle(`https://cloud.gmap.vn/api/tiles/style/darkmap?x-api-key=${KEY}`);
        ```
      x-i18n:
        vi:
          summary: "[TileJson] Style bản đồ nền tối"
          description: |
            Biến thể giao diện tối của style descriptor MapLibre. Giữ nguyên 116 lớp
            — phủ bề mặt, sử dụng đất, mặt nước, công viên, tòa nhà (có đùn 3D),
            giao thông (đường bộ, hầm, cầu, đường sắt, phà), sân bay, ranh giới hành chính,
            nhãn địa danh và điểm POI — hiển thị với bảng màu tối tối ưu cho môi trường
            thiếu sáng.

            | Nguồn | Kiểu | Lớp dữ liệu |
            |-------|------|-------------|
            | `darkmap` | vector | `landcover`, `landuse`, `park`, `water`, `waterway`, `water_name`, `building`, `transportation`, `transportation_name`, `aeroway`, `aerodrome_label`, `boundary`, `place` |
            | `poi` | vector | `poi`, `poi_point` |

            Chuyển sang giao diện tối khi đang chạy:

            ```js
            map.setStyle(`https://cloud.gmap.vn/api/tiles/style/darkmap?x-api-key=${KEY}`);
            ```
      security:
        - ApiKeyAuth: []
      parameters:
        - name: x-api-key
          in: query
          schema:
            type: string
          example: public-gmap-cloud-x-api-key-demo
          description: API key for authentication
          x-i18n:
            vi:
              description: Khóa API để xác thực
      responses:
        "200":
          description: MapLibre style JSON
          x-i18n:
            vi:
              description: MapLibre style JSON
          content:
            application/json:
              schema:
                type: object

  # =========================================================================
  # Business Layer
  # =========================================================================
  /api/satellite/re-qhsdd/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getPlanningRasterTile
      summary: "[Raster] Land-use planning"
      description: |
        Pre-rendered raster (PNG) tiles displaying land-use planning zones
        (quy hoạch sử dụng đất đai). These tiles overlay the satellite basemap.
        Served from PMTiles.
      x-i18n:
        vi:
          summary: "[Raster] Quy hoạch sử dụng đất"
          description: |
            Ô raster (PNG) hiển thị vùng quy hoạch sử dụng đất đai.
            Các ô này phủ lên nền bản đồ vệ tinh. Dữ liệu từ PMTiles.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
          description: Zoom level (0–16).
          example: 14
          x-i18n:
            vi:
              description: Mức thu phóng (0–16).
        - name: x
          in: path
          required: true
          schema:
            type: integer
          description: Tile X (Web Mercator)
          example: 13006
          x-i18n:
            vi:
              description: Tọa độ X ô (Web Mercator)
        - name: y
          in: path
          required: true
          schema:
            type: integer
          description: Tile Y (Web Mercator)
          example: 7214
          x-i18n:
            vi:
              description: Tọa độ Y ô (Web Mercator)
      responses:
        "200":
          description: Planning raster tile (PNG, 256x256)
          x-i18n:
            vi:
              description: Ô quy hoạch raster (PNG, 256x256)
          content:
            image/png:
              schema:
                type: string
                format: binary

  /api/tiles/parcels-view/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getParcelsViewTile
      summary: "[Vector] Parcel detail"
      description: |
        Vector (PBF) tiles displaying individual parcel polygon geometries at zoom level 17.
        Delivers boundary-accurate shapes for inspection-level views. Served from `martin-cp`
        with gzip compression.
      x-i18n:
        vi:
          summary: "[Vector] Chi tiết thửa đất"
          description: |
            Ô vector (PBF) hiển thị đa giác từng thửa đất ở mức zoom 17.
            Cung cấp hình học chính xác theo ranh giới phục vụ chế độ xem chi tiết.
            Dữ liệu từ `martin-cp`, nén gzip.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
          description: Zoom level (17)
          example: 17
          x-i18n:
            vi:
              description: Mức thu phóng (17)
        - name: x
          in: path
          required: true
          schema:
            type: integer
          description: Tile X (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ X ô (Web Mercator)
        - name: y
          in: path
          required: true
          schema:
            type: integer
          description: Tile Y (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ Y ô (Web Mercator)
      responses:
        "200":
          description: Vector tile (PBF, gzip)
          x-i18n:
            vi:
              description: Ô vector (PBF, gzip)
          content:
            application/vnd.mapbox-vector-tile:
              schema:
                type: string
                format: binary

  /api/tiles/parcels-density/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getParcelsDensityTile
      summary: "[Vector] Parcel density"
      description: |
        Vector (PBF) tiles providing an aggregated parcel density grid at zoom levels 0–16.
        Each grid cell contains a `parcel_count` property for choropleth and heatmap rendering.
      x-i18n:
        vi:
          summary: "[Vector] Mật độ thửa đất"
          description: |
            Ô vector (PBF) cung cấp lưới mật độ thửa đất tổng hợp ở mức zoom 0–16.
            Mỗi ô lưới chứa thuộc tính `parcel_count` phục vụ hiển thị choropleth và heatmap.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
          description: Zoom level (0–16)
          example: 10
          x-i18n:
            vi:
              description: Mức thu phóng (0–16)
        - name: x
          in: path
          required: true
          schema:
            type: integer
          description: Tile X (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ X ô (Web Mercator)
        - name: y
          in: path
          required: true
          schema:
            type: integer
          description: Tile Y (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ Y ô (Web Mercator)
      responses:
        "200":
          description: Vector tile (PBF, gzip)
          x-i18n:
            vi:
              description: Ô vector (PBF, gzip)
          content:
            application/vnd.mapbox-vector-tile:
              schema:
                type: string
                format: binary

  # =========================================================================
  # Navigation
  # =========================================================================
  /api/route/v1/{mode}/{coord_string}:
    get:
      tags: [Navigation]
      operationId: routing
      summary: "[API] Basic — OSRM routing"
      description: |
        Fastest-route computation between coordinates using the Open Source Routing Machine
        (OSRM v5). Supports multiple waypoints in `lon,lat` order separated by semicolons.
        Three travel profiles are available: `car` (driving), `bike` (motorbike), and
        `foot` (pedestrian).

        **Coordinate format:** `{lon},{lat};{lon},{lat}[;...]` — at least 2 pairs required.
        Coordinates can also be supplied as a polyline: `polyline({encoded})`.

        **Authentication:** Send the API key via the `x-api-key` HTTP header:

        ```bash
        curl 'https://cloud.gmap.vn/api/route/v1/car/105.854,21.028;105.835,21.037?geometries=geojson&overview=full&steps=true&alternatives=false' \\
          --header 'x-api-key: public-gmap-cloud-x-api-key-demo'
        ```

        **Key parameters:**

        | Parameter | Values | Default | Description |
        |-----------|--------|---------|-------------|
        | `geometries` | `polyline`, `geojson` | `polyline` | Route geometry format. Polyline is compact (Google encoded); GeoJSON returns full `LineString`. |
        | `steps` | `true`, `false` | `false` | Return turn-by-turn `RouteStep` objects with street names, maneuver types, and per-step geometry. |
        | `overview` | `full`, `simplified`, `false` | `simplified` | Geometry detail: `full` returns all coordinates, `simplified` reduces to ~17 points, `false` omits geometry entirely. |
        | `alternatives` | `true`, `false` | `false` | Search for alternative routes. Note: not guaranteed to return extras. |
        | `annotations` | `true`, `false` | `false` | Per-coordinate metadata: `distance`, `duration`, `speed` (km/h), `nodes` (OSM node IDs), `datasources`, and `weight`. |
        | `continue_straight` | `true`, `false`, `default` | `default` | Force straight through waypoints, preventing U-turns even if faster. |

        **Available OSRM services:** Only the `route` service is exposed via the GMap API.
        The `nearest`, `table`, `match`, and `trip` OSRM services are not available.
        Use the Valhalla `/api/tsp/route/` endpoints for table, optimized route,
        isochrone, trace, and elevation queries.

        **Error codes:**

        | Code | Description |
        |------|-------------|
        | `Ok` | Route found successfully |
        | `NoRoute` | No path exists between the given coordinates |
        | `NoSegment` | A coordinate could not snap to a road segment |
        | `TooBig` | Request exceeds service size limits |
        | `InvalidQuery` | Malformed query string |
        | `InvalidValue` | Valid syntax but invalid parameter values |

        See also the official [OSRM API docs](https://project-osrm.org/docs/v5.5.1/api/#route-service).
      x-i18n:
        vi:
          summary: "[API] Cơ bản — Tìm đường OSRM"
          description: |
            Tính toán đường đi nhanh nhất giữa các tọa độ sử dụng Open Source Routing Machine
            (OSRM v5). Hỗ trợ nhiều điểm dừng (waypoint) theo thứ tự `lon,lat` cách nhau bởi dấu
            chấm phẩy. Ba hồ sơ di chuyển có sẵn: `car` (ô tô), `bike` (xe máy), `foot` (đi bộ).

            **Định dạng tọa độ:** `{lon},{lat};{lon},{lat}[;...]` — tối thiểu 2 cặp.
            Cũng có thể cung cấp dưới dạng polyline: `polyline({encoded})`.

            **Xác thực:** Gửi API key qua HTTP header `x-api-key`:

            ```bash
            curl 'https://cloud.gmap.vn/api/route/v1/car/105.854,21.028;105.835,21.037?geometries=geojson&overview=full&steps=true&alternatives=false' \\
              --header 'x-api-key: public-gmap-cloud-x-api-key-demo'
            ```

            **Tham số chính:**

            | Tham số | Giá trị | Mặc định | Mô tả |
            |---------|---------|----------|-------|
            | `geometries` | `polyline`, `geojson` | `polyline` | Định dạng hình học. Polyline nén gọn; GeoJSON trả về `LineString` đầy đủ. |
            | `steps` | `true`, `false` | `false` | Trả về chỉ dẫn rẽ từng bước (`RouteStep`) kèm tên đường, loại rẽ và hình học. |
            | `overview` | `full`, `simplified`, `false` | `simplified` | Mức chi tiết: `full` toàn bộ tọa độ, `simplified` rút gọn ~17 điểm, `false` bỏ hình học. |
            | `alternatives` | `true`, `false` | `false` | Tìm tuyến thay thế. Không đảm bảo luôn có kết quả thêm. |
            | `annotations` | `true`, `false` | `false` | Metadata từng điểm: `distance`, `duration`, `speed` (km/h), `nodes` (mã nút OSM), `datasources`, `weight`. |
            | `continue_straight` | `true`, `false`, `default` | `default` | Đi thẳng qua waypoint, ngăn quay đầu kể cả khi nhanh hơn. |

            **Dịch vụ OSRM khả dụng:** Chỉ dịch vụ `route` được cung cấp qua GMap API.
            Các dịch vụ `nearest`, `table`, `match`, và `trip` của OSRM không khả dụng.
            Sử dụng endpoint Valhalla `/api/tsp/route/` cho table, optimized route,
            isochrone, trace và elevation.

            **Mã lỗi:**

            | Mã | Mô tả |
            |----|-------|
            | `Ok` | Tìm thấy tuyến đường |
            | `NoRoute` | Không có đường đi giữa các tọa độ đã cho |
            | `NoSegment` | Tọa độ không khớp được vào đoạn đường nào |
            | `TooBig` | Yêu cầu vượt quá giới hạn dịch vụ |
            | `InvalidQuery` | Chuỗi truy vấn sai cú pháp |
            | `InvalidValue` | Cú pháp đúng nhưng giá trị tham số không hợp lệ |

            Xem thêm [tài liệu chính thức OSRM API](https://project-osrm.org/docs/v5.5.1/api/#route-service).
      security:
        - ApiKeyAuth: []
      parameters:
        - name: mode
          in: path
          required: true
          schema:
            type: string
            enum: [car, bike, foot]
          description: Travel mode
          example: car
          x-i18n:
            vi:
              description: Phương thức di chuyển (car=ô tô, bike=xe máy, foot=đi bộ)
        - name: coord_string
          in: path
          required: true
          schema:
            type: string
          description: |
            Semicolon-separated coordinate pairs in `lon,lat` format.
            Minimum 2 points. Hoàn Kiếm → West Lake example: `105.854,21.028;105.835,21.037`
          x-i18n:
            vi:
              description: |
                Chuỗi các cặp tọa độ ngăn cách bởi dấu chấm phẩy, định dạng `lon,lat`.
                Tối thiểu 2 điểm. Ví dụ Hồ Hoàn Kiếm → Hồ Tây: `105.854,21.028;105.835,21.037`
          example: "105.854,21.028;105.835,21.037"
        - name: geometries
          in: query
          required: true
          schema:
            type: string
            enum: [polyline, geojson]
            default: geojson
          example: geojson
          description: Geometry output format
          x-i18n:
            vi:
              description: Định dạng hình học đầu ra
        - name: steps
          in: query
          required: true
          schema:
            type: boolean
            default: true
          example: true
          description: Include turn-by-turn instructions
          x-i18n:
            vi:
              description: Bao gồm hướng dẫn từng bước
        - name: alternatives
          in: query
          required: true
          schema:
            type: boolean
            default: false
          example: false
          description: Return alternative routes
          x-i18n:
            vi:
              description: Trả về các tuyến đường thay thế
        - name: overview
          in: query
          required: true
          schema:
            type: string
            enum: [full, simplified]
            default: full
          example: full
          description: Route geometry detail level
          x-i18n:
            vi:
              description: Mức độ chi tiết hình học tuyến đường
      responses:
        "200":
          description: Route information
          x-i18n:
            vi:
              description: Thông tin tuyến đường
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RouteResponse"
              example:
                code: "Ok"
                routes:
                  - geometry: "c_j_CkraeSt@}JzBL`LfCuEtT}Knm@_@p@k@fCsf@xe@c@`@_@A@^yAdBs@rGQCE^{Eu@"
                    distance: 3220.7
                    duration: 1081.8
                    weight_name: "duration"
                    weight: 1081.8
                    legs:
                      - distance: 3220.7
                        duration: 1081.8
                        steps: []
                        summary: ""
                        weight: 1081.8
                waypoints:
                  - distance: 16.2
                    location: [105.853978, 21.027855]
                    name: ""
                  - distance: 1.4
                    location: [105.835013, 21.036998]
                    name: ""

  # Valhalla routing
  /api/tsp/route/route:
    post:
      tags: [Navigation]
      operationId: valhallaRoute
      summary: "[API] Advanced — Routing"
      description: |
        Turn-by-turn route with detailed step-by-step navigation instructions.
        Supports costing models: auto, bicycle, pedestrian, truck, bus, taxi,
        motorcycle, motor_scooter, and multimodal. Returns geometry (polyline
        or GeoJSON), distance, duration, and maneuver instructions.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Tìm đường Valhalla"
          description: |
            Đường đi kèm hướng dẫn chi tiết từng bước. Hỗ trợ các mô hình chi phí:
            auto, bicycle, pedestrian, truck, bus, taxi, motorcycle,
            motor_scooter và multimodal. Trả về hình học (polyline hoặc GeoJSON),
            khoảng cách, thời gian và chỉ dẫn từng bước.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              locations:
                - lat: 21.0285
                  lon: 105.8542
                  type: break
                - lat: 21.0367
                  lon: 105.8352
                  type: break
              costing: auto
      responses:
        "200":
          description: Route result
          x-i18n:
            vi:
              description: Kết quả định tuyến
          content:
            application/json:
              schema:
                type: object
              example:
                trip:
                  locations:
                    - type: break
                      lat: 21.0285
                      lon: 105.8542
                      side_of_street: right
                      original_index: 0
                    - type: break
                      lat: 21.0367
                      lon: 105.8352
                      side_of_street: right
                      original_index: 1
                  legs:
                    - maneuvers:
                        - type: 10
                          instruction: "Turn right onto Phố Đinh Tiên Hoàng."
                          street_names: ["Phố Đinh Tiên Hoàng"]
                          time: 52.045
                          length: 0.517
                          travel_mode: drive
                          travel_type: car

  /api/tsp/route/optimized_route:
    post:
      tags: [Navigation]
      operationId: valhallaOptimizedRoute
      summary: "[API] Advanced — Optimized route (TSP)"
      description: |
        Travelling Salesman Problem (TSP) solver for optimal multi-stop route ordering.
        Accepts a list of waypoints and returns the optimal visiting sequence
        with total distance and duration.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Optimized route (TSP)"
          description: |
            Giải thuật Travelling Salesman Problem (TSP) cho sắp xếp thứ tự tuyến đa điểm tối ưu.
            Nhận danh sách điểm đến và trả về thứ tự tham quan tối ưu
            kèm tổng khoảng cách và thời gian.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              locations:
                - lat: 21.0285
                  lon: 105.8542
                  type: break
                - lat: 21.0367
                  lon: 105.8352
                  type: break
                - lat: 21.0150
                  lon: 105.8470
                  type: break
              costing: auto
      responses:
        "200":
          description: Optimized route result
          x-i18n:
            vi:
              description: Kết quả tuyến tối ưu
          content:
            application/json:
              schema:
                type: object
              example:
                trip:
                  locations:
                    - type: break
                      lat: 21.0285
                      lon: 105.8542
                      side_of_street: right
                      original_index: 0
                    - type: break
                      lat: 21.0367
                      lon: 105.8352
                      side_of_street: right
                      original_index: 1
                    - type: break
                      lat: 21.03
                      lon: 105.85
                      side_of_street: right
                      original_index: 2
                  legs:
                    - maneuvers:
                        - type: 10
                          instruction: "Turn right onto Phố Đinh Tiên Hoàng."
                          street_names: ["Phố Đinh Tiên Hoàng"]
                          time: 52.045
                          length: 0.517
                          travel_mode: drive

  /api/tsp/route/sources_to_targets:
    post:
      tags: [Navigation]
      operationId: valhallaMatrix
      summary: "[API] Advanced — Matrix (time-distance)"
      description: |
        Computes the time and distance between multiple sources and targets.
        Accepts arrays of source and target locations and returns a cost matrix
        for each source-target pair.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Matrix (time-distance)"
          description: |
            Tính toán thời gian và khoảng cách giữa nhiều điểm đi (sources) và điểm đến (targets).
            Nhận mảng vị trí nguồn và đích, trả về ma trận chi phí
            cho từng cặp source-target.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              sources:
                - lat: 21.0285
                  lon: 105.8542
                - lat: 21.0367
                  lon: 105.8352
              targets:
                - lat: 21.0150
                  lon: 105.8470
                - lat: 21.0450
                  lon: 105.8200
              costing: auto
      responses:
        "200":
          description: Time-distance matrix
          x-i18n:
            vi:
              description: Ma trận thời gian-khoảng cách
          content:
            application/json:
              schema:
                type: object
              example:
                sources_to_targets:
                  - - time: 387
                      distance: 3.936
                      from_index: 0
                      to_index: 0
                sources:
                  - lat: 21.028426
                    lon: 105.854092
                targets:
                  - lat: 21.036474
                    lon: 105.83647
                units: kilometers
                algorithm: costmatrix

  /api/tsp/route/isochrone:
    post:
      tags: [Navigation]
      operationId: valhallaIsochrone
      summary: "[API] Advanced — Isochrone"
      description: |
        Computes reachability polygons for a given location. Specify time contours
        (in minutes) or distance contours (in kilometers). Returns GeoJSON polygons.
        Supports `format=geotiff` for raster output.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Isochrone"
          description: |
            Tính toán đa giác vùng phủ cho một vị trí. Chỉ định đường đồng mức thời gian
            (phút) hoặc khoảng cách (km). Trả về GeoJSON đa giác.
            Hỗ trợ `format=geotiff` cho đầu ra raster.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              locations:
                - lat: 21.0285
                  lon: 105.8542
              costing: auto
              contours:
                - time: 15
                - time: 30
      responses:
        "200":
          description: Isochrone result
          x-i18n:
            vi:
              description: Kết quả isochrone
          content:
            application/json:
              schema:
                type: object
              example:
                features:
                  - properties:
                      fill-opacity: 0.33
                      fillColor: "#bf4040"
                      contour: 5.0
                      metric: time
                    geometry:
                      type: Polygon
                      coordinates: [[[105.8412, 21.050332], [105.840403, 21.0495], [105.841024, 21.049324]]]

  /api/tsp/route/trace_route:
    post:
      tags: [Navigation]
      operationId: valhallaTraceRoute
      summary: "[API] Advanced — Map-matched route"
      description: |
        Map-matches a GPS trace to the road network and returns a turn-by-turn
        route along the matched path. Supports shape matching strategies:
        edge_walk, map_snap, walk_or_snap.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Map-matched route"
          description: |
            Khớp vết GPS vào mạng lưới đường và trả về đường đi từng bước
            dọc theo đường đã khớp. Hỗ trợ chiến lược khớp: edge_walk,
            map_snap, walk_or_snap.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              shape:
                - lat: 21.02424
                  lon: 105.84999
                - lat: 21.02436
                  lon: 105.84982
                - lat: 21.02445
                  lon: 105.84968
                - lat: 21.02456
                  lon: 105.84954
                - lat: 21.02465
                  lon: 105.84942
                - lat: 21.02477
                  lon: 105.84926
                - lat: 21.02484
                  lon: 105.84914
                - lat: 21.02495
                  lon: 105.84900
                - lat: 21.02505
                  lon: 105.84884
                - lat: 21.02515
                  lon: 105.84870
              costing: auto
              shape_match: walk_or_snap
      responses:
        "200":
          description: Map-matched route
          x-i18n:
            vi:
              description: Đường đi đã khớp bản đồ
          content:
            application/json:
              schema:
                type: object
              example:
                trip:
                  locations:
                    - type: break
                      lat: 21.0285
                      lon: 105.8542
                  legs:
                    - maneuvers:
                        - type: 10
                          instruction: "Turn right onto Phố Đinh Tiên Hoàng."
                          street_names: ["Phố Đinh Tiên Hoàng"]
                          time: 8.432
                          length: 0.035
                          travel_mode: drive
                          travel_type: car

  /api/tsp/route/trace_attributes:
    post:
      tags: [Navigation]
      operationId: valhallaTraceAttributes
      summary: "[API] Advanced — Map-matched attributes"
      description: |
        Map-matches a GPS trace and returns detailed edge attributes (speed,
        road class, surface, elevation, etc.) along the matched path.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Map-matched attributes"
          description: |
            Khớp vết GPS vào mạng lưới đường và trả về thuộc tính chi tiết của
            từng cạnh (tốc độ, loại đường, bề mặt, độ cao, v.v.)
            dọc theo đường đã khớp.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              shape:
                - lat: 21.02424
                  lon: 105.84999
                - lat: 21.02436
                  lon: 105.84982
                - lat: 21.02445
                  lon: 105.84968
                - lat: 21.02456
                  lon: 105.84954
                - lat: 21.02465
                  lon: 105.84942
                - lat: 21.02477
                  lon: 105.84926
                - lat: 21.02484
                  lon: 105.84914
                - lat: 21.02495
                  lon: 105.84900
                - lat: 21.02505
                  lon: 105.84884
                - lat: 21.02515
                  lon: 105.84870
              costing: auto
              shape_match: walk_or_snap
              filters:
                attributes:
                  - edge.length
                  - edge.speed
                  - edge.road_class
                action: include
      responses:
        "200":
          description: Edge attributes
          x-i18n:
            vi:
              description: Thuộc tính cạnh
          content:
            application/json:
              schema:
                type: object
              example:
                units: kilometers
                edges:
                  - road_class: service_other
                    speed: 20
                    length: 0.018
                alternate_paths: []

  /api/tsp/route/height:
    post:
      tags: [Navigation]
      operationId: valhallaHeight
      summary: "[API] Advanced — Elevation"
      description: |
        Returns elevation data for specified points or along a path.
        Accepts shape coordinates and returns height values in meters.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Elevation"
          description: |
            Trả về dữ liệu độ cao cho các điểm được chỉ định hoặc dọc theo một đường đi.
            Nhận tọa độ shape và trả về giá trị độ cao tính bằng mét.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              shape:
                - lat: 21.0285
                  lon: 105.8542
                - lat: 21.0367
                  lon: 105.8352
              shape_format: polyline5
      responses:
        "200":
          description: Elevation data
          x-i18n:
            vi:
              description: Dữ liệu độ cao
          content:
            application/json:
              schema:
                type: object
              example:
                shape:
                  - lat: 21.0285
                    lon: 105.8542
                  - lat: 21.0367
                    lon: 105.8352
                range_height:
                  - [0, 12.5]
                  - [2175, 18.3]

  /api/tsp/route/locate:
    post:
      tags: [Navigation]
      operationId: valhallaLocate
      summary: "[API] Advanced — Graph metadata"
      description: |
        Returns metadata about nearby edges and nodes in the routing graph
        for the specified coordinates. Useful for debugging and understanding
        network topology.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Graph metadata"
          description: |
            Trả về thông tin về cạnh và nút lân cận trong đồ thị định tuyến
            cho tọa độ được chỉ định. Hữu ích cho gỡ lỗi và hiểu cấu trúc
            mạng lưới.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
            example:
              locations:
                - lat: 21.0285
                  lon: 105.8542
              costing: auto
      responses:
        "200":
          description: Locate result
          x-i18n:
            vi:
              description: Kết quả locate
          content:
            application/json:
              schema:
                type: object
              example:
                - input_lat: 21.0285
                  input_lon: 105.8542
                  edges:
                    - way_id: 3853825
                      correlated_lat: 21.028426
                      correlated_lon: 105.854092
                      side_of_street: left
                      percent_along: 0.24767

  /api/tsp/route/status:
    get:
      tags: [Navigation]
      operationId: valhallaStatus
      summary: "[API] Advanced — Service status"
      description: |
        Returns service health and tileset metadata including Valhalla version,
        tileset last modified timestamp, and available actions.
      x-i18n:
        vi:
          summary: "[API] Nâng cao — Service status"
          description: |
            Trả về trạng thái dịch vụ và thông tin tileset bao gồm phiên bản
            Valhalla, thời điểm cập nhật tileset và danh sách hành động khả dụng.
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Status information
          x-i18n:
            vi:
              description: Thông tin trạng thái
          content:
            application/json:
              schema:
                type: object
              example:
                version: "3.6.3-8ddfc7622"
                tileset_last_modified: 1782278655
                available_actions: ["route", "optimized_route", "sources_to_targets", "isochrone", "trace_route", "trace_attributes", "height", "locate", "status", "tile", "centroid", "expansion", "transit_available"]

  # =========================================================================
  # Address & POI
  # =========================================================================
  /api/idunn/v1/autocomplete:
    get:
      tags: [Address & POI]
      operationId: autocomplete
      summary: "[API] Search places and addresses"
      description: |
        Returns a list of matching places (addresses or POIs) for the specified query string.
        Results are returned as a GeoJSON FeatureCollection with Point geometries.
      x-i18n:
        vi:
          summary: "[API] Tìm kiếm địa điểm và địa chỉ"
          description: |
            Trả về danh sách địa điểm (địa chỉ hoặc POI) khớp với chuỗi tìm kiếm.
            Kết quả được trả về dưới dạng GeoJSON FeatureCollection với hình học Point.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
          description: Search query string (e.g. "Hà Nội", "Trường đại học Y")
          example: "Hà Nội"
          x-i18n:
            vi:
              description: "Chuỗi tìm kiếm (vd: 'Hà Nội', 'Trường đại học Y')"
      responses:
        "200":
          description: List of matching places
          x-i18n:
            vi:
              description: Danh sách địa điểm khớp
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FeatureCollection"
              example:
                type: FeatureCollection
                geocoding:
                  version: "0.1.0"
                  query: "Hà Nội"
                features:
                  - type: Feature
                    geometry:
                      type: Point
                      coordinates: [105.83416, 21.02776]
                    properties:
                      geocoding:
                        type: city
                        label: "Hà Nội, Việt Nam"
                        name: "Hà Nội"
                        postcode: "10000"
                        id: "admin:osm:relation:2000001"
                        administrative_regions:
                          - name: "Hà Nội"
                            level: 4
                            zone_type: "state"

  /api/idunn/v1/search:
    get:
      tags: [Address & POI]
      operationId: searchPlaces
      summary: "[API] Search addresses and POIs"
      description: |
        Full-text search across the address and POI indexes (addr34/addr63/poi34/poi63),
        merging GADM34 and GADM63 variants into one GeoJSON FeatureCollection. Supports the
        same `q` parameter and filters as autocomplete, with an optional `lang` and `size`.
      x-i18n:
        vi:
          summary: "[API] Tìm kiếm địa chỉ và POI"
          description: |
            Tìm kiếm toàn văn trên các chỉ mục địa chỉ và POI (addr34/addr63/poi34/poi63),
            hợp nhất biến thể GADM34 và GADM63 thành một GeoJSON FeatureCollection. Hỗ trợ
            tham số `q` và bộ lọc tương tự autocomplete, kèm `lang` và `size` tùy chọn.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
          description: |
            Search query string. Unlike `/autocomplete`, search matches a specific place/address;
            a broad term (e.g. `Hà Nội`) returns an empty feature list. Use a concrete name.
          example: "Bệnh viện Bạch Mai"
          x-i18n:
            vi:
              description: |
                Chuỗi tìm kiếm. Khác với `/autocomplete`, `search` khớp một địa điểm/địa chỉ cụ thể;
                từ chung chung (vd `Hà Nội`) trả về danh sách rỗng. Hãy dùng tên cụ thể.
        - name: lang
          in: query
          schema:
            type: string
            enum: [vi, en]
          example: vi
          description: Language code for localized results
          x-i18n:
            vi:
              description: Mã ngôn ngữ cho kết quả bản địa hóa
        - name: size
          in: query
          schema:
            type: integer
          example: 20
          description: Maximum number of results
          x-i18n:
            vi:
              description: Số kết quả tối đa
      responses:
        "200":
          description: Search results as a GeoJSON FeatureCollection
          x-i18n:
            vi:
              description: Kết quả tìm kiếm dạng GeoJSON FeatureCollection
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FeatureCollection"
        "204":
          description: No results
          x-i18n:
            vi:
              description: Không có kết quả

  /api/idunn/v1/reverse/{lat}:{lon}:
    get:
      tags: [Address & POI]
      operationId: reverseGeocode
      summary: "[API] Reverse geocoding"
      description: |
        Reverse geocoding — returns the nearest address and POI for a coordinate, one per GADM
        dataset (addr34, addr63, poi34, poi63), sorted by distance. Each item carries a `subtype`
        and `meta.dataset`, plus `distance` (km) and VN2000 coordinates (`coord_vn2000`).
      x-i18n:
        vi:
          summary: "[API] Geocoding ngược"
          description: |
            Geocoding ngược — trả về địa chỉ và POI gần nhất cho một tọa độ, mỗi phần tử theo từng
            dataset GADM (addr34, addr63, poi34, poi63), sắp xếp theo khoảng cách. Mỗi phần tử mang
            `subtype` và `meta.dataset`, kèm `distance` (km) và tọa độ VN2000 (`coord_vn2000`).
      security:
        - ApiKeyAuth: []
      parameters:
        - name: lat
          in: path
          required: true
          schema:
            type: number
          description: Latitude (WGS84, -90 to 90)
          example: 21.05692
          x-i18n:
            vi:
              description: Vĩ độ (WGS84, -90 đến 90)
        - name: lon
          in: path
          required: true
          schema:
            type: number
          description: Longitude (WGS84, -180 to 180)
          example: 105.74591
          x-i18n:
            vi:
              description: Kinh độ (WGS84, -180 đến 180)
        - name: lang
          in: query
          schema:
            type: string
            enum: [vi, en]
          example: vi
          description: Language code for localized results
          x-i18n:
            vi:
              description: Mã ngôn ngữ cho kết quả bản địa hóa
        - name: subtype
          in: query
          schema:
            type: string
            enum: [addr34, addr63, poi34, poi63]
          description: Restrict results to a specific GADM dataset
          x-i18n:
            vi:
              description: Giới hạn kết quả theo một dataset GADM cụ thể
      responses:
        "200":
          description: List of nearest places, one per GADM dataset
          x-i18n:
            vi:
              description: Danh sách địa điểm gần nhất, mỗi dataset GADM một phần tử
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object

  /api/idunn/v1/places:
    get:
      tags: [Address & POI]
      operationId: placesBbox
      summary: "[API] List places in a bounding box"
      description: |
        Returns all places (POIs and/or addresses) inside a bounding box, filtered by
        `category`, `raw_filter`, or free-text `q`. At least one of those three filters is required.
        Max bbox width/height is 1.0 degree.
      x-i18n:
        vi:
          summary: "[API] Danh sách địa điểm trong bounding box"
          description: |
            Trả về toàn bộ địa điểm (POI và/hoặc địa chỉ) trong một bounding box, lọc theo
            `category`, `raw_filter`, hoặc `q`. Bắt buộc cung cấp ít nhất một trong ba bộ lọc.
            Kích thước bbox tối đa 1.0 độ.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: bbox
          in: query
          required: true
          schema:
            type: string
          description: "Bounding box as `minLon,minLat,maxLon,maxLat`"
          example: "105.83,21.02,105.85,21.04"
          x-i18n:
            vi:
              description: "Bounding box dạng `minLon,minLat,maxLon,maxLat`"
        - name: category
          in: query
          schema:
            type: array
            items:
              type: string
          description: POI category filter (see /categories). One of `category`/`raw_filter`/`q` is required.
          example: [pharmacy]
          x-i18n:
            vi:
              description: Bộ lọc phân loại POI (xem /categories). Bắt buộc có một trong `category`/`raw_filter`/`q`.
        - name: q
          in: query
          schema:
            type: string
          description: Free-text query filter
          x-i18n:
            vi:
              description: Bộ lọc tìm kiếm tự do
        - name: lang
          in: query
          schema:
            type: string
            enum: [vi, en]
          example: vi
          description: Language code for localized results
          x-i18n:
            vi:
              description: Mã ngôn ngữ cho kết quả bản địa hóa
        - name: size
          in: query
          schema:
            type: integer
          description: Maximum number of results
          x-i18n:
            vi:
              description: Số kết quả tối đa
      responses:
        "200":
          description: List of places in the bounding box
          x-i18n:
            vi:
              description: Danh sách địa điểm trong bounding box
          content:
            application/json:
              schema:
                type: object

  /api/idunn/v1/places/vnland:
    get:
      tags: [Address & POI]
      operationId: placesVnlandCircle
      summary: "[API] List places in a circle (vnland)"
      description: |
        Returns all places inside a circle centered on `latitude`/`longitude` with a radius in
        kilometers (0–2 km, default 2). Results are sorted by distance from the center.

        At least one of `category`, `raw_filter`, or `q` is required (same rule as `/places`).
        Response is `{"places": {<category>: [ ... ]}, "source", "bbox", "bbox_extended"}` —
        places are grouped by category.
      x-i18n:
        vi:
          summary: "[API] Danh sách địa điểm trong hình tròn (vnland)"
          description: |
            Trả về toàn bộ địa điểm trong hình tròn tâm `latitude`/`longitude` với bán kính tính
            bằng km (0–2 km, mặc định 2). Kết quả được sắp xếp theo khoảng cách từ tâm.

            Bắt buộc cung cấp ít nhất một trong `category`, `raw_filter`, hoặc `q` (giống `/places`).
            Phản hồi là `{"places": {<category>: [ ... ]}, "source", "bbox", "bbox_extended"}` —
            địa điểm được nhóm theo phân loại.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: latitude
          in: query
          required: true
          schema:
            type: number
          description: Circle center latitude
          example: 21.05692
          x-i18n:
            vi:
              description: Vĩ độ tâm hình tròn
        - name: longitude
          in: query
          required: true
          schema:
            type: number
          description: Circle center longitude
          example: 105.74591
          x-i18n:
            vi:
              description: Kinh độ tâm hình tròn
        - name: radius
          in: query
          schema:
            type: number
            maximum: 2
          description: Radius in kilometers (max 2)
          example: 1
          x-i18n:
            vi:
              description: Bán kính tính bằng km (tối đa 2)
        - name: category
          in: query
          schema:
            type: array
            items:
              type: string
          description: POI category filter. One of `category`/`raw_filter`/`q` is required.
          example: [pharmacy]
          x-i18n:
            vi:
              description: Bộ lọc phân loại POI. Bắt buộc có một trong `category`/`raw_filter`/`q`.
        - name: q
          in: query
          schema:
            type: string
          description: Free-text query filter. One of `category`/`raw_filter`/`q` is required.
          x-i18n:
            vi:
              description: Bộ lọc tìm kiếm tự do. Bắt buộc có một trong `category`/`raw_filter`/`q`.
        - name: size
          in: query
          schema:
            type: integer
          description: Maximum number of results
          x-i18n:
            vi:
              description: Số kết quả tối đa
      responses:
        "200":
          description: List of places in the circle
          x-i18n:
            vi:
              description: Danh sách địa điểm trong hình tròn
          content:
            application/json:
              schema:
                type: object

  /api/idunn/v1/categories:
    get:
      tags: [Address & POI]
      operationId: listCategories
      summary: "[API] List POI categories"
      description: |
        Returns the list of supported POI category keys usable with the `category` filter
        on `/places` and `/places/vnland`.
      x-i18n:
        vi:
          summary: "[API] Danh sách phân loại POI"
          description: |
            Trả về danh sách khóa phân loại POI được hỗ trợ, dùng cho bộ lọc `category`
            của `/places` và `/places/vnland`.
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: List of category keys
          x-i18n:
            vi:
              description: Danh sách khóa phân loại
          content:
            application/json:
              schema:
                type: object
                properties:
                  categories:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string

  /api/idunn/v1/instant_answer:
    get:
      tags: [Address & POI]
      operationId: instantAnswer
      summary: "[API] Instant answer"
      description: |
        Resolves a query naming a specific place (e.g. "Nhà hát Lớn Hà Nội") into an instant-answer
        card with the most relevant place. Intent-style queries such as "pizza gần Hồ Gươm"
        (category near a place) are not supported yet and return `204`.
      x-i18n:
        vi:
          summary: "[API] Trả lời tức thời"
          description: |
            Phân giải câu truy vấn tên một địa điểm cụ thể (vd: "Nhà hát Lớn Hà Nội") thành thẻ trả lời
            tức thời kèm địa điểm liên quan nhất. Truy vấn dạng ý định như "pizza gần Hồ Gươm"
            (loại địa điểm gần một nơi) chưa được hỗ trợ và trả về `204`.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
          description: Name of a specific place
          example: "Nhà hát Lớn Hà Nội"
          x-i18n:
            vi:
              description: "Tên một địa điểm cụ thể"
        - name: lang
          in: query
          schema:
            type: string
            enum: [vi, en]
          example: vi
          description: Language code for the result
          x-i18n:
            vi:
              description: Mã ngôn ngữ của kết quả
      responses:
        "200":
          description: Instant-answer card
          x-i18n:
            vi:
              description: Thẻ trả lời tức thời
          content:
            application/json:
              schema:
                type: object
        "204":
          description: No instant answer available
          x-i18n:
            vi:
              description: Không có câu trả lời tức thời

  /api/idunn/v1/directions/{f_lon},{f_lat};{t_lon},{t_lat}:
    get:
      tags: [Address & POI]
      operationId: directionsCoordinates
      summary: "[API] Directions between coordinates"
      description: |
        Computes a route between two coordinates for a transport mode (`type`: car, bike, foot).
        Note: the directions backend may return `501 Not Implemented` when a mode is not deployed.
      x-i18n:
        vi:
          summary: "[API] Chỉ đường giữa hai tọa độ"
          description: |
            Tính toán tuyến đường giữa hai tọa độ theo phương thức di chuyển (`type`: car, bike, foot).
            Lưu ý: backend chỉ đường có thể trả `501 Not Implemented` khi phương thức chưa được triển khai.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: f_lon
          in: path
          required: true
          schema:
            type: number
          description: Origin longitude
          example: 105.83416
          x-i18n:
            vi:
              description: Kinh độ điểm đi
        - name: f_lat
          in: path
          required: true
          schema:
            type: number
          description: Origin latitude
          example: 21.02776
          x-i18n:
            vi:
              description: Vĩ độ điểm đi
        - name: t_lon
          in: path
          required: true
          schema:
            type: number
          description: Destination longitude
          example: 105.84
          x-i18n:
            vi:
              description: Kinh độ điểm đến
        - name: t_lat
          in: path
          required: true
          schema:
            type: number
          description: Destination latitude
          example: 21.03
          x-i18n:
            vi:
              description: Vĩ độ điểm đến
        - name: type
          in: query
          required: true
          schema:
            type: string
            enum: [car, bike, foot]
          description: Transport mode
          example: car
          x-i18n:
            vi:
              description: Phương thức di chuyển
      responses:
        "200":
          description: Route directions
          x-i18n:
            vi:
              description: Chỉ đường
          content:
            application/json:
              schema:
                type: object
        "422":
          description: Path not allowed for the mode
          x-i18n:
            vi:
              description: Tuyến đường không cho phép đối với phương thức này
        "501":
          description: Directions backend not deployed for the mode
          x-i18n:
            vi:
              description: Backend chỉ đường chưa được triển khai cho phương thức này

  /api/idunn/v1/directions:
    get:
      tags: [Address & POI]
      operationId: directionsByIds
      summary: "[API] Directions between place IDs"
      description: |
        Computes a route between two place identifiers for a transport mode (`type`: car, bike, foot).
        `origin` and `destination` are place IDs (e.g. `latlon:...`, `addr:...`, `vdt:node:...`).
      x-i18n:
        vi:
          summary: "[API] Chỉ đường giữa hai mã địa điểm"
          description: |
            Tính toán tuyến đường giữa hai mã địa điểm theo phương thức di chuyển (`type`: car, bike, foot).
            `origin` và `destination` là mã địa điểm (vd: `latlon:...`, `addr:...`, `vdt:node:...`).
      security:
        - ApiKeyAuth: []
      parameters:
        - name: origin
          in: query
          required: true
          schema:
            type: string
          description: Origin place ID
          example: "latlon:21.02776:105.83416"
          x-i18n:
            vi:
              description: Mã địa điểm đi
        - name: destination
          in: query
          required: true
          schema:
            type: string
          description: Destination place ID
          example: "latlon:21.03:105.84"
          x-i18n:
            vi:
              description: Mã địa điểm đến
        - name: type
          in: query
          required: true
          schema:
            type: string
            enum: [car, bike, foot]
          description: Transport mode
          example: car
          x-i18n:
            vi:
              description: Phương thức di chuyển
      responses:
        "200":
          description: Route directions
          x-i18n:
            vi:
              description: Chỉ đường
          content:
            application/json:
              schema:
                type: object

  /api/idunn/v1/projections:
    get:
      tags: [Address & POI]
      operationId: listProjections
      summary: "[API] List VN2000 projections"
      description: |
        Lists the supported VN2000 projections with their EPSG codes, central meridians,
        and the provinces (new 34 and old 63 era) that fall in each zone.
      x-i18n:
        vi:
          summary: "[API] Danh sách hệ chiếu VN2000"
          description: |
            Liệt kê các hệ chiếu VN2000 được hỗ trợ kèm mã EPSG, kinh tuyến trục và danh sách
            tỉnh (thời kỳ mới 34 và cũ 63) thuộc từng múi.
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: List of projections
          x-i18n:
            vi:
              description: Danh sách hệ chiếu
          content:
            application/json:
              schema:
                type: object
                properties:
                  projections:
                    type: array
                    items:
                      type: object

  /api/idunn/v1/projections/resolve:
    get:
      tags: [Address & POI]
      operationId: resolveProjection
      summary: "[API] Resolve VN2000 projection by province"
      description: |
        Resolves the VN2000 TM3 projection zone for a province name. Because the same province
        may fall in different zones between the 34-province (new, 2025+) and 63-province (old,
        2008–2025) eras, pass `era=new` or `era=old` to constrain the search.
      x-i18n:
        vi:
          summary: "[API] Xác định hệ chiếu VN2000 theo tỉnh"
          description: |
            Xác định múi chiếu VN2000 TM3 cho một tên tỉnh. Vì cùng tên tỉnh có thể nằm ở múi khác
            giữa thời kỳ 34 tỉnh (mới, 2025+) và 63 tỉnh (cũ, 2008–2025), truyền `era=new` hoặc
            `era=old` để giới hạn tìm kiếm.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: province
          in: query
          required: true
          schema:
            type: string
          description: Province/city name
          example: "Hà Nội"
          x-i18n:
            vi:
              description: "Tên tỉnh/thành phố"
        - name: era
          in: query
          schema:
            type: string
            enum: [new, old]
          description: "Administrative era: new (34 provinces) or old (63 provinces)"
          x-i18n:
            vi:
              description: "Thời kỳ hành chính: new (34 tỉnh) hoặc old (63 tỉnh)"
      responses:
        "200":
          description: Resolved projection match
          x-i18n:
            vi:
              description: Kết quả xác định hệ chiếu
          content:
            application/json:
              schema:
                type: object

  /api/idunn/v1/gadm/zipcode/{zip_code}:
    get:
      tags: [Address & POI]
      operationId: gadmZipcode
      summary: "[API] GADM administrative unit by zipcode"
      description: |
        Looks up the GADM34/GADM63 administrative units associated with a VNPOST zipcode.
        Response is slow (database-backed); allow generous timeouts.
      x-i18n:
        vi:
          summary: "[API] Đơn vị hành chính GADM theo zipcode"
          description: |
            Tra cứu đơn vị hành chính GADM34/GADM63 theo mã bưu chính VNPOST.
            Phản hồi chậm (truy vấn cơ sở dữ liệu); nên đặt timeout rộng rãi.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: zip_code
          in: path
          required: true
          schema:
            type: string
          description: |
            5-digit VNPOST zip code of an administrative unit (the value found in a place's
            `postcodes` / `zip_codes`, e.g. from `/reverse`), not the 12-character `vpostcode`.
          example: "00070"
          x-i18n:
            vi:
              description: |
                Mã bưu chính VNPOST 5 số của đơn vị hành chính (lấy từ `postcodes` / `zip_codes`
                của một địa điểm, vd từ `/reverse`), không phải `vpostcode` 12 ký tự.
      responses:
        "200":
          description: GADM administrative unit(s) for the zipcode
          x-i18n:
            vi:
              description: Đơn vị hành chính GADM theo zipcode
          content:
            application/json:
              schema:
                type: object

  /api/idunn/v1/insert-poi:
    post:
      tags: [Address & POI]
      operationId: insertPoi
      summary: "[API] Insert a POI (internal)"
      description: |
        Inserts a new POI into the `poi_point` table (name, tags, subclass, mapping key,
        and `[longitude, latitude]` geometry). Internal/admin use.
      x-i18n:
        vi:
          summary: "[API] Thêm POI (nội bộ)"
          description: |
            Thêm POI mới vào bảng `poi_point` (tên, tags, subclass, mapping key và hình học
            `[kinh độ, vĩ độ]`). Dùng nội bộ/quản trị.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, tags, geometry]
              properties:
                name:
                  type: string
                name_en:
                  type: string
                tags:
                  type: object
                subclass:
                  type: string
                  default: amenity
                mapping_key:
                  type: string
                  default: amenity
                geometry:
                  type: array
                  minItems: 2
                  maxItems: 2
                  items:
                    type: number
                  description: "[longitude, latitude]"
      responses:
        "200":
          description: Inserted POI
          x-i18n:
            vi:
              description: POI đã được thêm
          content:
            application/json:
              schema:
                type: object

  /api/idunn/v1/places/latlon:{lat}:{lon}:
    get:
      tags: [Address & POI]
      operationId: reverseGeocode
      summary: "[API] Coordinate detail lookup"
      description: |
        Retrieves the nearest address or POI for the specified geographic coordinates (latitude, longitude).
        Supports an optional language parameter for localized results.
      x-i18n:
        vi:
          summary: "[API] Tra cứu chi tiết tọa độ"
          description: |
            Trả về địa chỉ hoặc POI gần nhất ứng với tọa độ địa lý (vĩ độ, kinh độ) được chỉ định.
            Hỗ trợ tham số ngôn ngữ tùy chọn cho kết quả bản địa hóa.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: lat
          in: path
          required: true
          schema:
            type: number
          description: Latitude (WGS84, -90 to 90)
          x-i18n:
            vi:
              description: Vĩ độ (WGS84, -90 đến 90)
          example: 21.05692
        - name: lon
          in: path
          required: true
          schema:
            type: number
          description: Longitude (WGS84, -180 to 180)
          x-i18n:
            vi:
              description: Kinh độ (WGS84, -180 đến 180)
          example: 105.74591
        - name: lang
          in: query
          schema:
            type: string
            enum: [vi, en]
          example: vi
          description: Language code for localized results
          x-i18n:
            vi:
              description: Mã ngôn ngữ cho kết quả bản địa hóa
      responses:
        "200":
          description: Address information for the coordinate
          x-i18n:
            vi:
              description: Thông tin địa chỉ cho tọa độ
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/LatLonPlace"
              example:
                - type: latlon
                  id: "latlon:21.02800:105.85400"
                  name: "21.02800 : 105.85400"
                  class_name: latlon
                  subclass_name: latlon
                  subtype: addr34
                  geometry:
                    type: Point
                    coordinates: [105.854, 21.028]
                  address:
                    id: "addr:105.854023;21.028015:12"
                    name: "12 Phố Lê Lai"
                    label: "12 Phố Lê Lai, Phường Hoàn Kiếm, Thành phố Hà Nội, Việt Nam"
                    housenumber: "12"
                    street:
                      name: "Phố Lê Lai"
                      postcodes: ["11024"]
                    postcode: "11024"
                    vpostcode: "11024XVX3XJR"
                    admins:
                      - name: "Phường Hoàn Kiếm"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  meta:
                    maps_place_url: "https://gmap.vn/place/latlon:21.02800:105.85400"
                    maps_directions_url: "https://gmap.vn/routes/?destination=latlon%3A21.02800%3A105.85400"
                - type: latlon
                  id: "latlon:21.02800:105.85400"
                  name: "21.02800 : 105.85400"
                  class_name: latlon
                  subclass_name: latlon
                  subtype: addr63
                  geometry:
                    type: Point
                    coordinates: [105.854, 21.028]
                  address:
                    id: "addr:105.854023;21.028015:12"
                    name: "12 Phố Lê Lai"
                    label: "12 Phố Lê Lai, Phường Lý Thái Tổ, Quận Hoàn Kiếm, Thành phố Hà Nội, Việt Nam"
                    housenumber: "12"
                    street:
                      name: "Phố Lê Lai"
                      postcodes: ["11024"]
                    postcode: "11024"
                    vpostcode: "11024XVX3XJR"
                    admins:
                      - name: "Phường Lý Thái Tổ"
                        class_name: state_district
                      - name: "Quận Hoàn Kiếm"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  meta:
                    maps_place_url: "https://gmap.vn/place/latlon:21.02800:105.85400"
                    maps_directions_url: "https://gmap.vn/routes/?destination=latlon%3A21.02800%3A105.85400"

  /api/idunn/v1/transform:
    get:
      tags: [Address & POI]
      operationId: crsTransform
      summary: "[API] Coordinate system transform"
      description: |
        Transforms coordinates between WGS84 (EPSG:4326) and VN2000 transverse Mercator
        (TM3) projection zones, in either direction.

        Provide `lon`/`lat` when the source is WGS84, or `x`/`y` (meters, VN2000) when the
        source is a VN2000 zone.

        | CRS Code | Zone Coverage |
        |----------|--------------|
        | `vn2000-tm3-481` | 102.9°E, longitude ≤ 104°E |
        | `vn2000-tm3-482` | 104°E < longitude ≤ 106°E (Hà Nội) |
        | `vn2000-tm3-483` | 106°E < longitude ≤ 108°E |
        | `vn2000-tm3-484` | 108°E < longitude ≤ 110°E (Đà Nẵng) |
        | `vn2000-tm3-485` | 110°E < longitude ≤ 112°E |
        | `vn2000-tm3-486` | 112°E < longitude ≤ 114°E |
        | `vn2000-tm3-487` | 114°E < longitude ≤ 115.5°E |
        | `vn2000-tm3-488` | 115.5°E < longitude |

        **Response:** Returns the converted `x`/`y` (meters, VN2000) and `lon`/`lat` (WGS84),
        along with the source and target CRS codes.
      x-i18n:
        vi:
          summary: "[API] Chuyển đổi hệ tọa độ"
          description: |
            Chuyển đổi tọa độ giữa WGS84 (EPSG:4326) và các múi chiếu VN2000 transverse
            Mercator (TM3), theo cả hai chiều.

            Cung cấp `lon`/`lat` khi nguồn là WGS84, hoặc `x`/`y` (mét, VN2000) khi nguồn
            là một múi VN2000.

            | Mã CRS | Khu vực |
            |--------|---------|
            | `vn2000-tm3-481` | 102.9°E, kinh độ ≤ 104°E |
            | `vn2000-tm3-482` | 104°E < kinh độ ≤ 106°E (Hà Nội) |
            | `vn2000-tm3-483` | 106°E < kinh độ ≤ 108°E |
            | `vn2000-tm3-484` | 108°E < kinh độ ≤ 110°E (Đà Nẵng) |
            | `vn2000-tm3-485` | 110°E < kinh độ ≤ 112°E |
            | `vn2000-tm3-486` | 112°E < kinh độ ≤ 114°E |
            | `vn2000-tm3-487` | 114°E < kinh độ ≤ 115.5°E |
            | `vn2000-tm3-488` | 115.5°E < kinh độ |

            **Phản hồi:** Trả về `x`/`y` (mét, VN2000) và `lon`/`lat` (WGS84) đã chuyển đổi,
            kèm mã CRS nguồn và đích.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: from_crs
          in: query
          required: true
          schema:
            type: string
            enum: [wgs84, vn2000, vn2000-utm48n, vn2000-tm3-481, vn2000-tm3-482, vn2000-tm3-483, vn2000-tm3-484, vn2000-tm3-485, vn2000-tm3-486, vn2000-tm3-487, vn2000-tm3-488]
          example: wgs84
          description: Source coordinate reference system
          x-i18n:
            vi:
              description: Hệ tọa độ nguồn
        - name: to_crs
          in: query
          required: true
          schema:
            type: string
            enum: [wgs84, vn2000, vn2000-utm48n, vn2000-tm3-481, vn2000-tm3-482, vn2000-tm3-483, vn2000-tm3-484, vn2000-tm3-485, vn2000-tm3-486, vn2000-tm3-487, vn2000-tm3-488]
          example: vn2000-tm3-482
          description: Target coordinate reference system
          x-i18n:
            vi:
              description: Hệ tọa độ đích
        - name: lon
          in: query
          schema:
            type: number
          example: 105.770663
          description: Longitude (WGS84, -180 to 180). Required when `from_crs` is wgs84.
          x-i18n:
            vi:
              description: Kinh độ (WGS84, -180 đến 180). Bắt buộc khi `from_crs` là wgs84.
        - name: lat
          in: query
          schema:
            type: number
          example: 20.998692
          description: Latitude (WGS84, -90 to 90). Required when `from_crs` is wgs84.
          x-i18n:
            vi:
              description: Vĩ độ (WGS84, -90 đến 90). Bắt buộc khi `from_crs` là wgs84.
        - name: x
          in: query
          schema:
            type: number
          description: Easting in meters (VN2000). Required when `from_crs` is a VN2000 zone.
          x-i18n:
            vi:
              description: Tọa độ X theo mét (VN2000). Bắt buộc khi `from_crs` là múi VN2000.
        - name: y
          in: query
          schema:
            type: number
          description: Northing in meters (VN2000). Required when `from_crs` is a VN2000 zone.
          x-i18n:
            vi:
              description: Tọa độ Y theo mét (VN2000). Bắt buộc khi `from_crs` là múi VN2000.
      responses:
        "200":
          description: Transformed coordinates
          x-i18n:
            vi:
              description: Tọa độ đã chuyển đổi
          content:
            application/json:
              schema:
                type: object
                properties:
                  from_crs:
                    type: string
                  to_crs:
                    type: string
                  x:
                    type: number
                    description: Easting in meters (VN2000)
                  y:
                    type: number
                    description: Northing in meters (VN2000)
                  lon:
                    type: number
                  lat:
                    type: number
              example:
                from_crs: wgs84
                to_crs: vn2000-tm3-482
                x: 579924.435
                "y": 2323001.038
                lon: 105.770663
                lat: 20.998692

  /api/idunn/v1/places/vpostcode:{vpostcode}:
    get:
      tags: [Address & POI]
      operationId: vpostcodeLookup
      summary: "[API] Vpostcode detail lookup"
      description: |
        Resolves a VNPOST postal code to the corresponding address, including
        house number, street name, district, city, and full administrative hierarchy.
        Returns a structured address with geometry and map URLs.
      x-i18n:
        vi:
          summary: "[API] Tra cứu chi tiết Vpostcode"
          description: |
            Phân giải mã bưu chính VNPOST thành địa chỉ tương ứng, bao gồm
            số nhà, tên đường, quận/huyện, tỉnh/thành và phân cấp hành chính đầy đủ.
            Trả về địa chỉ có cấu trúc kèm hình học và URL bản đồ.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: vpostcode
          in: path
          required: true
          schema:
            type: string
          description: VNPOST postal code, e.g. `11914XPXWX8V`
          example: "11914XPXWX8V"
          x-i18n:
            vi:
              description: "Mã bưu chính VNPOST, vd: `11914XPXWX8V`"
      responses:
        "200":
          description: Address resolved from vpostcode
          x-i18n:
            vi:
              description: Địa chỉ được phân giải từ vpostcode
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/LatLonPlace"
              example:
                - type: latlon
                  id: "latlon:20.99999:105.74580"
                  name: "20.99999 : 105.74580"
                  class_name: latlon
                  subclass_name: latlon
                  subtype: addr34
                  geometry:
                    type: Point
                    coordinates: [105.7458, 20.99999]
                  address:
                    id: "addr:105.745730;21.000009:10"
                    name: "10 Ngõ 193 Phố Cầu Cốc"
                    label: "10 Ngõ 193 Phố Cầu Cốc, Phường Tây Mỗ, Thành phố Hà Nội, Việt Nam"
                    housenumber: "10"
                    street:
                      name: "Ngõ 193 Phố Cầu Cốc"
                      postcodes: ["12009"]
                    postcode: "12009"
                    vpostcode: "12009XPXWX8V"
                    admins:
                      - name: "Phường Tây Mỗ"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  meta:
                    maps_place_url: "https://gmap.vn/place/latlon:20.99999:105.74580"
                    maps_directions_url: "https://gmap.vn/routes/?destination=latlon%3A20.99999%3A105.74580"
                - type: latlon
                  id: "latlon:20.99999:105.74580"
                  name: "20.99999 : 105.74580"
                  class_name: latlon
                  subclass_name: latlon
                  subtype: addr63
                  geometry:
                    type: Point
                    coordinates: [105.7458, 20.99999]
                  address:
                    id: "addr:105.745730;21.000009:10"
                    name: "10 Ngõ 193 Phố Cầu Cốc"
                    label: "10 Ngõ 193 Phố Cầu Cốc, Phường Tây Mỗ, Quận Nam Từ Liêm, Thành phố Hà Nội, Việt Nam"
                    housenumber: "10"
                    street:
                      name: "Ngõ 193 Phố Cầu Cốc"
                      postcodes: ["12009"]
                    postcode: "12009"
                    vpostcode: "12009XPXWX8V"
                    admins:
                      - name: "Phường Tây Mỗ"
                        class_name: state_district
                      - name: "Quận Nam Từ Liêm"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  meta:
                    maps_place_url: "https://gmap.vn/place/latlon:20.99999:105.74580"
                    maps_directions_url: "https://gmap.vn/routes/?destination=latlon%3A20.99999%3A105.74580"

  # TODO — POI detail by ID
  /api/idunn/v1/places/{poi_id}:
    get:
      tags: [Address & POI]
      operationId: poiDetail
      summary: "[API] POI detail lookup"
      description: |
        Returns comprehensive POI details including name, category, address,
        geometry, contact information (phone, website, social links), and map URLs.
      x-i18n:
        vi:
          summary: "[API] Tra cứu chi tiết POI"
          description: |
            Trả về thông tin POI đầy đủ gồm tên, phân loại, địa chỉ, hình học,
            thông tin liên hệ (điện thoại, website, mạng xã hội) và URL bản đồ.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: poi_id
          in: path
          required: true
          schema:
            type: string
          description: POI identifier (from autocomplete or reverse geocode results)
          example: "vdt:node:otm:101775561"
          x-i18n:
            vi:
              description: Mã định danh POI (từ kết quả autocomplete hoặc geocoding ngược)
        - name: lang
          in: query
          schema:
            type: string
            enum: [vi, en]
          example: vi
          description: Language code for localized results
          x-i18n:
            vi:
              description: Mã ngôn ngữ cho kết quả bản địa hóa
      responses:
        "200":
          description: POI details
          x-i18n:
            vi:
              description: Thông tin POI
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
              example:
                - type: poi
                  id: "vdt:node:otm:101775561"
                  name: "YOKO Shop - Hàng nhật xách tay"
                  local_name: "YOKO Shop - Hàng nhật xách tay"
                  class_name: restaurant
                  subclass_name: restaurant
                  subtype: poi34
                  geometry:
                    type: Point
                    coordinates: [105.8445731, 20.9916032]
                  address:
                    id: "addr:105.844545;20.991553:122"
                    name: "122 Phố Nguyễn An Ninh"
                    label: "122 Phố Nguyễn An Ninh, Phường Tương Mai, Thành phố Hà Nội, Việt Nam"
                    housenumber: "122"
                    street:
                      name: "Phố Nguyễn An Ninh"
                      postcodes: ["11715"]
                    postcode: "11715"
                    admins:
                      - name: "Phường Tương Mai"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  blocks:
                    - type: phone
                      url: "tel:+84982892425"
                    - type: website
                      url: "https://yokoshop.vn/"
                  meta:
                    source: osm
                    maps_place_url: "https://gmap.vn/place/vdt:node:otm:101775561"
                - type: poi
                  id: "vdt:node:otm:101775561"
                  name: "YOKO Shop - Hàng nhật xách tay"
                  local_name: "YOKO Shop - Hàng nhật xách tay"
                  class_name: restaurant
                  subclass_name: restaurant
                  subtype: poi63
                  geometry:
                    type: Point
                    coordinates: [105.8445731, 20.9916032]
                  address:
                    id: "addr:105.844545;20.991553:122"
                    name: "122 Phố Nguyễn An Ninh"
                    label: "122 Phố Nguyễn An Ninh, Phường Tương Mai, Quận Hoàng Mai, Thành phố Hà Nội, Việt Nam"
                    housenumber: "122"
                    street:
                      name: "Phố Nguyễn An Ninh"
                      postcodes: ["11715"]
                    postcode: "11715"
                    admins:
                      - name: "Phường Tương Mai"
                        class_name: state_district
                      - name: "Quận Hoàng Mai"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  blocks:
                    - type: phone
                      url: "tel:+84982892425"
                    - type: website
                      url: "https://yokoshop.vn/"
                  meta:
                    source: osm
                    maps_place_url: "https://gmap.vn/place/vdt:node:otm:101775561"

  # TODO — Address detail by ID
  /api/idunn/v1/places/{addr_id}:
    get:
      tags: [Address & POI]
      operationId: addressDetail
      summary: "[API] Address detail lookup"
      description: |
        Returns comprehensive address details for a given place identifier,
        including house number, street name, full administrative hierarchy,
        postcode, vpostcode, geometry, and map URLs.
      x-i18n:
        vi:
          summary: "[API] Tra cứu chi tiết địa chỉ"
          description: |
            Trả về thông tin địa chỉ đầy đủ cho mã định danh địa điểm,
            bao gồm số nhà, tên đường, phân cấp hành chính đầy đủ,
            postcode, vpostcode, hình học và URL bản đồ.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: addr_id
          in: path
          required: true
          schema:
            type: string
          description: "Address identifier, e.g. `addr:105.804114;20.997197:105`"
          example: "addr:105.804114;20.997197:105"
          x-i18n:
            vi:
              description: "Mã định danh địa chỉ, vd: `addr:105.804114;20.997197:105`"
        - name: subtype
          in: query
          schema:
            type: string
          example: addr34
          description: Subtype filter (e.g. `addr34`)
          x-i18n:
            vi:
              description: "Bộ lọc subtype (vd: `addr34`)"
        - name: lang
          in: query
          schema:
            type: string
            enum: [vi, en]
          example: vi
          description: Language code for localized results
          x-i18n:
            vi:
              description: Mã ngôn ngữ cho kết quả bản địa hóa
      responses:
        "200":
          description: Address details
          x-i18n:
            vi:
              description: Thông tin địa chỉ
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
              example:
                - type: address
                  id: "addr:105.854023;21.028015:12"
                  name: "12 Phố Lê Lai"
                  local_name: "12 Phố Lê Lai"
                  class_name: address
                  subclass_name: address
                  subtype: addr34
                  geometry:
                    type: Point
                    coordinates: [105.854023, 21.0280149]
                  address:
                    id: "addr:105.854023;21.028015:12"
                    name: "12 Phố Lê Lai"
                    label: "12 Phố Lê Lai, Phường Hoàn Kiếm, Thành phố Hà Nội, Việt Nam"
                    housenumber: "12"
                    street:
                      name: "Phố Lê Lai"
                      postcodes: ["11024"]
                    postcode: "11024"
                    vpostcode: "11024XVX3XJR"
                    admins:
                      - name: "Phường Hoàn Kiếm"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  meta:
                    maps_place_url: "https://gmap.vn/place/addr:105.854023;21.028015:12"
                    maps_directions_url: "https://gmap.vn/routes/?destination=addr%3A105.854023%3B21.028015%3A12"
                - type: address
                  id: "addr:105.854023;21.028015:12"
                  name: "12 Phố Lê Lai"
                  local_name: "12 Phố Lê Lai"
                  class_name: address
                  subclass_name: address
                  subtype: addr63
                  geometry:
                    type: Point
                    coordinates: [105.854023, 21.0280149]
                  address:
                    id: "addr:105.854023;21.028015:12"
                    name: "12 Phố Lê Lai"
                    label: "12 Phố Lê Lai, Phường Lý Thái Tổ, Quận Hoàn Kiếm, Thành phố Hà Nội, Việt Nam"
                    housenumber: "12"
                    street:
                      name: "Phố Lê Lai"
                      postcodes: ["11024"]
                    postcode: "11024"
                    vpostcode: "11024XVX3XJR"
                    admins:
                      - name: "Phường Lý Thái Tổ"
                        class_name: state_district
                      - name: "Quận Hoàn Kiếm"
                        class_name: state_district
                      - name: "Thành phố Hà Nội"
                        class_name: state
                  meta:
                    maps_place_url: "https://gmap.vn/place/addr:105.854023;21.028015:12"
                    maps_directions_url: "https://gmap.vn/routes/?destination=addr%3A105.854023%3B21.028015%3A12"

  # =========================================================================
  # GADM
  # =========================================================================
  /api/tiles/gadm34/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getGadm34Tile
      summary: "[Vector] Administrative boundaries GADM34"
      description: |
        Vector tile (PBF) of Vietnam administrative boundaries at GADM34 (34-province) resolution.
        Native tile coverage is available at zoom levels 0–16 through the Playground GADM layer.
        Tiles are served in Web Mercator (EPSG:3857); for VN2000-projected coordinates use the
        `/api/idunn/v1/transform` endpoint or the GADM detail API.

        > **Data sensitivity notice:** PBF tiles expose detailed boundary geometries.
        > Access control and rate limiting apply.
      x-i18n:
        vi:
          summary: "[Vector] Ranh giới hành chính GADM34"
          description: |
            Ô vector (PBF) ranh giới hành chính Việt Nam ở độ phân giải GADM34 (34 tỉnh),
            với vùng tile gốc ở mức zoom 0–16. Khả dụng qua lớp GADM trên Playground.
            Ô được phục vụ theo Web Mercator (EPSG:3857); để lấy tọa độ VN2000 hãy dùng
            endpoint `/api/idunn/v1/transform` hoặc API chi tiết GADM.

            > **Lưu ý về độ nhạy cảm dữ liệu:** Ô PBF tiết lộ ranh giới chi tiết.
            > Áp dụng kiểm soát truy cập và giới hạn lưu lượng.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
          description: Zoom level (0–16)
          x-i18n:
            vi:
              description: Mức thu phóng (0–16)
        - name: x
          in: path
          required: true
          schema:
            type: integer
          description: Tile X (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ X ô
        - name: y
          in: path
          required: true
          schema:
            type: integer
          description: Tile Y (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ Y ô
        - name: crs
          in: query
          schema:
            type: string
            enum: [epsg4326, vn2000]
          description: "Coordinate reference system (default: epsg4326)"
          x-i18n:
            vi:
              description: "Hệ quy chiếu tọa độ (mặc định: epsg4326)"
      responses:
        "200":
          description: GADM34 vector tile (PBF)
          x-i18n:
            vi:
              description: Ô vector GADM34 (PBF)
          content:
            application/vnd.mapbox-vector-tile:
              schema:
                type: string
                format: binary

  /api/tiles/gadm63/{z}/{x}/{y}:
    get:
      tags: [Business Layer]
      operationId: getGadm63Tile
      summary: "[Vector] Administrative boundaries GADM63"
      description: |
        Vector tile (PBF) of Vietnam administrative boundaries at GADM63 (63-province) resolution.
        Native tile coverage is available at zoom levels 0–16 through the Playground GADM layer.
        Tiles are served in Web Mercator (EPSG:3857); for VN2000-projected coordinates use the
        `/api/idunn/v1/transform` endpoint or the GADM detail API.

        > **Data sensitivity notice:** PBF tiles expose detailed boundary geometries.
        > Access control and rate limiting apply.
      x-i18n:
        vi:
          summary: "[Vector] Ranh giới hành chính GADM63"
          description: |
            Ô vector (PBF) ranh giới hành chính Việt Nam ở độ phân giải GADM63 (63 tỉnh),
            với vùng tile gốc ở mức zoom 0–16. Khả dụng qua lớp GADM trên Playground.
            Ô được phục vụ theo Web Mercator (EPSG:3857); để lấy tọa độ VN2000 hãy dùng
            endpoint `/api/idunn/v1/transform` hoặc API chi tiết GADM.

            > **Lưu ý về độ nhạy cảm dữ liệu:** Ô PBF tiết lộ ranh giới chi tiết.
            > Áp dụng kiểm soát truy cập và giới hạn lưu lượng.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: z
          in: path
          required: true
          schema:
            type: integer
          description: Zoom level (0–16)
          x-i18n:
            vi:
              description: Mức thu phóng (0–16)
        - name: x
          in: path
          required: true
          schema:
            type: integer
          description: Tile X (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ X ô
        - name: y
          in: path
          required: true
          schema:
            type: integer
          description: Tile Y (Web Mercator)
          x-i18n:
            vi:
              description: Tọa độ Y ô
        - name: crs
          in: query
          schema:
            type: string
            enum: [epsg4326, vn2000]
          description: "Coordinate reference system (default: epsg4326)"
          x-i18n:
            vi:
              description: "Hệ quy chiếu tọa độ (mặc định: epsg4326)"
      responses:
        "200":
          description: GADM63 vector tile (PBF)
          x-i18n:
            vi:
              description: Ô vector GADM63 (PBF)
          content:
            application/vnd.mapbox-vector-tile:
              schema:
                type: string
                format: binary

  /api/hasura/gql/gadm/get-gadm-detail-by-coordinate:
    get:
      tags: [Business Layer]
      operationId: getGadmDetailByCoordinate
      summary: "[API] Administrative unit detail GADM by coordinate"
      description: |
        Returns the GADM34 and GADM63 administrative units containing the requested WGS84
        coordinate. Each unit includes its administrative metadata, center point, bounding box,
        boundary geometry, and recursively nested parent hierarchy. Boundary coordinates are
        returned in GeoJSON `[longitude, latitude]` order.

        The example abbreviates boundary coordinate arrays; the complete `bbox` and `geometry`
        values are returned by the API.
      x-i18n:
        vi:
          summary: "[API] Chi tiết đơn vị hành chính GADM theo tọa độ"
          description: |
            Trả về đơn vị hành chính GADM34 và GADM63 chứa tọa độ WGS84 được yêu cầu. Mỗi đơn vị
            gồm thông tin hành chính, tâm điểm, bounding box, hình học ranh giới và phân cấp đơn vị
            cha được lồng đệ quy. Tọa độ hình học trả về theo thứ tự GeoJSON `[kinh độ, vĩ độ]`.

            Ví dụ rút gọn phần mảng tọa độ ranh giới; API vẫn trả về đầy đủ giá trị `bbox` và `geometry`.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: lat
          in: query
          required: true
          schema:
            type: number
            format: double
            minimum: -90
            maximum: 90
          description: Latitude in WGS84 decimal degrees.
          x-i18n:
            vi:
              description: Vĩ độ theo WGS84, đơn vị độ thập phân.
          example: 21.023826
        - name: lon
          in: query
          required: true
          schema:
            type: number
            format: double
            minimum: -180
            maximum: 180
          description: Longitude in WGS84 decimal degrees.
          x-i18n:
            vi:
              description: Kinh độ theo WGS84, đơn vị độ thập phân.
          example: 105.794329
      responses:
        "200":
          description: GADM34 and GADM63 administrative detail for the coordinate.
          x-i18n:
            vi:
              description: Chi tiết hành chính GADM34 và GADM63 tại tọa độ được yêu cầu.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GadmCoordinateDetailResponse"
              example:
                geo_get_gadm_detail_by_coordinate:
                  - gadm34:
                      id: 600000715
                      osm_id: "relation:600000715"
                      admin_level: 6
                      zone_type: state_district
                      name: "Phường Yên Hòa"
                      loc_name: "Phường Yên Hòa"
                      div_code: "00175"
                      parent_id: 400000001
                      wikidata: ""
                      country_code: VN
                      postal_codes: "11312"
                      key: "00175"
                      epsg_code: "EPSG:4326"
                      center_point:
                        type: Point
                        coordinates: [105.795044999, 21.014384478]
                      bbox:
                        type: Polygon
                        coordinates: []
                      geometry:
                        type: MultiPolygon
                        coordinates: []
                      parent:
                        id: 400000001
                        osm_id: "relation:400000001"
                        admin_level: 4
                        zone_type: state
                        name: "Thành phố Hà Nội"
                        loc_name: "Thành phố Hà Nội"
                        div_code: "01"
                        parent_id: 200000001
                        wikidata: ""
                        country_code: VN
                        postal_codes: "10-11-12-13-14"
                        key: "01"
                        epsg_code: "EPSG:4326"
                        center_point:
                          type: Point
                          coordinates: [105.675051526, 20.974747873]
                        bbox:
                          type: Polygon
                          coordinates: []
                        geometry:
                          type: MultiPolygon
                          coordinates: []
                        parent:
                          id: 200000001
                          osm_id: "relation:200000001"
                          admin_level: 2
                          zone_type: country
                          name: "Việt Nam"
                          loc_name: ""
                          div_code: "VN"
                          parent_id: null
                          wikidata: "Q881"
                          country_code: "FR"
                          postal_codes: null
                          key: null
                          epsg_code: null
                          center_point:
                            type: Point
                            coordinates: [107.863510454, 15.97404813]
                          bbox:
                            type: Polygon
                            coordinates: []
                          geometry:
                            type: MultiPolygon
                            coordinates: []
                          parent: null
                    gadm63:
                      id: 800000061
                      osm_id: "relation:800000061"
                      admin_level: 8
                      zone_type: city_district
                      name: "Phường Yên Hoà"
                      loc_name: "Phường Yên Hoà"
                      div_code: "00172"
                      parent_id: 600010005
                      wikidata: null
                      country_code: VN
                      postal_codes: null
                      key: null
                      epsg_code: null
                      center_point:
                        type: Point
                        coordinates: [105.792070267, 21.021085524]
                      bbox:
                        type: Polygon
                        coordinates: []
                      geometry:
                        type: MultiPolygon
                        coordinates: []
                      parent:
                        id: 600010005
                        osm_id: "relation:600010005"
                        admin_level: 6
                        zone_type: state_district
                        name: "Quận Cầu Giấy"
                        loc_name: "Quận Cầu Giấy"
                        div_code: "005"
                        parent_id: 400000001
                        wikidata: null
                        country_code: VN
                        postal_codes: null
                        key: null
                        epsg_code: null
                        center_point:
                          type: Point
                          coordinates: [105.791320305, 21.029828801]
                        bbox:
                          type: Polygon
                          coordinates: []
                        geometry:
                          type: MultiPolygon
                          coordinates: []
                        parent:
                          id: 400000001
                          osm_id: "relation:400000001"
                          admin_level: 4
                          zone_type: state
                          name: "Thành phố Hà Nội"
                          loc_name: "Thành phố Hà Nội"
                          div_code: "01"
                          parent_id: 200000001
                          wikidata: null
                          country_code: VN
                          postal_codes: null
                          key: null
                          epsg_code: null
                          center_point:
                            type: Point
                            coordinates: [105.675500243, 20.974902939]
                          bbox:
                            type: Polygon
                            coordinates: []
                          geometry:
                            type: MultiPolygon
                            coordinates: []
                          parent:
                            id: 200000001
                            osm_id: "relation:200000001"
                            admin_level: 2
                            zone_type: country
                            name: "Việt Nam"
                            loc_name: ""
                            div_code: "VN"
                            parent_id: null
                            wikidata: null
                            country_code: VN
                            postal_codes: null
                            key: null
                            epsg_code: null
                            center_point:
                              type: Point
                              coordinates: [107.863510454, 15.97404813]
                            bbox:
                              type: Polygon
                              coordinates: []
                            geometry:
                              type: MultiPolygon
                              coordinates: []
                            parent: null

  /api/hasura/gql/gadm/get-gadm-detail-by-id:
    get:
      tags: [Business Layer]
      operationId: getGadmDetailById
      summary: "[API] Administrative unit detail GADM by ID"
      description: |
        Returns the GADM34 and GADM63 administrative units matching the requested administrative
        unit ID. Each unit includes its administrative metadata, center point, bounding box,
        boundary geometry, and recursively nested parent hierarchy. Boundary coordinates are
        returned in GeoJSON `[longitude, latitude]` order.

        The example abbreviates boundary coordinate arrays; the complete `bbox` and `geometry`
        values are returned by the API.
      x-i18n:
        vi:
          summary: "[API] Chi tiết đơn vị hành chính GADM theo mã"
          description: |
            Trả về đơn vị hành chính GADM34 và GADM63 khớp với mã đơn vị hành chính được yêu cầu.
            Mỗi đơn vị gồm thông tin hành chính, tâm điểm, bounding box, hình học ranh giới và phân
            cấp đơn vị cha được lồng đệ quy. Tọa độ hình học trả về theo thứ tự GeoJSON `[kinh độ, vĩ độ]`.

            Ví dụ rút gọn phần mảng tọa độ ranh giới; API vẫn trả về đầy đủ giá trị `bbox` và `geometry`.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: integer
            format: int64
          description: GADM administrative unit ID.
          x-i18n:
            vi:
              description: Mã đơn vị hành chính GADM.
          example: 400000001
      responses:
        "200":
          description: GADM34 and GADM63 administrative detail for the requested ID.
          x-i18n:
            vi:
              description: Chi tiết hành chính GADM34 và GADM63 theo mã được yêu cầu.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GadmByIdDetailResponse"
              example:
                geo_vnsdi_get_gadm_detail_by_id:
                  - gadm34:
                      id: 400000001
                      osm_id: "relation:400000001"
                      admin_level: 4
                      zone_type: state
                      name: "Thành phố Hà Nội"
                      loc_name: "Thành phố Hà Nội"
                      div_code: "01"
                      parent_id: 200000001
                      wikidata: ""
                      country_code: VN
                      postal_codes: "10-11-12-13-14"
                      key: "01"
                      epsg_code: "EPSG:4326"
                      center_point:
                        type: Point
                        coordinates: [105.675051526, 20.974747873]
                      bbox:
                        type: Polygon
                        coordinates: []
                      geometry:
                        type: MultiPolygon
                        coordinates: []
                      parent:
                        id: 200000001
                        osm_id: "relation:200000001"
                        admin_level: 2
                        zone_type: country
                        name: "Việt Nam"
                        loc_name: ""
                        div_code: "VN"
                        parent_id: null
                        wikidata: "Q881"
                        country_code: "FR"
                        postal_codes: null
                        key: null
                        epsg_code: null
                        center_point:
                          type: Point
                          coordinates: [107.863510454, 15.97404813]
                        bbox:
                          type: Polygon
                          coordinates: []
                        geometry:
                          type: MultiPolygon
                          coordinates: []
                        parent: null
                    gadm63:
                      id: 400000001
                      osm_id: "relation:400000001"
                      admin_level: 4
                      zone_type: state
                      name: "Thành phố Hà Nội"
                      loc_name: "Thành phố Hà Nội"
                      div_code: "01"
                      parent_id: 200000001
                      wikidata: null
                      country_code: VN
                      postal_codes: null
                      key: null
                      epsg_code: null
                      center_point:
                        type: Point
                        coordinates: [105.675500243, 20.974902939]
                      bbox:
                        type: Polygon
                        coordinates: []
                      geometry:
                        type: MultiPolygon
                        coordinates: []
                      parent:
                        id: 200000001
                        osm_id: "relation:200000001"
                        admin_level: 2
                        zone_type: country
                        name: "Việt Nam"
                        loc_name: ""
                        div_code: "VN"
                        parent_id: null
                        wikidata: null
                        country_code: VN
                        postal_codes: null
                        key: null
                        epsg_code: null
                        center_point:
                          type: Point
                          coordinates: [107.863510454, 15.97404813]
                        bbox:
                          type: Polygon
                          coordinates: []
                        geometry:
                          type: MultiPolygon
                          coordinates: []
                        parent: null

  # =========================================================================
  # Parcels
  # =========================================================================
  /api/hasura/gql/property/parcel/get-parcel-by-lat-lon:
    get:
      tags: [Parcels]
      operationId: getParcelByPoint
      summary: "[API] Parcel lookup by coordinate"
      description: |
        Returns all land parcels whose geometry covers the requested WGS84 coordinate.
        Each result may include planning information that intersects the parcel, such as zoning,
        project, and architecture-rule details. The lookup uses `ST_Covers`. Results are ordered
        by confidence score, most recent update, and record ID. Invalid or out-of-range coordinates
        return an empty array.
      x-i18n:
        vi:
          summary: "[API] Tra cứu thửa đất theo tọa độ"
          description: |
            Trả về tất cả thửa đất có hình học bao phủ tọa độ WGS84 được yêu cầu. Mỗi kết quả có thể
            kèm thông tin quy hoạch giao với thửa đất, như phân khu, dự án và chỉ tiêu kiến trúc.
            Tra cứu không gian sử dụng `ST_Covers`. Kết quả được sắp xếp theo điểm tin cậy, thời điểm
            cập nhật mới nhất và mã bản ghi. Tọa độ không hợp lệ hoặc nằm ngoài phạm vi sẽ trả về
            mảng rỗng.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: lat
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            pattern: '^-?\d+(\.\d+)?$'
          description: Latitude (WGS84, -90 to 90)
          x-i18n:
            vi:
              description: Vĩ độ (WGS84, -90 đến 90)
          example: "21.023826"
        - name: lon
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            pattern: '^-?\d+(\.\d+)?$'
          description: Longitude (WGS84, -180 to 180)
          x-i18n:
            vi:
              description: Kinh độ (WGS84, -180 đến 180)
          example: "105.794329"
      responses:
        "200":
          description: Parcel data with planning overlays (array of matching records)
          x-i18n:
            vi:
              description: Dữ liệu thửa đất kèm quy hoạch (mảng các bản ghi khớp)
          content:
            application/json:
              schema:
                type: object
                required: [property_get_prop_planning_parcel_by_point]
                properties:
                  property_get_prop_planning_parcel_by_point:
                    type: array
                    items:
                      $ref: "#/components/schemas/ParcelResponse"
              example:
                property_get_prop_planning_parcel_by_point:
                  - parcel_id: "09b688e9-4382-45b5-a2ef-0d198c14db5b"
                    so_to: "16"
                    so_thua: "706"
                    ma_thua_dat: "001720160706"
                    thong_tin_su_dung_dat:
                      - ma_su_dung_dat: "ODT"
                        ten_su_dung_dat: "Đất ở tại đô thị"
                        muc_dich_su_dung_dat: "Đất ở thuộc địa giới phường, thị trấn hoặc xã đã có dự án xây dựng đô thị mới."
                    dien_tich_m2: 41.7
                    ma_phuong_xa_cu: "00172"
                    ten_phuong_xa_cu: "Phường Yên Hòa"
                    ma_quan_huyen_cu: "005"
                    ten_quan_huyen_cu: "Quận Cầu Giấy"
                    ma_tinh_tp_cu: "01"
                    ten_tinh_tp_cu: "Thành phố Hà Nội"
                    ma_phuong_xa: "00175"
                    ten_phuong_xa: "Phường Yên Hòa"
                    ma_tinh_tp: "01"
                    ten_tinh_tp: "Thành phố Hà Nội"
                    center_geojson:
                      type: Point
                      coordinates: [105.794320664, 21.023828308]
                    geometry_geojson:
                      type: MultiPolygon
                      coordinates: [[[[105.794349989, 21.023787948], [105.79430602, 21.023788758], [105.794306137, 21.023872578], [105.794338585, 21.023872462], [105.794348319, 21.023872263], [105.794348554, 21.023860213], [105.794349404, 21.023817306], [105.794349989, 21.023787948]]]]
                    overlays: {}
                    thong_tin_khac:
                      chu_so_huu: null
                      do_rong_duong_m: null
                      khoang_cach_m: null
                      so_mat_tien: null
                      huong_mat_tien: null
                      hinh_dang: null
                    data_source: "public-verified"
                    confidence_score: 0.7
                    updated_at: "2026-07-15T08:06:38.373432"

  /api/hasura/gql/property/parcel/get-parcel-by-cadastral:
    get:
      tags: [Parcels]
      operationId: getParcelByCadastral
      summary: "[API] Parcel lookup by cadastral number"
      description: |
        Returns all land parcels matching the map sheet number, parcel number, and legacy
        ward/commune code. Optional legacy district and province/municipality codes can further
        narrow the search. Results are ordered by confidence score, most recent update, and record ID.
        If a required parameter is blank, the endpoint returns an empty array.
      x-i18n:
        vi:
          summary: "[API] Tra cứu thửa đất theo số tờ, số thửa"
          description: |
            Trả về tất cả thửa đất khớp với số tờ, số thửa và mã phường/xã cũ. Có thể lọc thêm
            theo mã quận/huyện hoặc tỉnh/thành phố cũ để thu hẹp kết quả. Kết quả được sắp xếp
            theo điểm tin cậy, thời điểm cập nhật mới nhất và mã bản ghi. Nếu tham số bắt buộc
            bị bỏ trống, endpoint sẽ trả về mảng rỗng.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: so_to
          in: query
          required: true
          schema:
            type: string
            minLength: 1
          description: Map sheet number
          x-i18n:
            vi:
              description: Số tờ bản đồ
          example: "31"
        - name: so_thua
          in: query
          required: true
          schema:
            type: string
            minLength: 1
          description: Parcel number within the sheet
          x-i18n:
            vi:
              description: Số thửa trong tờ bản đồ
          example: "50"
        - name: ma_phuong_xa_cu
          in: query
          required: true
          schema:
            type: string
            minLength: 1
          description: Legacy ward/commune code (gadm63, admin_level=8)
          x-i18n:
            vi:
              description: Mã phường/xã cũ (gadm63, admin_level=8)
          example: "20323"
        - name: ma_quan_huyen_cu
          in: query
          schema:
            type: string
          example: "497"
          description: Legacy district code — optional filter
          x-i18n:
            vi:
              description: Mã quận/huyện cũ — lọc thêm (tùy chọn)
        - name: ma_tinh_tp_cu
          in: query
          schema:
            type: string
          example: "48"
          description: Legacy province/city code — optional filter
          x-i18n:
            vi:
              description: Mã tỉnh/TP cũ — lọc thêm (tùy chọn)
      responses:
        "200":
          description: Parcel data with planning overlays (array of matching records)
          x-i18n:
            vi:
              description: Dữ liệu thửa đất kèm quy hoạch (mảng các bản ghi khớp)
          content:
            application/json:
              schema:
                type: object
                required: [property_get_prop_planning_parcel_by_cadastral]
                properties:
                  property_get_prop_planning_parcel_by_cadastral:
                    type: array
                    items:
                      $ref: "#/components/schemas/ParcelResponse"
              example:
                property_get_prop_planning_parcel_by_cadastral:
                  - parcel_id: "aa02b95f-fced-408a-96fe-725a17086e4f"
                    so_to: "31"
                    so_thua: "50"
                    ma_thua_dat: "203230310050"
                    thong_tin_su_dung_dat:
                      - ma_su_dung_dat: "LUC"
                        ten_su_dung_dat: "Đất chuyên trồng lúa"
                        muc_dich_su_dung_dat: "Đất trồng từ 02 vụ lúa trở lên. Được bảo vệ nghiêm ngặt, hạn chế chuyển đổi mục đích."
                    dien_tich_m2: 238.2
                    ma_phuong_xa_cu: "20323"
                    ten_phuong_xa_cu: "Xã Hòa Châu"
                    ma_quan_huyen_cu: "497"
                    ten_quan_huyen_cu: "Huyện Hòa Vang"
                    ma_tinh_tp_cu: "48"
                    ten_tinh_tp_cu: "Thành phố Đà Nẵng"
                    ma_phuong_xa: "20314"
                    ten_phuong_xa: "Phường Hòa Xuân"
                    ma_tinh_tp: "48"
                    ten_tinh_tp: "Thành phố Đà Nẵng"
                    center_geojson:
                      type: Point
                      coordinates: [108.200239679, 15.984659154]
                    geometry_geojson:
                      type: MultiPolygon
                      coordinates: [[[[108.200248925, 15.984766858], [108.200329476, 15.984607087], [108.200232939, 15.984553516], [108.200148259, 15.984705252], [108.200248925, 15.984766858]]]]
                    overlays:
                      qh_phan_khu:
                        - plan_code: "qh_phan_khu_da_nang"
                          loai_quy_hoach: "qh_phan_khu"
                          ten_quy_hoach: "Quy hoạch phân khu Thành phố Đà Nẵng"
                          projects:
                            - project_id: "296a970a-1ee7-4833-832a-c9ce8fa84d07"
                              project_name: "Tổng mặt bằng Khu vực phía Tây Nam"
                              chu_dau_tu: null
                              tinh_trang: "dang_trien_khai"
                              dien_tich_ha: 9965
                              so_quyet_dinh: "1618"
                              ngay_phe_duyet: "2017-03-29"
                              nam_quy_hoach: "2017"
                              project_overlay:
                                overlay_id: "08bd4aed-107d-4ae0-9a41-c60e00a65151"
                                ty_le_giao: 1
                                dien_tich_giao_m2: 238.26845623366535
                                geometry_geojson:
                                  type: Polygon
                                  coordinates: [[[108.200329476, 15.984607087], [108.200232939, 15.984553516], [108.200148259, 15.984705252], [108.200248925, 15.984766858], [108.200329476, 15.984607087]]]
                                created_at: "2026-07-16T05:49:11.196982"
                              zones:
                                - zone_id: "38e01da0-706d-48d7-b6c5-d3cc90e97daf"
                                  zone_name: "Đất đơn vị ở"
                                  loai_vung: "vung_chuc_nang"
                                  ma_su_dung_dat: "QHOLK"
                                  ma_o_quy_hoach: "B-2"
                                  dien_tich_m2: 52651.30078125
                                  zone_overlay:
                                    overlay_id: "e5afabe1-6673-4184-af24-7d7562a81d79"
                                    ty_le_giao: 1
                                    dien_tich_giao_m2: 238.26845623366535
                                    ma_su_dung_dat: "QHOLK"
                                    ten_su_dung_dat: "Đất đơn vị ở"
                                    geometry_geojson:
                                      type: Polygon
                                      coordinates: [[[108.200329476, 15.984607087], [108.200232939, 15.984553516], [108.200148259, 15.984705252], [108.200248925, 15.984766858], [108.200329476, 15.984607087]]]
                                    created_at: "2026-07-16T05:49:11.196982"
                          architecture_rules: []
                    thong_tin_khac:
                      chu_so_huu: null
                      do_rong_duong_m: null
                      khoang_cach_m: null
                      so_mat_tien: null
                      huong_mat_tien: null
                      hinh_dang: null
                    data_source: "official-verified"
                    confidence_score: 1
                    updated_at: "2026-07-15T12:22:15.576595"

  /api/hasura/gql/property/get-land-use:
    get:
      tags: [Parcels]
      operationId: getLandUse
      summary: "[PLANNED] [API] Land-use code reference"
      description: |
        **Status:** This endpoint is under development and not yet available in production.

        Returns the full land-use code tree from the Hasura `property_get_land_use_tree` function.
        Each record contains the land-use code, Vietnamese name, purpose description, parent code,
        and depth level in the tree. This endpoint has no query parameters.

        Designed to assist in interpreting the `ma_su_dung_dat` field in parcel lookup responses.
      x-i18n:
        vi:
          summary: "[DỰ KIẾN] [API] Danh mục mã loại đất"
          description: |
            **Trạng thái:** Endpoint này đang trong quá trình phát triển, chưa khả dụng.

            Trả về toàn bộ cây mã sử dụng đất từ function Hasura `property_get_land_use_tree`.
            Mỗi bản ghi gồm mã sử dụng đất, tên tiếng Việt, mô tả mục đích, mã cha và cấp độ trong cây.
            Endpoint này không có query parameter.

            Phục vụ việc tra cứu ý nghĩa của trường `ma_su_dung_dat` trong kết quả tra cứu thửa đất.
      security:
        - ApiKeyAuth: []
      parameters: []
      responses:
        "404":
          description: Not implemented — the endpoint is not defined in production yet (verified live).
          x-i18n:
            vi:
              description: Chưa triển khai — endpoint chưa được định nghĩa trên môi trường sản xuất (đã kiểm chứng).
        "200":
          description: Full land-use code tree.
          x-i18n:
            vi:
              description: Toàn bộ cây mã loại đất.
          content:
            application/json:
              schema:
                type: object
                required: [property_get_land_use_tree]
                properties:
                  property_get_land_use_tree:
                    type: array
                    description: Land-use code tree records returned by the Hasura REST query.
                    x-i18n:
                      vi:
                        description: Danh sách cây mã loại đất trả về từ Hasura REST query.
                    items:
                      type: object
                      required: [ma_su_dung_dat, ten_su_dung_dat, level]
                      properties:
                        ma_su_dung_dat:
                          type: string
                          description: Land-use code
                          example: ODT
                          x-i18n:
                            vi:
                              description: Mã sử dụng đất
                        ten_su_dung_dat:
                          type: string
                          description: Vietnamese land-use name
                          example: Đất ở tại đô thị
                          x-i18n:
                            vi:
                              description: Tên loại đất tiếng Việt
                        muc_dich_su_dung:
                          type: string
                          nullable: true
                          description: Land-use purpose description
                          example: Đất ở thuộc địa giới phường, thị trấn hoặc xã đã có dự án xây dựng đô thị mới.
                          x-i18n:
                            vi:
                              description: Mô tả mục đích sử dụng đất
                        parent_code:
                          type: string
                          nullable: true
                          description: Parent land-use code; null for root groups.
                          x-i18n:
                            vi:
                              description: Mã sử dụng đất cha; null đối với nhóm gốc.
                        level:
                          type: integer
                          description: Depth level in the land-use tree.
                          x-i18n:
                            vi:
                              description: Cấp độ trong cây mã sử dụng đất.
              example:
                property_get_land_use_tree:
                  - ma_su_dung_dat: NNP
                    ten_su_dung_dat: Nhóm đất nông nghiệp
                    muc_dich_su_dung: Nhóm đất sử dụng vào mục đích sản xuất nông nghiệp, lâm nghiệp, nuôi trồng thủy sản, làm muối và các mục đích bảo vệ, phát triển rừng.
                    parent_code: null
                    level: 0
                  - ma_su_dung_dat: PNN
                    ten_su_dung_dat: Nhóm đất phi nông nghiệp
                    muc_dich_su_dung: Nhóm đất không thuộc nhóm đất nông nghiệp.
                    parent_code: null
                    level: 0
                  - ma_su_dung_dat: OTC
                    ten_su_dung_dat: Đất ở
                    muc_dich_su_dung: Đất làm nhà ở và các mục đích khác phục vụ cho đời sống trong cùng một thửa đất.
                    parent_code: PNN
                    level: 1

  # Legacy commune code reference
  /api/hasura/gql/gadm/unit:
    get:
      tags: [Parcels]
      operationId: GeoGadm63UnitDetail
      summary: "[API] Legacy commune code reference"
      description: |
        Returns the administrative units below the specified parent unit.
        Set null `parent_id` to list top-level province/city units. Pass a returned `id`
        as `parent_id` to browse the district and commune hierarchy.
        Each result contains `id`, `div_code`, `name`, and `zone_type`.
      x-i18n:
        vi:
          summary: "[API] Danh mục mã xã cũ"
          description: |
            Trả về các đơn vị hành chính bên dưới đơn vị cha được chỉ định.
            Để null `parent_id` để lấy danh sách đơn vị cấp tỉnh/thành phố.
            Truyền `id` nhận được vào `parent_id` để duyệt tiếp cấp quận/huyện và phường/xã.
            Mỗi kết quả gồm `id`, `div_code`, `name` và `zone_type`.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: parent_id
          in: query
          schema:
            type: integer
            format: int64
          description: |
            Parent administrative unit ID (a province/city id is a 9-digit `4000000xx`).
            Set null to list top-level province/city units.
          x-i18n:
            vi:
              description: |
                Mã đơn vị hành chính cha (mã tỉnh/thành phố dạng `4000000xx` 9 chữ số).
                Để null để lấy danh sách đơn vị cấp tỉnh/thành phố.
          example: 400000001
      responses:
        "200":
          description: List of child administrative units.
          x-i18n:
            vi:
              description: Danh sách các đơn vị hành chính cấp dưới.
          content:
            application/json:
              schema:
                type: object
                required: [property_get_admin_children]
                properties:
                  property_get_admin_children:
                    type: array
                    items:
                      type: object
                      required: [id, div_code, name, zone_type]
                      properties:
                        id:
                          type: integer
                          format: int64
                          description: Administrative unit ID. Use it as `parent_id` to retrieve child units.
                          x-i18n:
                            vi:
                              description: Mã đơn vị hành chính. Dùng giá trị này làm `parent_id` để lấy các đơn vị cấp dưới.
                        div_code:
                          type: string
                          description: Administrative division code.
                          example: "01"
                          x-i18n:
                            vi:
                              description: Mã đơn vị hành chính.
                        name:
                          type: string
                          description: Administrative unit name.
                          x-i18n:
                            vi:
                              description: Tên đơn vị hành chính.
                        zone_type:
                          type: string
                          description: Administrative level of the unit.
                          x-i18n:
                            vi:
                              description: Cấp hành chính của đơn vị.
              example:
                property_get_admin_children:
                  - id: 400000092
                    div_code: "92"
                    name: "Thành phố Cần Thơ"
                    zone_type: "state"
                  - id: 400000048
                    div_code: "48"
                    name: "Thành phố Đà Nẵng"
                    zone_type: "state"
                  - id: 400000031
                    div_code: "31"
                    name: "Thành phố Hải Phòng"
                    zone_type: "state"
                  - id: 400000001
                    div_code: "01"
                    name: "Thành phố Hà Nội"
                    zone_type: "state"
                  - id: 400000079
                    div_code: "79"
                    name: "Thành phố Hồ Chí Minh"
                    zone_type: "state"
                  - id: 400000046
                    div_code: "46"
                    name: "Thành phố Huế"
                    zone_type: "state"
                  - id: 400000089
                    div_code: "89"
                    name: "Tỉnh An Giang"
                    zone_type: "state"
                  - id: 400000024
                    div_code: "24"
                    name: "Tỉnh Bắc Giang"
                    zone_type: "state"
                  - id: 400000006
                    div_code: "06"
                    name: "Tỉnh Bắc Kạn"
                    zone_type: "state"
                  - id: 400000095
                    div_code: "95"
                    name: "Tỉnh Bạc Liêu"
                    zone_type: "state"
                  - id: 400000027
                    div_code: "27"
                    name: "Tỉnh Bắc Ninh"
                    zone_type: "state"
                  - id: 400000077
                    div_code: "77"
                    name: "Tỉnh Bà Rịa - Vũng Tàu"
                    zone_type: "state"
                  - id: 400000083
                    div_code: "83"
                    name: "Tỉnh Bến Tre"
                    zone_type: "state"
                  - id: 400000052
                    div_code: "52"
                    name: "Tỉnh Bình Định"
                    zone_type: "state"
                  - id: 400000074
                    div_code: "74"
                    name: "Tỉnh Bình Dương"
                    zone_type: "state"
                  - id: 400000070
                    div_code: "70"
                    name: "Tỉnh Bình Phước"
                    zone_type: "state"
                  - id: 400000060
                    div_code: "60"
                    name: "Tỉnh Bình Thuận"
                    zone_type: "state"
                  - id: 400000096
                    div_code: "96"
                    name: "Tỉnh Cà Mau"
                    zone_type: "state"
                  - id: 400000004
                    div_code: "04"
                    name: "Tỉnh Cao Bằng"
                    zone_type: "state"
                  - id: 400000066
                    div_code: "66"
                    name: "Tỉnh Đắk Lắk"
                    zone_type: "state"
                  - id: 400000067
                    div_code: "67"
                    name: "Tỉnh Đắk Nông"
                    zone_type: "state"
                  - id: 400000011
                    div_code: "11"
                    name: "Tỉnh Điện Biên"
                    zone_type: "state"
                  - id: 400000075
                    div_code: "75"
                    name: "Tỉnh Đồng Nai"
                    zone_type: "state"
                  - id: 400000087
                    div_code: "87"
                    name: "Tỉnh Đồng Tháp"
                    zone_type: "state"
                  - id: 400000064
                    div_code: "64"
                    name: "Tỉnh Gia Lai"
                    zone_type: "state"
                  - id: 400000002
                    div_code: "02"
                    name: "Tỉnh Hà Giang"
                    zone_type: "state"
                  - id: 400000030
                    div_code: "30"
                    name: "Tỉnh Hải Dương"
                    zone_type: "state"
                  - id: 400000035
                    div_code: "35"
                    name: "Tỉnh Hà Nam"
                    zone_type: "state"
                  - id: 400000042
                    div_code: "42"
                    name: "Tỉnh Hà Tĩnh"
                    zone_type: "state"
                  - id: 400000093
                    div_code: "93"
                    name: "Tỉnh Hậu Giang"
                    zone_type: "state"
                  - id: 400000017
                    div_code: "17"
                    name: "Tỉnh Hoà Bình"
                    zone_type: "state"
                  - id: 400000033
                    div_code: "33"
                    name: "Tỉnh Hưng Yên"
                    zone_type: "state"
                  - id: 400000056
                    div_code: "56"
                    name: "Tỉnh Khánh Hòa"
                    zone_type: "state"
                  - id: 400000091
                    div_code: "91"
                    name: "Tỉnh Kiên Giang"
                    zone_type: "state"
                  - id: 400000062
                    div_code: "62"
                    name: "Tỉnh Kon Tum"
                    zone_type: "state"
                  - id: 400000012
                    div_code: "12"
                    name: "Tỉnh Lai Châu"
                    zone_type: "state"
                  - id: 400000068
                    div_code: "68"
                    name: "Tỉnh Lâm Đồng"
                    zone_type: "state"
                  - id: 400000020
                    div_code: "20"
                    name: "Tỉnh Lạng Sơn"
                    zone_type: "state"
                  - id: 400000010
                    div_code: "10"
                    name: "Tỉnh Lào Cai"
                    zone_type: "state"
                  - id: 400000080
                    div_code: "80"
                    name: "Tỉnh Long An"
                    zone_type: "state"
                  - id: 400000036
                    div_code: "36"
                    name: "Tỉnh Nam Định"
                    zone_type: "state"
                  - id: 400000040
                    div_code: "40"
                    name: "Tỉnh Nghệ An"
                    zone_type: "state"
                  - id: 400000037
                    div_code: "37"
                    name: "Tỉnh Ninh Bình"
                    zone_type: "state"
                  - id: 400000058
                    div_code: "58"
                    name: "Tỉnh Ninh Thuận"
                    zone_type: "state"
                  - id: 400000025
                    div_code: "25"
                    name: "Tỉnh Phú Thọ"
                    zone_type: "state"
                  - id: 400000054
                    div_code: "54"
                    name: "Tỉnh Phú Yên"
                    zone_type: "state"
                  - id: 400000044
                    div_code: "44"
                    name: "Tỉnh Quảng Bình"
                    zone_type: "state"
                  - id: 400000049
                    div_code: "49"
                    name: "Tỉnh Quảng Nam"
                    zone_type: "state"
                  - id: 400000051
                    div_code: "51"
                    name: "Tỉnh Quảng Ngãi"
                    zone_type: "state"
                  - id: 400000022
                    div_code: "22"
                    name: "Tỉnh Quảng Ninh"
                    zone_type: "state"
                  - id: 400000045
                    div_code: "45"
                    name: "Tỉnh Quảng Trị"
                    zone_type: "state"
                  - id: 400000094
                    div_code: "94"
                    name: "Tỉnh Sóc Trăng"
                    zone_type: "state"
                  - id: 400000014
                    div_code: "14"
                    name: "Tỉnh Sơn La"
                    zone_type: "state"
                  - id: 400000072
                    div_code: "72"
                    name: "Tỉnh Tây Ninh"
                    zone_type: "state"
                  - id: 400000034
                    div_code: "34"
                    name: "Tỉnh Thái Bình"
                    zone_type: "state"
                  - id: 400000019
                    div_code: "19"
                    name: "Tỉnh Thái Nguyên"
                    zone_type: "state"
                  - id: 400000038
                    div_code: "38"
                    name: "Tỉnh Thanh Hóa"
                    zone_type: "state"
                  - id: 400000082
                    div_code: "82"
                    name: "Tỉnh Tiền Giang"
                    zone_type: "state"
                  - id: 400000084
                    div_code: "84"
                    name: "Tỉnh Trà Vinh"
                    zone_type: "state"
                  - id: 400000008
                    div_code: "08"
                    name: "Tỉnh Tuyên Quang"
                    zone_type: "state"
                  - id: 400000086
                    div_code: "86"
                    name: "Tỉnh Vĩnh Long"
                    zone_type: "state"
                  - id: 400000026
                    div_code: "26"
                    name: "Tỉnh Vĩnh Phúc"
                    zone_type: "state"
                  - id: 400000015
                    div_code: "15"
                    name: "Tỉnh Yên Bái"
                    zone_type: "state"

  # TODO — Parcel fuzzy search
  /api/parcel/v1/search:
    get:
      tags: [Parcels]
      operationId: todo-parcel-fuzzy-search
      summary: "[PLANNED] [API] Fuzzy parcel search"
      description: |
        **Status:** This endpoint is under development and not yet available in production.

        Free-text fuzzy search across parcels by map sheet number, parcel number,
        or province/city name. Returns a list of matching parcels with basic metadata.

        This endpoint provides quick discovery capabilities. For precise cadastral
        lookup, use `/api/hasura/gql/property/parcel/get-parcel-by-cadastral`.
      x-i18n:
        vi:
          summary: "[DỰ KIẾN] [API] Tìm kiếm thửa đất tương đối"
          description: |
            **Trạng thái:** Endpoint này đang trong quá trình phát triển, chưa khả dụng.

            Tìm kiếm tương đối (fuzzy) theo số tờ, số thửa hoặc tên tỉnh/thành.
            Trả về danh sách thửa đất khớp kèm thông tin cơ bản.

            Endpoint này hỗ trợ tra cứu nhanh. Để tra cứu chính xác theo cadastral,
            sử dụng `/api/hasura/gql/property/parcel/get-parcel-by-cadastral`.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
          description: Search query (map sheet, parcel number, or province/city name)
          example: "Hòa Xuân"
          x-i18n:
            vi:
              description: "Từ khóa tìm kiếm (số tờ, số thửa hoặc tên tỉnh/thành)"
      responses:
        "404":
          description: Not implemented — the route is not deployed in production yet (verified live).
          x-i18n:
            vi:
              description: Chưa triển khai — route chưa được triển khai trên môi trường sản xuất (đã kiểm chứng).
