{
    "openapi": "3.0.0",
    "info": {
        "title": "tinhthanhpho.com API",
        "description": "Vietnamese administrative units before and after 1 July 2025, and conversion of old addresses to the new units. Every successful response carries metadata.data_version. Conversion answers carry confidence (exact, check, not_found), a reason and, when the old ward was split or the text is ambiguous, candidates.",
        "contact": {
            "email": "contact@tinhthanhpho.com"
        },
        "version": "1.1.0"
    },
    "servers": [
        {
            "url": "https://tinhthanhpho.com",
            "description": "Production"
        }
    ],
    "paths": {
        "/api/v1/convert/address": {
            "post": {
                "tags": [
                    "Address Conversion"
                ],
                "summary": "Convert single address",
                "description": "Send free text (`text`) or the three old codes. The answer keeps the v1 fields (old, new, mergeInfo) and adds confidence (exact | check), reason and candidates (every new ward of a split old ward, or of ambiguous text). Not found: HTTP 422 with message, reason and suggestions.",
                "operationId": "41c48062ddf75b6433edfdd4cb47ebae",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "text": {
                                        "description": "Free text; or use the codes below",
                                        "type": "string",
                                        "maxLength": 300,
                                        "example": "12 Nguyễn Huệ, P. Bến Nghé, Q.1, TP.HCM"
                                    },
                                    "provinceCode": {
                                        "type": "string",
                                        "example": "01"
                                    },
                                    "districtCode": {
                                        "type": "string",
                                        "example": "001"
                                    },
                                    "wardCode": {
                                        "type": "string",
                                        "example": "00001"
                                    },
                                    "streetAddress": {
                                        "type": "string",
                                        "example": "15 Nguyễn Văn A"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "422": {
                        "description": "Validation error"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/convert/batch": {
            "post": {
                "tags": [
                    "Address Conversion"
                ],
                "summary": "Batch convert addresses",
                "description": "Each address counts as one call against the monthly quota; a batch larger than the calls left this month is refused with 429.",
                "operationId": "95553daa5fde909291511a504d8801b8",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "addresses"
                                ],
                                "properties": {
                                    "addresses": {
                                        "type": "array",
                                        "items": {
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "example": "addr_001"
                                                },
                                                "text": {
                                                    "type": "string",
                                                    "example": "Phường Bến Nghé, Quận 1, TP HCM"
                                                },
                                                "provinceCode": {
                                                    "type": "string",
                                                    "example": "01"
                                                },
                                                "districtCode": {
                                                    "type": "string",
                                                    "example": "001"
                                                },
                                                "wardCode": {
                                                    "type": "string",
                                                    "example": "00001"
                                                },
                                                "streetAddress": {
                                                    "type": "string",
                                                    "example": "15 Nguyễn Văn A"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/districts/{code}": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Get district details",
                "description": "Get district details",
                "operationId": "446ff2feee98a5452b4294841bc10fe6",
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "description": "District code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "404": {
                        "description": "District not found"
                    }
                }
            }
        },
        "/api/v1/districts/{districtCode}/wards": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Get wards by district",
                "description": "Get wards by district",
                "operationId": "9d84c6d508e84ad096279c4a98a5019e",
                "parameters": [
                    {
                        "name": "districtCode",
                        "in": "path",
                        "description": "District code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "keyword",
                        "in": "query",
                        "description": "Search keyword",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Number of results per page",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 20
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/full-address": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Get full address information",
                "description": "Get full address information",
                "operationId": "c12052af05d72c1c4faba678fd6b45c1",
                "parameters": [
                    {
                        "name": "provinceCode",
                        "in": "query",
                        "description": "Province code",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "districtCode",
                        "in": "query",
                        "description": "District code",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "wardCode",
                        "in": "query",
                        "description": "Ward code",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/merge-history/province/{code}": {
            "get": {
                "tags": [
                    "Merge History"
                ],
                "summary": "Get province merge history",
                "description": "Get merge history for a province",
                "operationId": "5c2e194480aafb04eaf4b5935e55e1f0",
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "description": "Province code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "404": {
                        "description": "Province not found"
                    }
                }
            }
        },
        "/api/v1/merge-history/ward/{code}": {
            "get": {
                "tags": [
                    "Merge History"
                ],
                "summary": "Get ward merge history",
                "description": "Get merge history for a ward",
                "operationId": "4b374a03d73b4b7a7c48dbe9a9a24359",
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "description": "Ward code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "404": {
                        "description": "Ward not found"
                    }
                }
            }
        },
        "/api/v1/new-full-address": {
            "get": {
                "tags": [
                    "Address - New Structure"
                ],
                "summary": "Get full address information (after 1/7/2025)",
                "description": "Get full address information (new structure)",
                "operationId": "1066f8c8d50e8f844c045f97344d1825",
                "parameters": [
                    {
                        "name": "provinceCode",
                        "in": "query",
                        "description": "Province code",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "wardCode",
                        "in": "query",
                        "description": "Ward code",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/new-provinces": {
            "get": {
                "tags": [
                    "Address - New Structure"
                ],
                "summary": "Get list of provinces (after 1/7/2025)",
                "description": "Get list of new provinces",
                "operationId": "b864c72f0c5caa2207ae6593e19e2a5f",
                "parameters": [
                    {
                        "name": "keyword",
                        "in": "query",
                        "description": "Search keyword",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Number of results per page",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 20
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/new-provinces/{code}": {
            "get": {
                "tags": [
                    "Address - New Structure"
                ],
                "summary": "Get new province details",
                "description": "Get new province details",
                "operationId": "8a09d8f36706cd23387b394c043acf2f",
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "description": "Province code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "404": {
                        "description": "Province not found"
                    }
                }
            }
        },
        "/api/v1/new-provinces/{provinceCode}/wards": {
            "get": {
                "tags": [
                    "Address - New Structure"
                ],
                "summary": "Get wards by new province",
                "description": "Get wards by new province",
                "operationId": "a559b4857f7b1d1b5dc6c8e5f25f4f55",
                "parameters": [
                    {
                        "name": "provinceCode",
                        "in": "path",
                        "description": "Province code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "keyword",
                        "in": "query",
                        "description": "Search keyword",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "description": "Only this unit type: phuong, xa or dac-khu (diacritics optional)",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "example": "phuong"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Number of results per page",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 20
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/new-wards/{code}": {
            "get": {
                "tags": [
                    "Address - New Structure"
                ],
                "summary": "Get new ward details",
                "description": "Get new ward details",
                "operationId": "38a76af43afe411f635dc1e9019edd45",
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "description": "Ward code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "404": {
                        "description": "Ward not found"
                    }
                }
            }
        },
        "/api/v1/profile": {
            "get": {
                "tags": [
                    "Account"
                ],
                "summary": "The account that owns the API key",
                "operationId": "9a4336b14bdee74fa925c7d52d3ce90b",
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "401": {
                        "description": "Unauthorized"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/provinces": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Get list of provinces (before 1/7/2025)",
                "description": "Get list of provinces",
                "operationId": "c66f8379fd1018228ba111594f29c1f9",
                "parameters": [
                    {
                        "name": "keyword",
                        "in": "query",
                        "description": "Search keyword",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Number of results per page",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 20
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "code": {
                                                        "type": "string",
                                                        "example": "01"
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "example": "Hà Nội"
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "example": "Thành phố"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "metadata": {
                                            "properties": {
                                                "total": {
                                                    "type": "integer",
                                                    "example": 63
                                                },
                                                "page": {
                                                    "type": "integer",
                                                    "example": 1
                                                },
                                                "limit": {
                                                    "type": "integer",
                                                    "example": 20
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/provinces/{code}": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Get province details",
                "description": "Get province details",
                "operationId": "8d609388d9a89ddce48a8d4f6ad57d87",
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "description": "Province code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "404": {
                        "description": "Province not found"
                    }
                }
            }
        },
        "/api/v1/provinces/{provinceCode}/districts": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Get districts by province",
                "description": "Get districts by province",
                "operationId": "c3422a269fed211367220bae1584ad92",
                "parameters": [
                    {
                        "name": "provinceCode",
                        "in": "path",
                        "description": "Province code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "keyword",
                        "in": "query",
                        "description": "Search keyword",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Number of results per page",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 20
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/search-address": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Search address across all levels",
                "description": "Search address",
                "operationId": "eef86145be84736b31df1f39ec39a04e",
                "parameters": [
                    {
                        "name": "keyword",
                        "in": "query",
                        "description": "Search keyword",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Maximum results",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 20
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/search-new-address": {
            "get": {
                "tags": [
                    "Address - New Structure"
                ],
                "summary": "Search address across all levels (after 1/7/2025)",
                "description": "Search address across all levels (new structure)",
                "operationId": "0e429aef9888c76fbf2a667d21946a5e",
                "parameters": [
                    {
                        "name": "keyword",
                        "in": "query",
                        "description": "Search keyword",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Maximum results",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 20
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    }
                }
            }
        },
        "/api/v1/suggest": {
            "get": {
                "tags": [
                    "Search"
                ],
                "summary": "Suggestions for a search box",
                "description": "New provinces and wards, and old wards with the unit they became. Understands names without diacritics and common abbreviations.",
                "operationId": "e43dce2f99b25ce7acefb09cb10b2eb7",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "description": "2 to 100 characters",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": "ben nghe"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 6,
                            "maximum": 10,
                            "minimum": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "422": {
                        "description": "Validation error"
                    },
                    "429": {
                        "description": "Too many requests"
                    }
                }
            }
        },
        "/api/v1/wards/{code}": {
            "get": {
                "tags": [
                    "Address - Old Structure"
                ],
                "summary": "Get ward details",
                "description": "Get ward details",
                "operationId": "e7b5a7b541e3d6baaf55352b926f273e",
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "description": "Ward code",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success"
                    },
                    "404": {
                        "description": "Ward not found"
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "description": "API key as a Bearer token (an X-API-Key header is also accepted). Conversion endpoints need the convert scope.",
                "scheme": "bearer"
            }
        }
    },
    "tags": [
        {
            "name": "Address - Old Structure",
            "description": "Provinces, districts and wards before 1 July 2025"
        },
        {
            "name": "Address - New Structure",
            "description": "Provinces and wards from 1 July 2025"
        },
        {
            "name": "Address Conversion",
            "description": "Old address to new units"
        },
        {
            "name": "Search",
            "description": "Suggestions for search boxes"
        },
        {
            "name": "Account",
            "description": "The key owner's account"
        },
        {
            "name": "Admin - Roles",
            "description": "Admin - Roles"
        },
        {
            "name": "Admin - Settings",
            "description": "Admin - Settings"
        },
        {
            "name": "Admin - Users",
            "description": "Admin - Users"
        },
        {
            "name": "Merge History",
            "description": "Merge History"
        }
    ]
}
