합의(Agreements) 도메인 API 엔드포인트
목차
관련 문서
- Auth 도메인 엔드포인트: /domains/common/core-domains/auth/endpoints
- 사용자 온보딩 플로우: /domains/common/core-domains/auth/endpoints#51-회원가입-프로세스
접근 권한 매트릭스
| 엔드포인트 | System Admin | IAM Admin | Service Account | Regular User | 비고 |
|---|---|---|---|---|---|
| POST /v1/agreements/terms | ✓ | ✓ | ✘ | ✘ | |
POST /v1/agreements/terms/{termsId}/translations | ✓ | ✓ | ✘ | ✘ | |
PATCH /v1/agreements/terms/{termsId}/status | ✓ | ✓ | ✘ | ✘ | |
| GET /v1/agreements/terms | ✓ | ✓ | ✓ | ✓ | |
GET /v1/agreements/terms/{termsId} | ✓ | ✓ | ✓ | ✓ | |
| GET /v1/agreements/terms/history | ✓ | ✓ | ✓ | ✓ | |
GET /v1/agreements/users/{userId}/history | ✓ | ✓ | ✓ | 자신만 | |
| POST /v1/agreements/terms/agreement | ✓ | ✓ | ✓ | ✓ | |
| POST /v1/agreements/consents/definitions | ✓ | ✓ | ✘ | ✘ | |
PATCH /v1/agreements/consents/definitions/{definitionId} | ✓ | ✓ | ✘ | ✘ | |
| POST /v1/agreements/consents/users | ✓ | ✓ | ✓ | ✓ | |
PATCH /v1/agreements/consents/users/{userId}/{consentKey} | ✓ | ✓ | ✓ | 자신만 | |
| GET /v1/agreements/consents/definitions | ✓ | ✓ | ✓ | ✓ | |
GET /v1/agreements/consents/users/{userId} | ✓ | ✓ | ✓ | 자신만 | |
| POST /v1/agreements/validate | ✓ | ✓ | ✓ | ✓ | |
| GET /v1/agreements/active | ✓ | ✓ | ✓ | ✓ | |
| POST /v1/agreements/batch | ✓ | ✓ | ✓ | ✓ |
참고:
- ✓: 접근 가능
- ✘: 접근 불가
- (범위 내): 할당된 조직/팀 범위 내에서만 접근 가능
- (자신만): 자신의 데이터에만 접근 가능
약관(Term) 관리 프로세스
합의 도메인의 약관 관리 API는 서비스 이용을 위한 약관의 버전 관리와 활성화 상태 관리, 다국어 지원 및 사용자 동의 이력 관리를 담당합니다.
2.1 약관 생성
- HTTP 메서드: POST
- 경로: /v1/agreements/terms
- Headers:
- Content-Type: application/json
- Authorization: Bearer
{adminToken}
요청 (Request)
{
"title": "서비스 이용약관",
"type": "service",
"required": true,
"defaultLanguage": "ko",
"contentUrl": "https://external-service.com/terms/service/v1.0.0/ko",
"validFrom": 1709251200000,
"validUntil": 1735689599000
}
응답 (Response)
- 성공 응답 (201 Created)
{
"id": 1,
"version": "1.0.0",
"title": "서비스 이용약관",
"type": "service",
"required": true,
"defaultLanguage": "ko",
"status": "DRAFT",
"validFrom": 1709251200000,
"validUntil": 1735689599000,
"createdAt": 1711011600000,
"updatedAt": 1711011600000
}
- 오류 응답 (400 Bad Request - 입력값 오류)
{
"code": 2000,
"message": "BAD_REQUEST",
"detail": "요청 본문이 유효하지 않습니다."
}
- 오류 응답 (401 Unauthorized - 토큰 오류)
{
"code": 2050,
"message": "INVALID_APP_TOKEN",
"detail": "토큰이 유효하지 않습니다"
}
- 오류 응답 (403 Forbidden - 권한 없음)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "요청한 작업에 대한 권한이 없습니다"
}
2.2 약관 번역 추가
- HTTP 메서드: POST
- 경로: /v1/agreements/terms/
{termsId}/translations - Headers:
- Content-Type: application/json
- Authorization: Bearer
{adminToken}
요청 (Request)
{
"language": "en",
"contentUrl": "https://external-service.com/terms/service/v1.0.0/en",
"title": "Terms of Service"
}
응답 (Response)
- 성공 응답 (201 Created)
{
"termsId": 1,
"language": "en",
"title": "Terms of Service",
"createdAt": 1711011900000,
"updatedAt": 1711011900000
}
- 오류 응답 (400 Bad Request - 입력값 오류)
{
"code": 2000,
"message": "BAD_REQUEST",
"detail": "요청 본문이 유효하지 않습니다."
}
- 오류 응답 (404 Not Found - 약관 없음)
{
"code": 2080,
"message": "TERMS_NOT_FOUND",
"detail": "요청한 약관을 찾을 수 없습니다"
}
- 오류 응답 (409 Conflict - 번역 중복)
{
"code": 2081,
"message": "TERMS_ALREADY_EXISTS",
"detail": "해당 언어의 번역이 이미 존재합니다"
}
2.3 약관 활성화
- HTTP 메서드: PATCH
- 경로: /v1/agreements/terms/
{termsId}/status - Headers:
- Content-Type: application/json
- Authorization: Bearer
{adminToken}
요청 (Request)
{
"status": "ACTIVE"
}
응답 (Response)
- 성공 응답 (200 OK)
{
"id": 1,
"version": "1.0.0",
"title": "서비스 이용약관",
"type": "service",
"status": "ACTIVE",
"previousStatus": "DRAFT",
"activatedAt": 1711015200000,
"updatedAt": 1711015200000
}
- 오류 응답 (400 Bad Request - 잘못된 상태값)
{
"code": 2000,
"message": "BAD_REQUEST",
"detail": "유효하지 않은 상태 값입니다."
}
- 오류 응답 (409 Conflict - 활성 약관 중복)
{
"code": 2081,
"message": "TERMS_ALREADY_EXISTS",
"detail": "동일한 유형의 활성화된 약관이 이미 존재합니다."
}
2.4 약관 조회
- HTTP 메서드: GET
- 경로: /v1/agreements/terms/
{termsId} - Headers:
- Accept-Language: ko-KR (기본값) 또는 en-US
- Authorization: Bearer
{accessToken}
응답 (Response)
- 성공 응답 (200 OK)
{
"id": 1,
"version": "1.0.0",
"title": "서비스 이용약관",
"contentUrl": "https://external-service.com/terms/service/v1.0.0/ko",
"type": "service",
"required": true,
"status": "ACTIVE",
"language": "ko",
"availableLanguages": ["ko", "en"],
"validFrom": 1709251200000,
"validUntil": 1735689599000,
"createdAt": 1711011600000,
"updatedAt": 1711015200000,
"activatedAt": 1711015200000
}
- 오류 응답 (404 Not Found - 약관 없음)
{
"code": 2080,
"message": "TERMS_NOT_FOUND",
"detail": "요청한 약관을 찾을 수 없습니다"
}
2.5 약관 목록 조회
- HTTP 메서드: GET
- 경로: /v1/agreements/terms
- Headers:
- Accept-Language: de-DE (기본값), ko-KR, en-US 등
- Authorization: Bearer {appToken 또는 accessToken}
- Query Parameters:
- status: 약관 상태 (선택 사항, 예: 'ACTIVE', 'DRAFT', 'INACTIVE', 'EXPIRED')
- type: 약관 유형 (선택 사항, 예: 'service', 'privacy', 'marketing')
- page: 페이지 번호 (기본값: 1)
- pageSize: 페이지 크기 (기본값: 10)
응답 (Response)
- 성공 응답 (200 OK)
{
"items": [
{
"id": 1,
"version": "1.0.0",
"title": "Ich stimme den Nutzungsbedingungen gemäß der DiGAV § 4 Abs. 2 zu.",
"contentUrl": "https://external-service.com/terms/service/v1.0.0/de",
"type": "service",
"required": true,
"status": "ACTIVE",
"language": "de",
"availableLanguages": ["de", "ko", "en"],
"validFrom": 1709251200000,
"validUntil": 1735689599000,
"createdAt": 1711011600000,
"updatedAt": 1711015200000,
"activatedAt": 1711015200000
},
{
"id": 2,
"version": "1.1.0",
"title": "Ich erlaube die Verarbeitung der zu der dauerhaften Gewährleistung der technischen Funktionsfähigkeit, der Nutzerfreundlichkeit und der Weiterentwicklung der digitalen Gesundheitsanwendung. (optional)",
"contentUrl": "https://external-service.com/terms/privacy/v1.1.0/de",
"type": "privacy",
"required": false,
"status": "ACTIVE",
"language": "de",
"availableLanguages": ["de", "ko", "en"],
"validFrom": 1711929600000,
"validUntil": null,
"createdAt": 1711929600000,
"updatedAt": 1711929600000,
"activatedAt": 1711929600000
}
],
"metadata": {
"totalCount": 2,
"currentPage": 1,
"pageSize": 10,
"totalPages": 1
}
}
2.6 약관 버전 이력 조회
- HTTP 메서드: GET
- 경로: /v1/agreements/terms/history
- Headers:
- Accept-Language: ko-KR (기본값) 또는 en-US
- Authorization: Bearer
{token}
- Query Parameters:
- type: 약관 유형 (필수, 예: 'service', 'privacy', 'marketing')
응답 (Response)
- 성공 응답 (200 OK)
{
"type": "service",
"currentVersion": "1.0.0",
"versions": [
{
"id": 1,
"version": "1.0.0",
"title": "서비스 이용약관",
"status": "ACTIVE",
"validFrom": 1709251200000,
"validUntil": 1735689599000,
"createdAt": 1711011600000,
"activatedAt": 1711015200000
}
]
}
2.7 사용자 약관 동의 이력 조회
- HTTP 메서드: GET
- 경로: /v1/agreements/users/
{userId}/history - Headers:
- Authorization: Bearer
{accessToken}
- Authorization: Bearer
응답 (Response)
- 성공 응답 (200 OK)
{
"userId": "user_123",
"agreements": [
{
"termsId": 1,
"version": "1.0.0",
"title": "서비스 이용약관",
"type": "service",
"isAgreed": true,
"agreedAt": 1711011600000
}
]
}
- 오류 응답 (403 Forbidden - 권한 없음)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 동의 이력을 조회할 권한이 없습니다"
}
동의(Consent) 관리 프로세스
합의 도메인의 동의 관리 API는 데이터 처리 동의 항목 정의와 사용자 동의 상태를 관리하고 검증합니다.
3.1 동의 항목 정의 생성
- HTTP 메서드: POST
- 경로: /v1/agreements/consents/definitions
- Headers:
- Content-Type: application/json
- Authorization: Bearer
{adminToken}
요청 (Request)
{
"key": "dataProcessingForImprovement",
"title": "데이터 처리 동의",
"description": "서비스 개선을 위한 데이터 처리에 동의합니다",
"purpose": "서비스 개선",
"scope": "사용자 활동 데이터",
"required": false
}
응답 (Response)
- 성공 응답 (201 Created)
{
"id": 1,
"key": "dataProcessingForImprovement",
"title": "데이터 처리 동의",
"description": "서비스 개선을 위한 데이터 처리에 동의합니다",
"purpose": "서비스 개선",
"scope": "사용자 활동 데이터",
"required": false,
"createdAt": 1711011600000,
"updatedAt": 1711011600000
}
- 오류 응답 (400 Bad Request - 입력값 오류)
{
"code": 2000,
"message": "BAD_REQUEST",
"detail": "요청 본문이 유효하지 않습니다."
}
- 오류 응답 (409 Conflict - 중복 키)
{
"code": 2090,
"message": "CONSENT_ALREADY_EXISTS",
"detail": "동일한 키를 가진 동의 항목이 이미 존재합니다"
}
3.2 동의 항목 정의 업데이트
- HTTP 메서드: PATCH
- 경로: /v1/agreements/consents/definitions/
{definitionId} - Headers:
- Content-Type: application/json
- Authorization: Bearer
{adminToken}
요청 (Request)
{
"title": "데이터 처리 및 분석 동의",
"description": "서비스 개선 및 분석을 위한 데이터 처리에 동의합니다",
"purpose": "서비스 개선 및 분석",
"scope": "사용자 활동 데이터, 사용 패턴"
}
응답 (Response)
- 성공 응답 (200 OK)
{
"id": 1,
"key": "dataProcessingForImprovement",
"title": "데이터 처리 및 분석 동의",
"description": "서비스 개선 및 분석을 위한 데이터 처리에 동의합니다",
"purpose": "서비스 개선 및 분석",
"scope": "사용자 활동 데이터, 사용 패턴",
"required": false,
"createdAt": 1711011600000,
"updatedAt": 1711015200000
}
- 오류 응답 (404 Not Found - 동의 항목 없음)
{
"code": 2091,
"message": "CONSENT_NOT_FOUND",
"detail": "요청한 동의 항목을 찾을 수 없습니다"
}
3.3 사용자 동의 상태 기록
- HTTP 메서드: POST
- 경로: /v1/agreements/consents/users
- Headers:
- Content-Type: application/json
- Authorization: Bearer
{accessToken}
요청 (Request)
{
"userId": "user_123",
"consentKey": "dataProcessingForImprovement",
"isAgreed": true
}
응답 (Response)
- 성공 응답 (201 Created)
{
"userId": "user_123",
"consentKey": "dataProcessingForImprovement",
"isAgreed": true,
"agreedAt": 1711011600000
}
- 오류 응답 (400 Bad Request - 잘못된 동의 키)
{
"code": 2092,
"message": "INVALID_CONSENT_KEY",
"detail": "유효하지 않은 동의 항목 키입니다"
}
3.4 사용자 동의 상태 업데이트
- HTTP 메서드: PATCH
- 경로: /v1/agreements/consents/users/
{userId}/{consentKey} - Headers:
- Content-Type: application/json
- Authorization: Bearer
{accessToken}
요청 (Request)
{
"isAgreed": false
}
응답 (Response)
- 성공 응답 (200 OK)
{
"userId": "user_123",
"consentKey": "dataProcessingForImprovement",
"isAgreed": false,
"agreedAt": null,
"updatedAt": 1711015200000
}
- 오류 응답 (403 Forbidden - 권한 없음)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 동의 상태를 변경할 권한이 없습니다"
}
- 오류 응답 (404 Not Found - 동의 상태 없음)
{
"code": 2093,
"message": "USER_CONSENT_NOT_FOUND",
"detail": "요청한 사용자의 동의 상태를 찾을 수 없습니다"
}
3.5 동의 항목 정의 목록 조회
- HTTP 메서드: GET
- 경로: /v1/agreements/consents/definitions
- Headers:
- Content-Type: application/json
- Authorization: Bearer
{accessToken}
- Query Parameters:
- required: 필수 여부 (선택 사항, 예: 'true', 'false')
- page: 페이지 번호 (기본값: 1)
- pageSize: 페이지 크기 (기본값: 10)
응답 (Response)
- 성공 응답 (200 OK)
{
"items": [
{
"id": 1,
"key": "dataProcessingForImprovement",
"title": "데이터 처리 및 분석 동의",
"description": "서비스 개선 및 분석을 위한 데이터 처리에 동의합니다",
"purpose": "서비스 개선 및 분석",
"scope": "사용자 활동 데이터, 사용 패턴",
"required": false,
"createdAt": 1711011600000,
"updatedAt": 1711015200000
},
{
"id": 2,
"key": "termsOfServiceDiGAV",
"title": "DiGAV § 4 Abs. 2에 따른 이용 약관 동의",
"description": "DiGAV § 4 Abs. 2에 따른 이용 약관에 동의합니다",
"purpose": "서비스 이용",
"scope": "사용자 정보",
"required": true,
"createdAt": 1711011600000,
"updatedAt": 1711011600000
}
],
"metadata": {
"totalCount": 2,
"currentPage": 1,
"pageSize": 10,
"totalPages": 1
}
}
3.6 사용자 동의 상태 목록 조회
- HTTP 메서드: GET
- 경로: /v1/agreements/consents/users/
{userId} - Headers:
- Content-Type: application/json
- Authorization: Bearer
{accessToken}
응답 (Response)
- 성공 응답 (200 OK)
{
"userId": "user_123",
"consents": [
{
"key": "dataProcessingForImprovement",
"title": "데이터 처리 및 분석 동의",
"isAgreed": false,
"required": false,
"agreedAt": null,
"updatedAt": 1711015200000
},
{
"key": "termsOfServiceDiGAV",
"title": "DiGAV § 4 Abs. 2에 따른 이용 약관 동의",
"isAgreed": true,
"required": true,
"agreedAt": 1711011600000,
"updatedAt": 1711011600000
}
]
}
- 오류 응답 (403 Forbidden - 권한 없음)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 동의 상태를 조회할 권한이 없습니다"
}
3.7 합의 상태 검증
- HTTP 메서드: POST
- 경로: /v1/agreements/validate
- Headers:
- Content-Type: application/json
- Authorization: Bearer
{accessToken}
요청 (Request)
{
"userId": "user_123",
"requiredConsents": ["termsOfServiceDiGAV"],
"requiredTermsTypes": ["service"]
}
응답 (Response)
- 성공 응답 (200 OK)
{
"userId": "user_123",
"validated": true,
"missingTerms": [],
"missingConsents": []
}
- 실패 응답 (검증 실패, 200 OK)
{
"userId": "user_123",
"validated": false,
"missingTerms": [
{
"type": "privacy",
"title": "개인정보 처리방침",
"required": true
}
],
"missingConsents": [
{
"key": "marketingConsent",
"title": "마케팅 정보 수신 동의",
"required": false
}
]
}
통합 프로세스
합의 도메인은 약관과 동의를 통합 관리하기 위한 API를 제공합니다.
4.1 모든 활성 약관 및 동의 항목 조회
- HTTP 메서드: GET
- 경로: /v1/agreements/active
- Headers:
- Accept-Language: ko-KR (기본값) 또는 en-US
- Authorization: Bearer
{accessToken}
응답 (Response)
- 성공 응답 (200 OK)
{
"terms": [
{
"id": 1,
"version": "1.0.0",
"title": "서비스 이용약관",
"contentUrl": "https://external-service.com/terms/service/v1.0.0/ko",
"type": "service",
"required": true,
"status": "ACTIVE",
"language": "ko",
"availableLanguages": ["ko", "en"],
"orderIndex": 0
},
{
"id": 2,
"version": "1.1.0",
"title": "개인정보 처리방침",
"contentUrl": "https://external-service.com/terms/privacy/v1.1.0/ko",
"type": "privacy",
"required": true,
"status": "ACTIVE",
"language": "ko",
"availableLanguages": ["ko", "en", "de"],
"orderIndex": 1
}
],
"consents": [
{
"key": "dataProcessingForImprovement",
"title": "데이터 처리 및 분석 동의",
"description": "서비스 개선 및 분석을 위한 데이터 처리에 동의합니다",
"purpose": "서비스 개선 및 분석",
"scope": "사용자 활동 데이터, 사용 패턴",
"required": false,
"orderIndex": 2
},
{
"key": "termsOfServiceDiGAV",
"title": "DiGAV § 4 Abs. 2에 따른 이용 약관 동의",
"description": "DiGAV § 4 Abs. 2에 따른 이용 약관에 동의합니다",
"purpose": "서비스 이용",
"scope": "사용자 정보",
"required": true,
"orderIndex": 3
}
]
}
4.2 약관 및 동의 상태 일괄 기록
- HTTP 메서드: POST
- 경로: /v1/agreements/batch
- Headers:
- Content-Type: application/json
- Authorization: Bearer
{accessToken}
요청 (Request)
{
"userId": "user_123",
"termsAgreements": [
{
"termsId": 1,
"isAgreed": true
},
{
"termsId": 2,
"isAgreed": true
}
],
"consentAgreements": [
{
"consentKey": "dataProcessingForImprovement",
"isAgreed": true
},
{
"consentKey": "termsOfServiceDiGAV",
"isAgreed": true
}
]
}
응답 (Response)
- 성공 응답 (200 OK)
{
"userId": "user_123",
"timestamp": 1711015200000,
"termsAgreements": [
{
"termsId": 1,
"isAgreed": true,
"agreedAt": 1711015200000
},
{
"termsId": 2,
"isAgreed": true,
"agreedAt": 1711015200000
}
],
"consentAgreements": [
{
"consentKey": "dataProcessingForImprovement",
"isAgreed": true,
"agreedAt": 1711015200000
},
{
"consentKey": "termsOfServiceDiGAV",
"isAgreed": true,
"agreedAt": 1711015200000
}
],
"requiredTermsComplete": true,
"requiredConsentsComplete": true
}
- 오류 응답 (400 Bad Request - 필수 항목 동의 누락)
{
"code": 2095,
"message": "REQUIRED_AGREEMENT_MISSING",
"detail": "필수 약관 또는 동의 항목에 대한 동의가 누락되었습니다",
"missingRequired": {
"terms": [
{
"id": 2,
"type": "privacy",
"title": "개인정보 처리방침"
}
],
"consents": []
}
}
오류 코드
합의 도메인 API에서 사용하는 주요 오류 코드는 다음과 같습니다:
| HTTP 상태 코드 | 오류 코드 | 메시지 | 설명 | 대응 방법 |
|---|---|---|---|---|
| 500 | 2000 | SERVER_ERROR | 서버 내부 오류 | 서버 로그를 확인하고 시스템 관리자에게 문의하세요. |
| 401 | 2050 | INVALID_APP_TOKEN | 유효하지 않은 토큰입니다 | 올바른 토큰으로 다시 요청하거나 재로그인하세요. |
| 403 | 2060 | PERMISSION_DENIED | 요청한 작업에 대한 권한이 없습니다 | 필요한 권한을 확인하고 적절한 권한을 가진 계정으로 요청하세요. |
| 404 | 2080 | TERMS_NOT_FOUND | 약관을 찾을 수 없습니다 | 약관 ID를 확인하고 다시 시도하세요. |
| 409 | 2081 | TERMS_ALREADY_EXISTS | 이미 존재하는 약관입니다 | 중복 여부를 확인하고 다시 시도하세요. |
| 409 | 2090 | CONSENT_ALREADY_EXISTS | 이미 존재하는 동의 항목입니다 | 동의 항목 키를 확인하고 다시 시도하세요. |
| 404 | 2091 | CONSENT_NOT_FOUND | 동의 항목을 찾을 수 없습니다 | 동의 항목 ID를 확인하고 다시 시도하세요. |
| 400 | 2092 | INVALID_CONSENT_KEY | 유효하지 않은 동의 항목 키입니다 | 유효한 동의 항목 키를 사용하세요. |
| 404 | 2093 | USER_CONSENT_NOT_FOUND | 사용자 동의 상태를 찾을 수 없습니다 | 사용자 ID와 동의 항목 키를 확인하세요. |
| 400 | 2094 | VALIDATION_FAILED | 합의 상태 검증에 실패했습니다 | 필요한 약관 및 동의 항목을 확인하세요. |
| 400 | 2095 | REQUIRED_AGREEMENT_MISSING | 필수 약관 또는 동의 항목에 대한 동의가 누락되었습니다 | 응답에서 제공하는 누락된 항목을 확인하고 동의를 요청하세요. |
변경 이력
| 버전 | 날짜 | 작성자 | 변경 내용 |
|---|---|---|---|
| 0.1.0 | 2025-05-08 | bok@weltcorp.com | 최초 작성 (약관 및 동의 도메인 통합 API 문서) |