득템시루 API 명세서

시흥시 소상공인 상생 마감할인 플랫폼 · 시루가치 팀

Base URL  https://api.deuktem-siru.com/api/v1
인증  Authorization: Bearer {accessToken} — memberId는 JWT에서 추출, URL 노출 금지
필드 네이밍  Request / Response → camelCase  ·  DB 컬럼 → snake_case
공통 응답  { "code": 200, "message": "...", "data": { ... } }
POST/auth/kakao/login 카카오 소셜 로그인 / 회원가입
설명카카오 소셜 로그인을 처리합니다. 신규 사용자는 자동 회원가입됩니다.
헤더Content-Type: application/json
Path Variable없음
Query String없음
Request Body
요청 종류필드 이름필수타입설명
카카오 액세스 토큰kakaoAccessTokenString카카오에서 발급받은 토큰
가입 유형roleStringCONSUMER / SELLER
Request Sample
POST /api/v1/auth/kakao/login { "kakaoAccessToken": "kakao_token_here", "role": "CONSUMER" }
Response Body
성공 여부응답 코드설명
Success200기존 회원 로그인 성공
Success201신규 회원가입 후 로그인
Error400유효하지 않은 카카오 토큰
Error500서버 내부 오류
Response Sample
// 200 OK { "code": 200, "message": "로그인 성공", "data": { "accessToken": "eyJ...", "refreshToken": "eyJ...", "member": { "memberId": 1, "nickname": "득템러", "role": "CONSUMER" } } } // 400 Bad Request { "code": 400, "message": "유효하지 않은 카카오 토큰입니다.", "data": null }
POST/auth/refresh 액세스 토큰 갱신
설명만료된 액세스 토큰을 갱신합니다.
헤더Content-Type: application/json
Path Variable없음
Query String없음
Request Body
요청 종류필드 이름필수타입설명
리프레시 토큰refreshTokenString발급받은 리프레시 토큰
Request Sample
POST /api/v1/auth/refresh { "refreshToken": "eyJ..." }
Response Body
성공 여부응답 코드설명
Success200토큰 갱신 성공
Error401리프레시 토큰 만료 또는 유효하지 않음
Response Sample
// 200 OK { "code": 200, "message": "토큰 갱신 성공", "data": { "accessToken": "eyJ..." } }
POST/auth/logout 로그아웃
설명로그아웃 처리 후 리프레시 토큰을 무효화합니다.
헤더Authorization: Bearer {accessToken}JWT 필요
Path Variable없음
Query String없음
Request Body
없음
Request Sample
POST /api/v1/auth/logout
Response Body
성공 여부응답 코드설명
Success200로그아웃 성공
Error401인증 실패
GET/members/me 마이페이지 조회
설명로그인한 회원의 마이페이지 정보를 조회합니다.
헤더Authorization: Bearer {accessToken}JWT 필요
Path Variable없음 (JWT에서 memberId 추출)
Query String없음
Request Body
없음
Request Sample
GET /api/v1/members/me
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error401인증 실패
Error500서버 내부 오류
Response Sample
// 200 OK { "code": 200, "message": "마이페이지 조회 성공", "data": { "memberId": 1, "email": "user@example.com", "nickname": "득템러", "name": "홍길동", "profileImageUrl": "https://s3.../profile.jpg", "phone": "010-1234-5678", "gender": "MALE", "birth": "1995-04-15", "role": "CONSUMER", "status": 1, "createdAt": "2026-01-12T09:00:00+09:00" } } // 401 Unauthorized { "code": 401, "message": "인증이 필요합니다.", "data": null }
GET/members/me/stats 절약 금액 / 탄소 저감량 통계
설명로그인한 회원의 절약 금액 및 탄소 저감량 통계를 조회합니다.
헤더Authorization: Bearer {accessToken}JWT 필요
Path Variable없음
Query String없음
Request Body
없음
Request Sample
GET /api/v1/members/me/stats
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error401인증 실패
Response Sample
// 200 OK { "code": 200, "message": "통계 조회 성공", "data": { "totalSavedAmount": 32000, "totalCarbonSavedKg": 1.24, "totalOrders": 8 } }
GET/stores 주변 가게 목록 (위치 기반)
설명현재 위치 기반으로 주변 가게 목록을 조회합니다.
헤더없음
Path Variable없음
Query Stringlatitude, longitude, radius, category, sort, page, size
Request Body (Query String)
요청 종류필드 이름필수타입설명
현재 위도latitudeDouble현재 위도
현재 경도longitudeDouble현재 경도
검색 반경radius-Integer반경(m), 기본값 1000
카테고리category-StringBAKERY / RESTAURANT / CAFE / GROCERY / OTHER
정렬 기준sort-Stringdistance (기본) / discount_rate
페이지 번호page-Integer기본값 0
페이지 크기size-Integer기본값 20
Request Sample
GET /api/v1/stores?latitude=37.123&longitude=126.456&radius=1000&sort=distance
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error400위도/경도 누락
Response Sample
// 200 OK { "code": 200, "message": "주변 가게 조회 성공", "data": { "stores": [{ "storeId": 1, "name": "삼미시장 떡집", "thumbnailUrl": "https://s3.../thumb.jpg", "distanceM": 320, "category": "BAKERY", "availableProductCount": 3 }], "hasNext": true } }
GET/stores/{storeId} 가게 상세 조회
설명가게의 상세 정보를 조회합니다.
헤더없음
Path VariablestoreId (Long) — 가게 ID
Query String없음
Request Body
없음
Request Sample
GET /api/v1/stores/1
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error404가게를 찾을 수 없음
Response Sample
// 200 OK { "code": 200, "message": "가게 조회 성공", "data": { "storeId": 1, "name": "삼미시장 떡집", "description": "전통 떡 전문점", "address": "경기도 시흥시 정왕동 ...", "latitude": 37.123, "longitude": 126.456, "phone": "031-000-0000", "images": ["https://s3.../img1.jpg"], "categories": ["BAKERY"], "averageRating": 4.5 } } // 404 Not Found { "code": 404, "message": "가게를 찾을 수 없습니다.", "data": null }
POST/stores 가게 등록 (판매자)
설명판매자가 가게를 등록합니다.
헤더Authorization: Bearer {accessToken}SELLER  Content-Type: multipart/form-data
Path Variable없음
Query String없음
Request Body
요청 종류필드 이름필수타입설명
가게명nameString최대 100자
가게 소개description-String가게 설명
주소addressString최대 255자
위도latitudeDouble가게 위도
경도longitudeDouble가게 경도
전화번호phone-String가게 전화번호
카테고리categoriesListBAKERY / RESTAURANT / CAFE / GROCERY / OTHER
대표 이미지thumbnailFile썸네일 이미지 1장
소개 이미지images-List<File>최대 5장
시루 가맹점 IDsiruStoreId-String시루 연동 확정 후 업데이트TBD
Request Sample
POST /api/v1/stores Content-Type: multipart/form-data { "name": "삼미시장 떡집", "address": "경기도 시흥시 정왕동 ...", "latitude": 37.123, "longitude": 126.456, "categories": ["BAKERY"], "thumbnail": (file) }
Response Body
성공 여부응답 코드설명
Success201가게 등록 성공
Error400입력값 오류
Error403판매자 권한 없음
GET/stores/my 내 가게 조회 (판매자)
설명로그인한 판매자의 가게 정보를 조회합니다.
헤더Authorization: Bearer {accessToken}SELLER
Path Variable없음
Query String없음
Request Body
없음
Request Sample
GET /api/v1/stores/my
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error401인증 실패
Error404등록된 가게 없음
GET/products 주변 마감할인 상품 목록
설명현재 위치 기반으로 주변 마감할인 상품을 조회합니다.
헤더없음
Path Variable없음
Query Stringlatitude, longitude, radius, category, sort, page, size
Request Body (Query String)
요청 종류필드 이름필수타입설명
현재 위도latitudeDouble현재 위도
현재 경도longitudeDouble현재 경도
검색 반경radius-Integer반경(m), 기본값 1000
카테고리category-String카테고리 필터
정렬 기준sort-Stringdistance / discount_rate / pickup_end
페이지 번호page-Integer기본값 0
페이지 크기size-Integer기본값 20
Request Sample
GET /api/v1/products?latitude=37.123&longitude=126.456&sort=pickup_end
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error400위도/경도 누락
Response Sample
// 200 OK { "code": 200, "message": "상품 조회 성공", "data": { "products": [{ "productId": 1, "name": "마감 샌드위치 세트", "originalPrice": 8000, "discountPrice": 4000, "quantityRemaining": 3, "pickupEnd": "20:00", "status": "AVAILABLE", "storeName": "삼미시장 떡집", "distanceM": 320 }], "hasNext": false } }
POST/stores/{storeId}/products 상품 등록 (판매자)
설명판매자가 마감할인 상품을 등록합니다.
헤더Authorization: Bearer {accessToken}SELLER  Content-Type: multipart/form-data
Path VariablestoreId (Long) — 가게 ID
Query String없음
Request Body
요청 종류필드 이름필수타입설명
상품명nameString상품명
상품 설명description-String상품 설명
정가originalPriceInteger정가 (원)
할인가discountPriceInteger할인가 (원)
총 수량quantityTotalInteger판매 수량
픽업 시작pickupStartString픽업 시작 시간 (HH:mm)
픽업 마감pickupEndString픽업 마감 시간 (HH:mm)
판매 날짜availableDateString판매 날짜 (yyyy-MM-dd)
상품 이미지imagesList<File>최소 1장
Request Sample
POST /api/v1/stores/1/products { "name": "마감 샌드위치 세트", "originalPrice": 8000, "discountPrice": 4000, "quantityTotal": 5, "pickupStart": "18:00", "pickupEnd": "20:00", "availableDate": "2026-04-11", "images": [(file)] }
Response Body
성공 여부응답 코드설명
Success201상품 등록 성공
Error400입력값 오류
Error403판매자 권한 없음
Error404가게를 찾을 수 없음
GET/stores/{storeId}/products 가게별 상품 목록
설명특정 가게의 상품 목록을 조회합니다.
헤더없음
Path VariablestoreId (Long) — 가게 ID
Query Stringpage, size
Request Body
없음
Request Sample
GET /api/v1/stores/1/products
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error404가게를 찾을 수 없음
POST/orders 주문 생성
설명소비자가 마감할인 상품을 주문(예약)합니다.
헤더Authorization: Bearer {accessToken}CONSUMER  Content-Type: application/json
Path Variable없음
Query String없음
Request Body
요청 종류필드 이름필수타입설명
상품 IDitems[].productIdLong주문할 상품 ID
주문 수량items[].quantityInteger주문 수량
결제 수단paymentMethodStringSIRU / CARD / CASH시루 TBD
Request Sample
POST /api/v1/orders { "items": [{ "productId": 1, "quantity": 2 }], "paymentMethod": "SIRU" }
Response Body
성공 여부응답 코드설명
Success201주문 성공
Error400입력값 오류
Error409수량 초과 또는 품절
Error500서버 내부 오류
Response Sample
// 201 Created { "code": 201, "message": "주문 성공", "data": { "orderId": 1, "pickupCode": "A1B2", "status": "PENDING", "totalPrice": 8000 } } // 409 Conflict { "code": 409, "message": "남은 수량이 부족합니다.", "data": null }
GET/orders/my 내 주문 목록
설명로그인한 소비자의 주문 목록을 조회합니다.
헤더Authorization: Bearer {accessToken}CONSUMER
Path Variable없음
Query Stringstatus, page, size
Request Body (Query String)
요청 종류필드 이름필수타입설명
주문 상태status-StringPENDING / CONFIRMED / PICKED_UP / CANCELLED
페이지 번호page-Integer기본값 0
페이지 크기size-Integer기본값 20
Request Sample
GET /api/v1/orders/my?status=PICKED_UP&page=0&size=10
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error401인증 실패
PATCH/orders/{orderId}/cancel 주문 취소
설명픽업 전 상태의 주문을 취소합니다.
헤더Authorization: Bearer {accessToken}CONSUMER
Path VariableorderId (Long) — 주문 ID
Query String없음
Request Body
없음
Request Sample
PATCH /api/v1/orders/1/cancel
Response Body
성공 여부응답 코드설명
Success200취소 성공
Error400취소 불가 상태
Error403권한 없음
Error404주문을 찾을 수 없음
PATCH/orders/{orderId}/confirm 픽업 완료 처리 (판매자)
설명판매자가 픽업 코드를 확인하고 주문을 완료 처리합니다.
헤더Authorization: Bearer {accessToken}SELLER  Content-Type: application/json
Path VariableorderId (Long) — 주문 ID
Query String없음
Request Body
요청 종류필드 이름필수타입설명
픽업 코드pickupCodeString소비자 픽업 확인 코드방식 TBD
Request Sample
PATCH /api/v1/orders/1/confirm { "pickupCode": "A1B2" }
Response Body
성공 여부응답 코드설명
Success200픽업 완료 처리 성공
Error400픽업 코드 불일치
Error403권한 없음
POST/payments/siru/callback 시루 결제 웹훅 수신
설명시루 결제 완료 웹훅을 수신합니다.
헤더없음 (시루 서버 발신)
상태TBD — 시루 결제 API 확정 후 업데이트
Response Body
성공 여부응답 코드설명
Success200웹훅 수신 성공
Error400유효하지 않은 요청
POST/reviews 리뷰 작성 (픽업 완료 후)
설명픽업이 완료된 주문에 대해 리뷰를 작성합니다.
헤더Authorization: Bearer {accessToken}CONSUMER  Content-Type: application/json
Path Variable없음
Query String없음
Request Body
요청 종류필드 이름필수타입설명
가게 IDstoreIdLong리뷰 대상 가게 ID
주문 IDorderIdLongPICKED_UP 상태여야 함
별점ratingInteger1~5
리뷰 내용content-String리뷰 텍스트
Request Sample
POST /api/v1/reviews { "storeId": 1, "orderId": 1, "rating": 5, "content": "신선하고 맛있었어요!" }
Response Body
성공 여부응답 코드설명
Success201리뷰 작성 성공
Error400픽업 미완료 주문
Error409이미 작성된 리뷰
Error500서버 내부 오류
Response Sample
// 201 Created { "code": 201, "message": "리뷰 작성 성공", "data": { "reviewId": 1, "rating": 5, "content": "신선하고 맛있었어요!", "createdAt": "2026-04-11T20:30:00+09:00" } } // 409 Conflict { "code": 409, "message": "이미 리뷰를 작성한 주문입니다.", "data": null }
GET/stores/{storeId}/reviews 가게 리뷰 목록
설명특정 가게의 리뷰 목록을 조회합니다.
헤더없음
Path VariablestoreId (Long) — 가게 ID
Query Stringpage, size
Request Body
없음
Request Sample
GET /api/v1/stores/1/reviews?page=0&size=10
Response Body
성공 여부응답 코드설명
Success200조회 성공
Error404가게를 찾을 수 없음
DELETE/reviews/{reviewId} 리뷰 삭제
설명본인이 작성한 리뷰를 삭제합니다.
헤더Authorization: Bearer {accessToken}JWT 필요
Path VariablereviewId (Long) — 리뷰 ID
Query String없음
Request Body
없음
Request Sample
DELETE /api/v1/reviews/1
Response Body
성공 여부응답 코드설명
Success200삭제 성공
Error403권한 없음 (본인 리뷰 아님)
Error404리뷰를 찾을 수 없음