MoaHub API Gateway

전국지역화폐맵 API Documentation

v1 · Base URL: https://voucher-api.moahub.co.kr

Overview

공공데이터포털(data.go.kr)의 지역사랑상품권 가맹점 및 판매정책 데이터를 정규화하여 제공하는 API Gateway입니다. Flutter 앱 “전국지역화폐맵”의 백엔드로 사용됩니다.

CacheIn-memory TTL 캐시 (10분)
Rate LimitIP 기반 분당 60회
SecurityserviceKey 완전 마스킹
Normalization일관된 앱 스키마 변환

Endpoints

GET/api/health

서버 상태 확인

Response 200
{
  "ok": true,
  "now": "2026-03-01T17:36:07.291Z",
  "version": "v1"
}
GET/api/v1/regions

전국 103개 시군구 목록 (정적 데이터)

Response 200
[
  {
    "region_code": "11010",
    "name": "서울 종로구",
    "level": "gu",
    "parent_code": "11000"
  },
  ...
]
GET/api/v1/policy?region_code=XXXXX

특정 지역의 지역화폐 판매정책 (정규화된 데이터)

ParameterTypeRequiredDescription
region_codestringYes5자리 시군구 코드 (예: 11680)
Response 200
{
  "region_code": "11680",
  "discount_rate": 0.07,
  "monthly_limit": 500000,
  "period": {
    "start": "2026-01-01",
    "end": "2026-12-31"
  },
  "updated_at": "2026-03-01T00:00:00Z",
  "source": {
    "name": "Public Data",
    "fetched_at": "2026-03-01T17:00:00Z"
  }
}
GET/api/v1/merchants/manifest?region_code=XXXXX

가맹점 데이터셋 메타정보 (URL, SHA256, 건수)

ParameterTypeRequiredDescription
region_codestringYes5자리 시군구 코드
Response 200
{
  "region_code": "11680",
  "dataset": {
    "url": "https://voucher-api.moahub.co.kr/api/v1/merchants/dataset/11680",
    "sha256": "a1b2c3d4e5...",
    "generated_at": "2026-03-01T17:00:00.000Z",
    "count": 1234
  },
  "source": {
    "name": "Public Data",
    "fetched_at": "2026-03-01T17:00:00.000Z"
  }
}
GET/api/v1/merchants/dataset/{regionCode}

가맹점 데이터셋 다운로드 (gzip 압축 JSON)

Content-Type: application/gzip · 앱에서 로컬 DB 동기화에 사용

Response Headers
Content-Type: application/gzip
Content-Disposition: attachment; filename="11680.json.gz"
X-Dataset-Count: 1234
X-Dataset-SHA256: a1b2c3d4e5...
Decompressed JSON (NormalizedMerchant[])
[
  {
    "merchant_id": "a1b2c3d4e5f67890",
    "name": "스타벅스 강남점",
    "address": "서울특별시 강남구 테헤란로 123",
    "lat": 37.4979,
    "lng": 127.0276,
    "industry": "커피전문점",
    "status": "ACTIVE",
    "updated_at": "2026-02-15T00:00:00Z",
    "quality": {
      "location_suspect": false,
      "stale": false
    }
  },
  ...
]

Admin Endpoints

x-admin-token 헤더 필요. ADMIN_TOKEN 환경변수 미설정 시 403 반환.

ADMIN/api/v1/franchises/raw

가맹점 공공API 원본 응답 프록시

ParameterTypeRequiredDescription
pageNonumberNo페이지 번호 (기본 1)
numOfRowsnumberNo페이지당 건수 (기본 10, 최대 200)
ADMIN/api/v1/policies/raw?kind=paper|cardMobile

정책 공공API 원본 응답 프록시

ParameterTypeRequiredDescription
kindstringYes"paper" 또는 "cardMobile"
pageNonumberNo페이지 번호 (기본 1)
numOfRowsnumberNo페이지당 건수 (기본 10, 최대 200)

Error Responses

모든 에러는 동일한 구조로 반환됩니다.

{
  "error": {
    "code": "BAD_REQUEST | FORBIDDEN | NOT_FOUND | TOO_MANY_REQUESTS | INTERNAL_ERROR",
    "message": "에러 설명",
    "details": {}
  }
}
StatusCodeDescription
400BAD_REQUEST잘못된 파라미터
403FORBIDDEN인증 실패 (Admin)
404NOT_FOUND데이터 없음
429TOO_MANY_REQUESTSRate Limit 초과
500INTERNAL_ERROR서버 에러

Data Normalization

Merchant ID 생성 규칙

sha1(name | address | lat.toFixed(4) | lng.toFixed(4)).substring(0, 16)

Status 매핑

원본정규화
영업중, 기타ACTIVE
폐업, 중지, 휴업INACTIVE

Quality Flags

Flag조건
staleupdated_at이 180일 이상 전
location_suspect클라이언트에서 판정

위경도 유효범위 (한국)

위도: 33~39 / 경도: 124~132 · 범위 밖이면 row 제외