# 인증 (Authentication)

## 헤더 인증

모든 FI 엔드포인트(공개 `GET /fi/health` 제외)는 요청마다 두 개의 헤더를 요구합니다.

EN — Every FI endpoint except the public `GET /fi/health` requires two headers per request.

| 헤더 | 설명 |
|---|---|
| `X-Client-Id` | 파트너 클라이언트 ID |
| `X-API-Key` | API 키 평문 — 서버는 BCrypt 해시와 대조 |

```bash
curl -s https://trendy.storydot.kr/superapp/api/fi/whoami \
  -H "X-Client-Id: YOUR_CLIENT_ID" \
  -H "X-API-Key: YOUR_API_KEY"
```

헤더 누락·키 불일치 → `SW2102`(INVALID_API_KEY), 클라이언트 정지 → `SW2101`(PARTNER_CLIENT_SUSPENDED).

## 환경과 키

키는 발급 시 LIVE 또는 SANDBOX 환경에 결속됩니다. 기본 URL은 공유하며 서버가 키의 환경으로 분기합니다.
SANDBOX 키는 실제 주체 조회 코드에 도달하지 않고 결정적 합성 응답만 반환합니다.
현재 환경은 `GET /fi/whoami` 및 점수 응답의 `environment` 필드("LIVE"|"SANDBOX")로 확인합니다.

EN — Keys are bound to LIVE or SANDBOX at issuance. The server branches on the authenticated key's
environment; a SANDBOX key never reaches real-subject lookup code.

## 키 관리 수칙

- **1회 표시**: 발급 시 한 번만 평문 표시(해시만 저장, 재조회 불가 — 분실 시 재발급)
- **시크릿 보관**: 코드/저장소/로그 금지, 시크릿 매니저 사용
- **서버 간 통신 전용**: 브라우저·모바일 앱 내장 금지
- **회전**: 노출 의심 시 즉시 재발급+구키 폐기 요청
- 서버는 인증 성공 시 `last_used_at`을 갱신해 미사용 키를 식별

EN — Shown once at issuance (hash-only storage); keep in a secrets manager; server-to-server only;
rotate on suspected exposure; `last_used_at` is updated on each successful authentication.

## 속도 제한

기본 60 req/min. 초과 시 HTTP 429 + `Retry-After: <seconds>`. 정책은 [errors.md](errors.md).

EN — Default 60 req/min; 429 carries `Retry-After` in seconds.

## 웹훅 서명 키

웹훅 엔드포인트 등록 시 별도의 서명 시크릿이 1회 평문 반환됩니다. API 키와 다른 값이며
`X-HACS-Signature` 검증 전용입니다. 상세: [webhooks.md](webhooks.md).
