REST API 개요
Base URL은 https://api.payri.kr이고 경로는 /v1/...로 시작하며 OpenAPI 명세는 개발 문서
인증
요청은 Authorization: Bearer <키> 헤더로 인증하고 키 정보는 인증과 API 키에서 확인하며, /v1은 서버 전용이라 브라우저에서는 라이선스 앱 API와 모든 origin에 CORS를 허용하는 API 키 없는 GET /v1/licenses/signing-keys를 호출해요.
공통 규칙
멱등성
라이선스 앱 API를 제외한 모든 POST /v1/... 요청에는 Idempotency-Key가 필요해요.
키는 공백 제거 후 1~255자이며 스토어와 mode 범위에서 24시간 보관하고, HTTP 메서드·경로·본문으로 요청을 구분해요.
| 상황 | 응답 | 할 일 |
|---|---|---|
| 키가 없거나 공백 제거 후 1~255자를 벗어남 | 400 VALIDATION_FAILED (details.fields[0].field는 Idempotency-Key) | 키를 넣어 다시 보내요. |
| 같은 키와 같은 요청 | 저장된 응답과 Idempotent-Replayed: true 헤더 | 저장된 응답을 사용해요. |
| 같은 키와 다른 요청 | 409 IDEMPOTENCY_KEY_CONFLICT | 새 요청에는 새 키를 사용해요. |
| 같은 키의 요청이 처리 중 | 409 IDEMPOTENCY_IN_PROGRESS | 잠시 후 같은 키와 같은 요청으로 다시 보내요. |
검증 실패(400 VALIDATION_FAILED) 또는 5xx 응답 | 저장하거나 재생하지 않아요. | 같은 키와 요청으로 다시 보내면 새로 처리돼요. |
| 네트워크 오류 또는 응답 시간 초과 | — | 같은 키로 재시도해요. |
요청과 응답
- 등록되지 않은 필드를 요청에 보내면
400 VALIDATION_FAILED가 와요. - 리소스 응답의
mode는"live"또는"test"이고, 값이 없는 필드는 생략하지 않고null로 와요. - 금액은 원 단위 정수이며 금액 필드와 함께
currency가 와요.
환경 분리
live·test API 키와 거래 데이터의 차이는 test 모드에서 확인해요.
목록
sort 또는 order를 보내면 400 VALIDATION_FAILED가 와요.
| 필드 | 타입 | 설명 |
|---|---|---|
page | integer | 페이지 번호예요. 1부터 시작해요. |
limit | integer | 페이지 크기예요. 기본값은 20이고 최대 100이에요. |
{
"data": [],
"total": 0,
"page": 1,
"limit": 20
}호출 제한
API 키마다 분당 300회까지 호출할 수 있고, 한도를 넘으면 429 RATE_LIMITED와 초 단위 Retry-After 헤더가 돌아와요.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json
{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "요청이 너무 많아요. 잠시 후 다시 시도해 주세요."
}엔드포인트
키 권한은 권한, 상품 범위 밖 응답은 IP · 상품 제한, 브라우저 라이선스 호출은 라이선스 앱 API에서 확인해요.
결제 세션
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
POST | /v1/checkout/sessions | 결제 세션 생성 | checkout:write | 필수 |
GET | /v1/checkout/sessions/{id} | 결제 세션 조회 | checkout:read | — |
라이선스
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
GET | /v1/licenses | 라이선스 목록 조회 | licenses:read | — |
GET | /v1/licenses/{id} | 라이선스 상세 조회 | licenses:read | — |
라이선스 앱 API
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
POST | /v1/licenses/activate | 라이선스 활성화 | API 키 불필요 | — |
POST | /v1/licenses/deactivate | 라이선스 비활성화 | API 키 불필요 | — |
GET | /v1/licenses/signing-keys | 라이선스 서명 공개키 조회 | API 키 불필요 | — |
POST | /v1/licenses/verify | 라이선스 검증 | API 키 불필요 | — |
명세
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
GET | /v1/openapi.json | 명세 조회 | API 키 불필요 | — |
주문
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
GET | /v1/orders | 주문 목록 조회 | orders:read | — |
GET | /v1/orders/{id} | 주문 상세 조회 | orders:read | — |
POST | /v1/orders/{id}/refund | 주문 환불 | refunds:write | 필수 |
포털 세션
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
POST | /v1/portal-sessions | 구매자 포털 세션 생성 | subscriptions:write | 필수 |
상품
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
GET | /v1/products | 상품 목록 조회 | products:read | — |
GET | /v1/products/{id} | 상품 상세 조회 | products:read | — |
환불 요청
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
GET | /v1/refund-requests | 환불 요청 목록 조회 | refunds:read | — |
GET | /v1/refund-requests/{id} | 환불 요청 상세 조회 | refunds:read | — |
POST | /v1/refund-requests/{id}/approve | 환불 요청 승인 | refunds:write | 필수 |
POST | /v1/refund-requests/{id}/hold | 환불 요청 보류 | refunds:write | 필수 |
POST | /v1/refund-requests/{id}/reject | 환불 요청 거절 | refunds:write | 필수 |
구독
| 메서드 | 경로 | 설명 | 권한 | 멱등 |
|---|---|---|---|---|
GET | /v1/subscriptions | 구독 목록 조회 | subscriptions:read | — |
GET | /v1/subscriptions/{id} | 구독 상세 조회 | subscriptions:read | — |
POST | /v1/subscriptions/{id}/cancel | 구독 해지 | subscriptions:write | 필수 |
GET | /v1/subscriptions/{id}/cancel-preview | 구독 해지 미리보기 | subscriptions:read | — |
Last updated on