인증
pk_ / sk_ 키, Origin 허용 목록, scope, 키 교체와 폐기
모든 요청은 Authorization: Bearer <키> 헤더로 인증합니다. 키는 콘솔에서 앱 단위로 발급하며, 두 종류가 있습니다.
pk_ 공개 키 | sk_ 비밀 키 | |
|---|---|---|
| 사용 위치 | 브라우저 | 서버 전용 |
| 호출 가능한 API | POST /v1/issue, POST /v1/verify만 | 모든 공개 API |
Origin 헤더 | 필수, 허용 목록과 정확히 일치해야 함 | 검사하지 않음 |
| 가질 수 있는 scope | otp:issue, otp:verify만 | 아래 표의 모든 scope |
키가 없거나 형식이 잘못됐거나 비활성(폐기·만료)이면 401 UNAUTHORIZED, 권한(scope·Origin)이 맞지 않으면 403 FORBIDDEN입니다. 인증 확인에 필요한 내부 의존성이 일시적으로 불가하면 503 SERVICE_UNAVAILABLE이 올 수 있습니다.
sk_ 비밀 키 (서버)
sk_ 키는 서버에서만 사용하세요. 브라우저나 모바일 앱 번들에 넣으면 누구나 키를 꺼내 발송·조회 API를 호출할 수 있습니다.
curl "https://api.k-otp.dev/v1/balance" \
-H "Authorization: Bearer $KOTP_SECRET_KEY"pk_ 공개 키 (브라우저)
pk_ 키는 웹 페이지에서 직접 발급·검증을 호출할 때 사용합니다. 키 값이 공개되는 것을 전제로 하므로 다음 제약이 항상 적용됩니다.
- 호출할 수 있는 API는
POST /v1/issue,POST /v1/verify뿐입니다. 다른 API는403입니다. - 모든 요청에
Origin헤더가 있어야 하며, 키에 등록한 허용 Origin 목록 중 하나와 정확히 일치해야 합니다. 없거나 일치하지 않으면403입니다. - 와일드카드는 지원하지 않습니다.
https://example.com과https://www.example.com,http://localhost:3000과http://localhost:5173은 모두 서로 다른 Origin이므로 각각 등록해야 합니다. pk_키에는otp:issue,otp:verify외의 scope(*포함)를 부여할 수 없습니다. 그런 키는 인증 단계에서 거절됩니다.
브라우저는 Origin 헤더를 자동으로 붙이므로 코드에서 따로 설정할 필요는 없습니다.
// https://app.example.com 에서 실행되는 코드. 이 Origin이 키의 허용 목록에 있어야 합니다.
const res = await fetch("https://api.k-otp.dev/v1/issue", {
method: "POST",
headers: {
Authorization: "Bearer pk_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({ phoneNumber: "01012345678", purpose: "signup" }),
});pk_ 키로도 발송(크레딧 차감)이 가능합니다. 봇 방어나 사용자별 요청 제한을 직접 적용해야 한다면,
브라우저가 아니라 여러분의 서버에서 sk_ 키로 발급을 호출하는 구성을 권장합니다.
Scope
키에는 scope가 부여되며, 각 API는 필요한 scope를 가진 키만 허용합니다. "대체 허용"에 있는 scope를 가진 키도 해당 API를 호출할 수 있습니다. *는 모든 scope를 만족합니다(sk_ 키 전용).
| API | 필요 scope | 대체 허용 | pk_ |
|---|---|---|---|
POST /v1/issue | otp:issue | otp:send, * | 가능 |
POST /v1/verify | otp:verify | otp:read, * | 가능 |
GET /v1/status | otp:status | otp:read, * | 불가 |
GET /v1/issues, GET /v1/issues/{issueId} | otp:dashboard:read | otp:read, * | 불가 |
GET /v1/credit-ledger | otp:ledger:read | otp:dashboard:read, otp:read, * | 불가 |
GET /v1/balance | otp:balance | * | 불가 |
GET /v1/templates, GET /v1/templates/{templateId} | otp:templates | otp:read, * | 불가 |
키에는 필요한 최소한의 scope만 부여하세요. 예를 들어 발급·검증만 하는 서버라면 otp:issue, otp:verify면 충분합니다.
키 교체와 폐기
키가 유출됐거나 주기적으로 교체하려면 다음 순서를 따르세요.
- 콘솔에서 같은 앱에 새 키를 발급합니다. 같은 앱의 키는 같은 크레딧 지갑과 발급 이력을 공유하므로 데이터 이전은 필요 없습니다.
- 서비스 설정(환경 변수 등)을 새 키로 바꿔 배포합니다.
pk_키라면 허용 Origin 목록도 동일하게 등록했는지 확인하세요. - 새 키로 정상 동작하는 것을 확인한 뒤 콘솔에서 기존 키를 폐기합니다.
폐기가 모든 요청에 반영되기까지 최대 약 60초가 걸릴 수 있습니다. 이 시간 동안은 폐기한 키로 보낸 요청이 여전히 성공할 수 있습니다. 새로 발급한 키도 사용 가능해지기까지 몇 초가 걸릴 수 있습니다.