
# 연령 정책 교체

`PUT /v1/age-policy` · 권한 `identity-settings:write`

연령 정책 전체를 기록합니다. `If-Match`은(는) 필수입니다(누락 시 `428`, 일치하지 않으면 `412`). 한 번도 기록되지 않은 정책의 버전은 `"0"`입니다. 규칙: `min_age` 및 국가별 기준 연령은 13-21이어야 합니다. 국가 코드는 ISO 3166-1 alpha-2(대문자)여야 하며 최대 250개 항목입니다. `parental_consent_below`은(는) `null` 또는 1..`min_age`입니다. `store_birthdate`은(는) `mode`이(가) `birthdate`일 때만 `true`이(가) 될 수 있습니다. 정책은 이후 가입에만 적용되며, 기존 사용자는 변경되지 않습니다.

## 요청

JSON 본문(알 수 없는 필드는 `400 unknown_field`(으)로 거부됩니다):

| 필드 | 유형 | 필수 | 설명 |
|---|---|---|---|
| `If-Match` | 헤더 | 예 | 헤더: `GET /v1/age-policy`의 `ETag` 값입니다. |
| `mode` | 문자열 | 예 | `off`, `attestation`(생년월 중립 질문, 값은 저장하지 않음) 또는 `birthdate`. |
| `min_age` | 정수 | 예 | 13-21. |
| `country_min_age` | 객체 | 예 | 국가 코드 → 기준 연령(13-21); 누락된 국가는 `min_age`을 사용합니다. |
| `country_source` | 문자열 | 예 | `ip` 또는 `declared`. |
| `under_age_action` | 문자열 | 예 | `block` 또는 `create_minor`. |
| `parental_consent_below` | 정수 \| null | 아니요 | `null`(보호자 동의 없음) 또는 1..`min_age`. |
| `pending_consent_action` | 문자열 | 예 | `block_sign_in` 또는 `issue_limited`. |
| `store_birthdate` | 불리언 | 예 | `true`은 `mode: birthdate`일 때만 사용합니다. |
| `applies_to` | 문자열 | 예 | `self_signup` 또는 `all`. |

## 응답

정책과 `ETag` 헤더가 포함된 `200 OK`입니다.

```json
{
  "mode": "attestation",
  "min_age": 16,
  "country_min_age": {"DE": 16, "FR": 15, "IT": 14},
  "country_source": "ip",
  "under_age_action": "block",
  "parental_consent_below": null,
  "pending_consent_action": "block_sign_in",
  "store_birthdate": false,
  "applies_to": "self_signup",
  "updated_at": "2026-10-05T09:30:00.123456Z"
}
```

## 토큰

`mode`이(가) `off`이(가) 아닌 동안에는 ID 토큰, 액세스 토큰 및 UserInfo 응답에 요청된 스코프와 관계없이 사용자의 `age_group`(`adult`, `minor` 또는 `unknown`)이 포함되며, 값이 있으면 `parental_consent_status`(`not_required`, `pending`, `granted`, `denied` 또는 `revoked`)도 포함됩니다. `mode: off`이(가) 설정된 경우 두 클레임 모두 발급되지 않습니다. 두 값은 KeenAuth만 기록할 수 있으며(후크와 클레임 템플릿으로는 설정할 수 없음), 변경하려면 `PATCH /v1/users/{user_id}`을(를) 사용하십시오.

`pending_consent_action: block_sign_in` 설정에서는 `parental_consent_status`이(가) `pending`, `denied` 또는 `revoked`인 사용자에게 토큰이 발급되지 않습니다. 인가 요청은 `access_denied`(으)로 끝나며, 토큰 엔드포인트는 인가 코드, 기기 코드 및 리프레시 토큰 grant에 대해 `invalid_grant`(`Parental consent has not been granted.`)으로 응답합니다. 리프레시 토큰은 취소되지 않으며, 동의가 `granted` 상태가 되면 다시 작동합니다. `issue_limited` 설정에서는 토큰이 발급되며, 애플리케이션이 클레임을 기준으로 사용자를 제한합니다.

## 오류

| HTTP | 코드 | 발생 조건 |
|---|---|---|
| 400 | `unknown_field` | 본문에 알 수 없는 필드가 있습니다. |
| 412 | `precondition_failed` | `If-Match`이(가) 현재 버전과 일치하지 않습니다. |
| 415 | `unsupported_media_type` | 콘텐츠 유형이 `application/json`이(가) 아닙니다. |
| 422 | `validation_failed` | 필드가 누락되었거나(`required`) 위의 규칙을 위반합니다. 포인터는 필드를 가리키며, 예: `/country_min_age/DE`. |
| 428 | `precondition_required` | `If-Match` 헤더가 없습니다. |
| 401 | `unauthenticated` | 자격 증명이 없거나 유효하지 않거나 취소되었습니다. |
| 403 | `insufficient_permissions` | 자격 증명에 필요한 권한이 없습니다. |
| 429 | `rate_limited` | 요청 한도를 초과했습니다. `Retry-After` 기간 후 다시 시도하십시오. |
| 503 | `service_unavailable` | 종속 서비스를 일시적으로 사용할 수 없습니다. `Retry-After` 기간 후 다시 시도하십시오. |

## 예시

```bash
curl -X PUT https://api.eu.keenauth.com/v1/age-policy \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "0"' \
  -d '{"mode":"attestation","min_age":16,"country_min_age":{"DE":16,"FR":15},"country_source":"ip","under_age_action":"block","parental_consent_below":null,"pending_consent_action":"block_sign_in","store_birthdate":false,"applies_to":"self_signup"}'
```
