{
  "openapi": "3.0.3",
  "info": {
    "title": "GAIA Free ZipCode & Logistics API",
    "description": "우체국 공식 전국 우편번호(645만 건 도로명주소), 도서산간·제주 추가 배송비 판별, 실시간 자동완성 및 당근 지역 매핑을 제공하는 고성능 무료 오픈 API 서비스입니다.\n\n### 주요 특징\n- **무료 & 무제한 기본 제공** (공개 API 기본 분당 60회 속도 제한 방어)\n- **도서산간·제주 배송비 자동 계산**\n- **CORS 허용 (`Access-Control-Allow-Origin: *`)**으로 프론트엔드 직접 연동 가능\n- **JSON 응답 표준 준수**",
    "version": "1.0.0",
    "contact": {
      "name": "GAIA Dev Team",
      "url": "https://zip.gaiadev.co.kr"
    }
  },
  "servers": [
    {
      "url": "https://zip.gaiadev.co.kr",
      "description": "운영 프로덕션 서버 (NAS PROD)"
    },
    {
      "url": "",
      "description": "현재 도메인 상대 경로"
    }
  ],
  "paths": {
    "/api/search.php": {
      "get": {
        "summary": "우편번호 및 도로명·지번 주소 검색",
        "description": "검색어(도로명, 건물명, 지번, 우편번호)를 기반으로 우편번호 데이터베이스를 조회하며, 도서산간 및 제주 추가 배송비 정보를 함께 반환합니다.",
        "operationId": "searchZipCode",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "검색할 키워드 (예: 세종대로, 03186, 역삼동)",
            "schema": {
              "type": "string",
              "example": "세종대로"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "페이지 번호 (기본값: 1)",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "한 페이지 결과 수 (1~100, 기본값: 20)",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "정렬 기준 (address_asc, address_desc, zipcode_asc, zipcode_desc)",
            "schema": {
              "type": "string",
              "enum": ["address_asc", "address_desc", "zipcode_asc", "zipcode_desc"],
              "default": "address_asc"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "검색 성공",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/remote-area.php": {
      "get": {
        "summary": "도서산간 / 제주 추가 배송비 판별기",
        "description": "우편번호 5자리 또는 주소 텍스트를 전달받아 제주권(+3,000원) 및 도서산간(+5,000원) 여부와 추가 운임을 즉시 산출합니다.",
        "operationId": "checkRemoteArea",
        "parameters": [
          {
            "name": "zip",
            "in": "query",
            "required": true,
            "description": "5자리 우편번호 (기초구역번호, 예: 63000, 23114)",
            "schema": {
              "type": "string",
              "example": "63000"
            }
          },
          {
            "name": "addr",
            "in": "query",
            "required": false,
            "description": "보정용 주소 텍스트 (예: 제주시, 추자면)",
            "schema": {
              "type": "string",
              "example": "제주특별자치도 제주시"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "판별 성공",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemoteAreaResponse"
                }
              }
            }
          },
          "400": {
            "description": "필수 파라미터(zip) 누락"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/autocomplete.php": {
      "get": {
        "summary": "초고속 주소 자동완성 (Autocomplete)",
        "description": "타이핑 중 입력된 키워드나 초성(ㄱ~ㅎ)에 일치하는 도로명/우편번호 추천 목록을 0.005초 내로 빠르게 반환합니다.",
        "operationId": "getAutocomplete",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "검색어 접두사 또는 초성 (예: 세종, 남대, 031, ㄴㄷㅁ)",
            "schema": {
              "type": "string",
              "example": "세종"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "자동완성 대상 (zipcode | carrot, 기본값: zipcode)",
            "schema": {
              "type": "string",
              "enum": ["zipcode", "carrot"],
              "default": "zipcode"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "자동완성 목록 반환 성공",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutocompleteResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "SearchResponse": {
        "type": "object",
        "properties": {
          "status": { "type": "integer", "example": 200 },
          "total": { "type": "integer", "example": 8 },
          "page": { "type": "integer", "example": 1 },
          "limit": { "type": "integer", "example": 20 },
          "data": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ZipCodeItem" }
          },
          "suggestion": {
            "type": "object",
            "nullable": true,
            "properties": {
              "suggested": { "type": "string", "example": "세종대로" },
              "similarity": { "type": "number", "example": 0.88 }
            }
          }
        }
      },
      "ZipCodeItem": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "example": 1024 },
          "zip_code": { "type": "string", "example": "03186" },
          "address": { "type": "string", "example": "서울특별시 종로구 세종대로 209" },
          "jibun_address": { "type": "string", "example": "서울특별시 종로구 세종로 77-6" },
          "sido": { "type": "string", "example": "서울특별시" },
          "sigungu": { "type": "string", "example": "종로구" },
          "road_name": { "type": "string", "example": "세종대로" },
          "building_name": { "type": "string", "example": "정부서울청사" },
          "legal_dong_name": { "type": "string", "example": "세종로" },
          "remote_area": { "$ref": "#/components/schemas/RemoteAreaInfo" }
        }
      },
      "RemoteAreaInfo": {
        "type": "object",
        "properties": {
          "is_remote": { "type": "boolean", "example": false },
          "is_jeju": { "type": "boolean", "example": false },
          "extra_fee": { "type": "integer", "example": 0 },
          "label": { "type": "string", "example": "일반 내륙 (표준 운임)" }
        }
      },
      "RemoteAreaResponse": {
        "type": "object",
        "properties": {
          "status": { "type": "integer", "example": 200 },
          "zip_code": { "type": "string", "example": "63000" },
          "is_remote": { "type": "boolean", "example": false },
          "is_jeju": { "type": "boolean", "example": true },
          "extra_fee": { "type": "integer", "example": 3000 },
          "label": { "type": "string", "example": "제주 권역 (추가운임 +3,000원)" }
        }
      },
      "AutocompleteResponse": {
        "type": "object",
        "properties": {
          "status": { "type": "integer", "example": 200 },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "display": { "type": "string", "example": "서울특별시 종로구 세종대로 209 (정부서울청사)" },
                "zip_code": { "type": "string", "example": "03186" },
                "sido": { "type": "string", "example": "서울특별시" },
                "sigungu": { "type": "string", "example": "종로구" },
                "dong": { "type": "string", "example": "세종로" }
              }
            }
          }
        }
      }
    },
    "responses": {
      "TooManyRequests": {
        "description": "호출 한도(분당 60회) 초과 시 반환",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "integer", "example": 429 },
                "error": { "type": "string", "example": "Too Many Requests" },
                "message": { "type": "string", "example": "요청 한도(분당 60회)를 초과했습니다. 잠시 후 다시 시도해 주세요." },
                "retry_after": { "type": "integer", "example": 60 }
              }
            }
          }
        }
      }
    }
  }
}

