{"components":{"schemas":{"ApiError":{"properties":{"code":{"description":"문제를 구분하는 오류 코드를 알려줘요.","example":"VALIDATION_FAILED","type":"string"},"details":{"description":"검증에 실패한 필드나 추가 원인을 설명해요.","example":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"oneOf":[{"additionalProperties":true,"description":"VALIDATION_FAILED 오류에서 필드별 검증 문제를 알려줘요.","example":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"not":{"required":["required"]},"properties":{"fields":{"description":"문제가 있는 필드와 원인이에요.","items":{"properties":{"field":{"description":"검증에 실패한 필드 이름이에요.","type":"string"},"message":{"description":"필드 값이 올바르지 않은 이유예요.","type":"string"}},"required":["field","message"],"type":"object"},"type":"array"}},"required":["fields"],"type":"object"},{"additionalProperties":true,"description":"API_KEY_SCOPE_MISSING 오류에서 필요한 권한을 알려줘요.","example":{"required":["orders:read"]},"not":{"required":["fields"]},"properties":{"required":{"description":"요청에 필요한 API 키 권한 목록이에요.","items":{"type":"string"},"type":"array"}},"required":["required"],"type":"object"},{"additionalProperties":true,"description":"그 밖의 오류가 제공하는 추가 정보를 담아요.","example":{"retryable":true},"not":{"anyOf":[{"required":["fields"]},{"required":["required"]}]},"type":"object"}]},"message":{"description":"오류 원인과 해결 방법을 한국어로 설명해요.","example":"요청 필드를 확인해 주세요.","type":"string"},"statusCode":{"description":"HTTP 상태 코드를 알려줘요.","example":400,"type":"number"}},"required":["statusCode","code","message"],"type":"object"},"CreatePortalSessionV1Dto":{"properties":{"buyerEmail":{"description":"구매자 이메일로 활성 구독을 찾아요.","example":"buyer@example.com","format":"email","type":"string"},"returnUrl":{"description":"포털에서 돌아갈 때 사용할 URL이에요.","example":"https://shop.example.com/account","type":"string"},"subscriptionId":{"description":"포털 세션을 만들 구독 식별자예요.","example":"sub_123","type":"string"}},"type":"object"},"V1BlockedReason":{"properties":{"code":{"description":"즉시 해지가 차단된 이유 코드예요.","enum":["SUBSCRIPTION_REFUND_SETTLED","REFUND_REQUEST_PENDING","ALREADY_ENDED"],"example":"REFUND_REQUEST_PENDING","type":"string"},"message":{"description":"즉시 해지가 차단된 이유예요.","example":"처리 중인 환불 요청이 있어요.","type":"string"}},"required":["code","message"],"type":"object"},"V1CancelBreakdownItem":{"properties":{"amount":{"description":"해당 주문에서 환불할 금액이에요.","example":5000,"type":"number"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"orderId":{"description":"환불 계산 대상 주문 식별자예요.","example":"ord_123","type":"string"}},"required":["orderId","amount","currency"],"type":"object"},"V1CancelPeriodEndPreview":{"properties":{"effectiveAt":{"description":"기간 종료 해지 효력이 발생할 시각이에요.","example":"2026-11-01T00:00:00.000Z","type":"string"}},"required":["effectiveAt"],"type":"object"},"V1CancelPreviewResponse":{"properties":{"immediate":{"allOf":[{"$ref":"#/components/schemas/V1ImmediateCancelPreview"}],"description":"즉시 해지 미리보기예요."},"mode":{"description":"test 또는 live 구독 환경을 알려줘요.","enum":["live","test"],"example":"live","type":"string"},"pendingRefundRequest":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1RefundRequestResponse"}],"description":"처리 중인 환불 요청 정보예요."},{"type":"null"}],"description":"처리 중인 환불 요청 정보예요."},"periodEnd":{"allOf":[{"$ref":"#/components/schemas/V1CancelPeriodEndPreview"}],"description":"기간 종료 해지 미리보기예요."}},"required":["mode","periodEnd","immediate","pendingRefundRequest"],"type":"object"},"V1CancelResultResponse":{"properties":{"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"refundAmount":{"description":"즉시 환불한 금액이에요.","example":0,"type":"number"},"refundOrderId":{"description":"즉시 환불한 주문 식별자예요.","example":null,"type":["string","null"]},"refundedOrderIds":{"description":"해지 처리 중 환불한 주문 식별자 목록이에요.","example":["ord_123"],"items":{"type":"string"},"type":"array"},"subscription":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionResponse"}],"description":"해지 후 구독 정보예요."},"timing":{"description":"해지 시점이에요.","enum":["period_end","immediate"],"example":"period_end","type":"string"}},"required":["subscription","refundOrderId","refundAmount","currency","refundedOrderIds","timing"],"type":"object"},"V1CancelSubscriptionDto":{"properties":{"reason":{"description":"해지 사유예요.","example":"서비스 이용을 중단해요.","type":"string"},"timing":{"description":"기간 종료 시점 또는 즉시 해지 시점을 지정해요.","enum":["period_end","immediate"],"example":"period_end","type":"string"}},"required":["timing"],"type":"object"},"V1CheckoutCustomer":{"properties":{"email":{"description":"결제 구매자의 이메일 주소예요.","example":"buyer@example.com","type":["string","null"]},"name":{"description":"결제 구매자의 이름이에요.","example":"홍길동","type":["string","null"]},"phone":{"description":"결제 구매자의 연락처예요.","example":"01012345678","type":["string","null"]}},"required":["name","email","phone"],"type":"object"},"V1CheckoutCustomerDto":{"properties":{"email":{"description":"결제 구매자의 이메일 주소예요.","example":"buyer@example.com","type":"string"},"name":{"description":"결제 구매자의 이름이에요.","example":"홍길동","type":"string"},"phone":{"description":"결제 구매자의 연락처예요.","example":"01012345678","type":"string"}},"type":"object"},"V1CheckoutSessionResponse":{"properties":{"cancelUrl":{"description":"결제 취소 후 이동할 URL이에요.","example":null,"type":["string","null"]},"createdAt":{"description":"세션이 생성된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"customer":{"allOf":[{"$ref":"#/components/schemas/V1CheckoutCustomer"}],"description":"세션에 사전 입력한 구매자 정보예요."},"expiresAt":{"description":"세션 생성 후 30분이 되는 만료 시각이에요.","example":"2026-10-15T00:30:00.000Z","type":"string"},"id":{"description":"결제 세션 식별자예요.","example":"cs_123","type":"string"},"metadata":{"description":"요청 때 전달한 메타데이터예요.","example":{"campaign":"fall"},"type":["object","null"]},"mode":{"description":"test 또는 live 결제 환경을 알려줘요.","enum":["live","test"],"example":"test","type":"string"},"orderId":{"description":"결제가 완료된 주문 식별자예요.","example":null,"type":["string","null"]},"productId":{"description":"상품 식별자예요.","example":"prod_123","type":"string"},"status":{"description":"결제 세션 상태예요.","enum":["open","completed","expired"],"example":"open","type":"string"},"successUrl":{"description":"결제 완료 후 이동할 URL이에요.","example":null,"type":["string","null"]},"url":{"description":"구매자가 열 결제 페이지 URL이에요.","example":"https://payri.kr/checkout/cs_123","type":"string"}},"required":["id","mode","productId","status","orderId","customer","metadata","successUrl","cancelUrl","expiresAt","createdAt","url"],"type":"object"},"V1CreateCheckoutSessionDto":{"properties":{"cancelUrl":{"description":"결제가 취소된 뒤 구매자를 돌려보낼 URL이에요.","example":"https://shop.example.com/cancel","type":"string"},"customer":{"allOf":[{"$ref":"#/components/schemas/V1CheckoutCustomerDto"}],"description":"구매자 사전 입력 정보예요."},"interval":{"description":"구독 상품의 결제 주기예요.","enum":["monthly","yearly"],"example":"monthly","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"description":"결제 후 웹훅과 조회 응답에서 받을 문자열 메타데이터예요.","example":{"campaign":"fall"},"type":"object"},"planId":{"description":"구독 상품의 플랜 식별자예요.","example":"plan_basic","type":"string"},"productId":{"description":"결제할 상품 식별자예요.","example":"prod_123","type":"string"},"successUrl":{"description":"결제 완료 후 구매자를 돌려보낼 URL이에요.","example":"https://shop.example.com/complete","type":"string"}},"required":["productId"],"type":"object"},"V1ImmediateCancelPreview":{"properties":{"blockedReason":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1BlockedReason"}],"description":"즉시 해지가 불가능한 이유예요."},{"type":"null"}],"description":"즉시 해지가 불가능한 이유예요."},"breakdown":{"description":"주문별 환불 금액 내역이에요.","items":{"$ref":"#/components/schemas/V1CancelBreakdownItem"},"type":"array"},"clawback":{"description":"연간 할인 환수 금액이에요.","example":0,"type":"number"},"clawbackCurrency":{"description":"환수 금액 통화예요.","enum":["KRW"],"example":"KRW","type":"string"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"deduction":{"description":"환불액에서 차감할 금액이에요.","example":0,"type":"number"},"deductionCap":{"description":"차감할 수 있는 최대 금액이에요.","example":0,"type":"number"},"deductionCapCurrency":{"description":"차감 한도 통화예요.","enum":["KRW"],"example":"KRW","type":"string"},"deductionCurrency":{"description":"차감 금액 통화예요.","enum":["KRW"],"example":"KRW","type":"string"},"fullRefund":{"description":"전액 환불인지 알려줘요.","example":false,"type":"boolean"},"penalty":{"description":"위약금 금액이에요.","example":0,"type":"number"},"penaltyCurrency":{"description":"위약금 통화예요.","enum":["KRW"],"example":"KRW","type":"string"},"reason":{"description":"환불 계산 사유예요.","enum":["initial_full","statutory_full","renewal_full","prorated","past_due","nothing_refundable"],"example":"prorated","type":"string"},"refundAmount":{"description":"즉시 해지 시 환불 예정 금액이에요.","example":5000,"type":"number"},"requiresApproval":{"description":"환불 요청의 판매자 승인이 필요한지 알려줘요.","example":false,"type":"boolean"},"statutory":{"description":"법정 환불 기준 적용 여부예요.","example":false,"type":"boolean"},"totalDays":{"description":"환불 계산에 사용하는 전체 일수예요.","example":30,"type":"number"},"usedDays":{"description":"구독 시작 후 사용한 일수예요.","example":5,"type":"number"}},"required":["refundAmount","currency","fullRefund","reason","breakdown","deduction","deductionCurrency","penalty","penaltyCurrency","clawback","clawbackCurrency","deductionCap","deductionCapCurrency","usedDays","totalDays","statutory","requiresApproval","blockedReason"],"type":"object"},"V1LicenseActivateRequestDto":{"properties":{"key":{"description":"활성화할 라이선스 키예요.","example":"PAYRI-ABCDE-FGHIJ-KLMNP-QRSTU","type":"string"},"label":{"description":"기기 이름이에요.","example":"내 컴퓨터","type":"string"},"nonce":{"description":"응답 위조와 재전송을 확인할 nonce예요. hex 또는 base64로 보내고, 디코딩한 값은 16바이트 이상이어야 해요. 32바이트 hex를 권장해요.","example":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","minLength":22,"pattern":"^(?:(?:[A-Fa-f0-9]{2}){16,}|[A-Za-z0-9+/_-]{22,}={0,2})$","type":"string"},"productId":{"description":"라이선스가 연결된 상품 식별자예요.","example":"prod_123","type":"string"}},"required":["key","productId","nonce"],"type":"object"},"V1LicenseActivation":{"properties":{"activatedAt":{"description":"활성화가 시작된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"deactivatedAt":{"description":"활성화가 해제된 시각이에요.","example":null,"type":["string","null"]},"id":{"description":"활성화 식별자예요.","example":"act_123","type":"string"},"label":{"description":"앱이 지정한 기기 이름이에요.","example":"내 컴퓨터","type":["string","null"]},"lastVerifiedAt":{"description":"마지막 검증 시각이에요.","example":null,"type":["string","null"]}},"required":["id","activatedAt","lastVerifiedAt","deactivatedAt","label"],"type":"object"},"V1LicenseAppActivation":{"properties":{"activatedAt":{"description":"활성화가 시작된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"deactivatedAt":{"description":"비활성화 시각이에요.","example":null,"type":["string","null"]},"id":{"description":"서버가 발급한 활성화 식별자예요.","example":"act_123","type":"string"},"label":{"description":"활성화할 기기의 이름이에요.","example":"내 컴퓨터","type":["string","null"]},"lastVerifiedAt":{"description":"마지막 검증 시각이에요.","example":null,"type":["string","null"]}},"required":["id","label","activatedAt","lastVerifiedAt","deactivatedAt"],"type":"object"},"V1LicenseAppResponse":{"properties":{"activation":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1LicenseAppActivation"}],"description":"이번 요청과 연결된 활성화 정보예요."},{"type":"null"}],"description":"이번 요청과 연결된 활성화 정보예요."},"activationCount":{"description":"현재 활성화 수예요.","example":1,"type":"number"},"expiresAt":{"description":"라이선스 만료 시각이에요.","example":null,"type":["string","null"]},"issuedAt":{"description":"응답을 만든(서명한) 시각이에요. 앱은 이 값이 현재 시각에서 5분 이내인지 확인해 오래된 응답 재사용을 막아요.","example":"2026-10-15T00:01:00.000Z","type":"string"},"maxActivations":{"description":"허용된 최대 활성화 수예요. 무제한이면 null이에요.","example":null,"type":["number","null"]},"mode":{"description":"test 또는 live 라이선스 환경을 알려줘요.","enum":["live","test"],"example":"live","type":"string"},"nonce":{"description":"요청 때 보낸 16바이트 이상 nonce를 그대로 돌려줘요. hex 또는 base64로 보내며 32바이트 hex를 권장해요.","example":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","type":"string"},"status":{"description":"라이선스 검증 결과예요.","enum":["active","expired","revoked","pending","not_found"],"example":"active","type":"string"}},"required":["status","expiresAt","maxActivations","activationCount","mode","activation","nonce","issuedAt"],"type":"object"},"V1LicenseDeactivateRequestDto":{"properties":{"activationId":{"description":"해제할 활성화 식별자예요.","example":"act_123","type":"string"},"key":{"description":"비활성화할 라이선스 키예요.","example":"PAYRI-ABCDE-FGHIJ-KLMNP-QRSTU","type":"string"},"nonce":{"description":"응답 위조와 재전송을 확인할 nonce예요. hex 또는 base64로 보내고, 디코딩한 값은 16바이트 이상이어야 해요. 32바이트 hex를 권장해요.","example":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","minLength":22,"pattern":"^(?:(?:[A-Fa-f0-9]{2}){16,}|[A-Za-z0-9+/_-]{22,}={0,2})$","type":"string"},"productId":{"description":"라이선스가 연결된 상품 식별자예요.","example":"prod_123","type":"string"}},"required":["key","productId","nonce","activationId"],"type":"object"},"V1LicenseIssueBuyer":{"properties":{"email":{"description":"구매자 이메일 주소예요.","example":"buyer@example.com","type":"string"},"name":{"description":"구매자 이름이에요.","example":"홍길동","type":"string"}},"required":["email","name"],"type":"object"},"V1LicenseIssueRequestData":{"properties":{"buyer":{"allOf":[{"$ref":"#/components/schemas/V1LicenseIssueBuyer"}],"description":"라이선스 구매자 정보예요."},"expiresAt":{"description":"라이선스 만료 시각이에요.","example":null,"type":["string","null"]},"interval":{"description":"구독 라이선스의 결제 주기예요.","enum":["monthly","yearly",null],"example":null,"type":["string","null"]},"licenseId":{"description":"발급 대기 중인 라이선스 식별자예요.","example":"lic_123","type":"string"},"maxActivations":{"description":"라이선스의 최대 활성화 수예요. 무제한이면 null이에요.","example":null,"type":["number","null"]},"mode":{"description":"test 또는 live 이벤트 환경을 알려줘요.","enum":["live","test"],"example":"live","type":"string"},"orderId":{"description":"라이선스 발급을 요청한 주문 식별자예요.","example":"ord_123","type":"string"},"planId":{"description":"구독 라이선스의 플랜 식별자예요.","example":null,"type":["string","null"]},"productId":{"description":"라이선스 발급 대상 상품 식별자예요.","example":"prod_123","type":"string"}},"required":["mode","licenseId","orderId","productId","planId","interval","buyer","maxActivations","expiresAt"],"type":"object"},"V1LicenseIssueResponse":{"properties":{"expiresAt":{"description":"발급한 키의 만료 시각이에요. 생략하거나 null이면 요청 data.expiresAt을 그대로 써요. 구독 라이선스는 갱신 때 주기 말로 다시 연장돼요.","example":"2027-10-15T00:00:00.000Z","format":"date-time","type":["string","null"]},"key":{"description":"발급한 라이선스 키예요. 1자 이상 256자 이하 문자열이어야 해요. 요청 data에 key를 더해 그대로 돌려줘도 돼요. key·expiresAt·maxActivations 외 필드는 무시해요.","example":"VENDOR-12345-ABCDE","maxLength":256,"minLength":1,"type":"string"},"maxActivations":{"description":"발급한 키의 최대 활성화 수예요. null이면 무제한이고, 생략하면 요청 data.maxActivations(상품 설정)를 그대로 써요. 0도 무제한으로 받지만 null을 권장해요.","example":null,"minimum":0,"type":["integer","null"]}},"required":["key"],"type":"object"},"V1LicensePageResponse":{"properties":{"data":{"description":"페이지에 포함된 라이선스 목록이에요.","items":{"$ref":"#/components/schemas/V1LicenseResponse"},"type":"array"},"limit":{"description":"페이지 크기예요.","example":20,"type":"number"},"page":{"description":"현재 페이지 번호예요.","example":1,"type":"number"},"total":{"description":"조건에 맞는 전체 항목 수예요.","example":1,"type":"number"}},"required":["page","limit","total","data"],"type":"object"},"V1LicenseResponse":{"properties":{"activationCount":{"description":"현재 활성화 수예요.","example":1,"type":"number"},"activations":{"description":"이 라이선스의 활성화 정보예요.","items":{"$ref":"#/components/schemas/V1LicenseActivation"},"type":["array","null"]},"buyerEmail":{"description":"구매자 이메일 주소예요.","example":"buyer@example.com","type":"string"},"buyerName":{"description":"구매자 이름이에요.","example":"홍길동","type":"string"},"expiresAt":{"description":"라이선스 만료 시각이에요.","example":null,"type":["string","null"]},"id":{"description":"라이선스 식별자예요.","example":"lic_123","type":"string"},"issuedAt":{"description":"라이선스 발급 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"key":{"description":"발급된 라이선스 키예요.","example":"PAYRI-ABCDE-FGHIJ-KLMNP-QRSTU","type":["string","null"]},"maxActivations":{"description":"허용된 최대 활성화 수예요. 무제한이면 null이에요.","example":null,"type":["number","null"]},"mode":{"description":"test 또는 live 라이선스 환경을 알려줘요.","enum":["live","test"],"example":"live","type":"string"},"orderId":{"description":"주문 식별자예요.","example":"ord_123","type":"string"},"orderItemId":{"description":"주문 항목 식별자예요.","example":"item_123","type":["string","null"]},"productId":{"description":"상품 식별자예요.","example":"prod_123","type":"string"},"productName":{"description":"상품 이름이에요.","example":"디지털 가이드","type":"string"},"revokeReason":{"description":"라이선스 취소 사유예요.","example":null,"type":["string","null"]},"revokedAt":{"description":"라이선스가 취소된 시각이에요.","example":null,"type":["string","null"]},"rotatedFrom":{"description":"교체 전 라이선스 식별자예요.","example":null,"type":["string","null"]},"status":{"description":"라이선스 상태예요.","enum":["active","pending","expired","revoked"],"example":"active","type":"string"}},"required":["id","mode","key","productId","productName","orderId","buyerEmail","buyerName","status","maxActivations","issuedAt","orderItemId","expiresAt","revokedAt","revokeReason","rotatedFrom","activationCount","activations"],"type":"object"},"V1LicenseSigningKey":{"properties":{"createdAt":{"description":"공개키가 유효해진 시각이에요.","example":"2026-10-01T00:00:00.000Z","type":"string"},"kid":{"description":"공개키 식별자예요.","example":"2026-10","type":"string"},"publicKey":{"description":"Ed25519 원시 32바이트 공개키의 Base64 값이에요.","example":"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=","type":"string"}},"required":["kid","publicKey","createdAt"],"type":"object"},"V1LicenseSigningKeysResponse":{"properties":{"keys":{"description":"라이선스 응답 서명 검증에 사용할 공개키 목록이에요.","items":{"$ref":"#/components/schemas/V1LicenseSigningKey"},"type":"array"}},"required":["keys"],"type":"object"},"V1LicenseVerifyRequestDto":{"properties":{"activationId":{"description":"상태를 확인할 활성화 식별자예요.","example":"act_123","type":"string"},"key":{"description":"검증할 라이선스 키예요.","example":"PAYRI-ABCDE-FGHIJ-KLMNP-QRSTU","type":"string"},"nonce":{"description":"응답 위조와 재전송을 확인할 nonce예요. hex 또는 base64로 보내고, 디코딩한 값은 16바이트 이상이어야 해요. 32바이트 hex를 권장해요.","example":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","minLength":22,"pattern":"^(?:(?:[A-Fa-f0-9]{2}){16,}|[A-Za-z0-9+/_-]{22,}={0,2})$","type":"string"},"productId":{"description":"라이선스가 연결된 상품 식별자예요.","example":"prod_123","type":"string"}},"required":["key","productId","nonce"],"type":"object"},"V1OrderCoupon":{"properties":{"code":{"description":"쿠폰 코드를 알려줘요.","example":"WELCOME10","type":"string"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"discountAmount":{"description":"할인 금액을 원 단위로 알려줘요.","example":1000,"type":"number"},"name":{"description":"쿠폰 이름을 알려줘요.","example":"신규 고객 할인","type":"string"},"originalAmount":{"description":"할인 전 금액을 원 단위로 알려줘요.","example":10000,"type":"number"}},"required":["code","name","discountAmount","originalAmount","currency"],"type":"object"},"V1OrderPageResponse":{"properties":{"data":{"description":"페이지에 포함된 주문 목록이에요.","items":{"$ref":"#/components/schemas/V1OrderResponse"},"type":"array"},"limit":{"description":"페이지 크기예요.","example":20,"type":"number"},"page":{"description":"현재 페이지 번호예요.","example":1,"type":"number"},"total":{"description":"조건에 맞는 전체 항목 수예요.","example":1,"type":"number"}},"required":["page","limit","total","data"],"type":"object"},"V1OrderRefundDetail":{"properties":{"amount":{"description":"환불 금액을 원 단위로 알려줘요.","example":5000,"type":"number"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"id":{"description":"환불 식별자예요.","example":"ref_123","type":"string"},"reason":{"description":"환불 사유를 알려줘요.","example":"고객 요청","type":["string","null"]},"refundedAt":{"description":"환불이 완료된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"}},"required":["id","amount","currency","reason","refundedAt"],"type":"object"},"V1OrderRefundItem":{"properties":{"amount":{"description":"환불 금액을 원 단위로 알려줘요.","example":5000,"type":"number"},"at":{"description":"환불이 처리된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"reason":{"description":"환불 사유를 알려줘요.","example":"고객 요청","type":["string","null"]}},"required":["amount","currency","at","reason"],"type":"object"},"V1OrderResponse":{"properties":{"amount":{"description":"결제 금액을 원 단위 정수로 알려줘요.","example":10000,"type":"number"},"billingInterval":{"description":"구독 청구 주기예요.","enum":["monthly","yearly",null],"example":"monthly","type":["string","null"]},"buyerEmail":{"description":"구매자 이메일 주소예요.","example":"buyer@example.com","type":"string"},"buyerName":{"description":"구매자 이름이에요.","example":"홍길동","type":"string"},"buyerPhone":{"description":"구매자 연락처예요.","example":"01012345678","type":"string"},"checkoutSessionId":{"description":"연결된 결제 세션 식별자예요.","example":"cs_123","type":["string","null"]},"confirmedAt":{"description":"구매 확정 시각이에요.","example":null,"type":["string","null"]},"coupon":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1OrderCoupon"}],"description":"적용한 쿠폰 정보예요."},{"type":"null"}],"description":"적용한 쿠폰 정보예요."},"createdAt":{"description":"주문이 생성된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"id":{"description":"주문 식별자예요.","example":"ord_123","type":"string"},"metadata":{"description":"요청 때 전달한 메타데이터예요.","example":{"campaign":"fall"},"type":["object","null"]},"method":{"description":"결제 수단이에요.","enum":["card","kakao_pay","naver_pay","toss"],"example":"card","type":"string"},"mode":{"description":"test 또는 live 결제 환경을 알려줘요.","enum":["live","test"],"example":"test","type":"string"},"paidAt":{"description":"결제가 완료된 시각이에요.","example":"2026-10-15T00:01:00.000Z","type":["string","null"]},"periodEnd":{"description":"해당 결제 기간의 종료 시각이에요.","example":null,"type":["string","null"]},"periodStart":{"description":"해당 결제 기간의 시작 시각이에요.","example":null,"type":["string","null"]},"planId":{"description":"구독 플랜 식별자예요.","example":null,"type":["string","null"]},"productId":{"description":"상품 식별자예요.","example":"prod_123","type":"string"},"productName":{"description":"구매한 상품 이름이에요.","example":"디지털 가이드","type":"string"},"refundedAmount":{"description":"누적 환불 금액을 원 단위로 알려줘요.","example":0,"type":["number","null"]},"refundedAt":{"description":"환불이 완료된 시각이에요.","example":null,"type":["string","null"]},"refunds":{"description":"주문에 연결된 환불 내역이에요.","items":{"$ref":"#/components/schemas/V1OrderRefundItem"},"type":"array"},"status":{"description":"주문 상태예요.","enum":["pending","paid","failed","refunded"],"example":"paid","type":"string"},"subscriptionEvent":{"description":"결제가 발생한 구독 이벤트예요.","enum":["initial","renewal","proration",null],"example":"initial","type":["string","null"]},"subscriptionId":{"description":"연결된 구독 식별자예요.","example":null,"type":["string","null"]},"withdrawalNoticeAgreedAt":{"description":"청약 철회 안내 동의 시각이에요.","example":null,"type":["string","null"]}},"required":["id","mode","productId","productName","amount","currency","buyerName","buyerEmail","buyerPhone","method","status","createdAt","paidAt","refundedAt","refundedAmount","refunds","confirmedAt","withdrawalNoticeAgreedAt","coupon","subscriptionId","planId","billingInterval","subscriptionEvent","periodStart","periodEnd","checkoutSessionId","metadata"],"type":"object"},"V1PlanInterval":{"properties":{"billingInterval":{"description":"변경 전후 청구 주기예요.","enum":["monthly","yearly"],"example":"monthly","type":"string"},"planId":{"description":"변경 전후 구독 플랜 식별자예요.","example":"plan_basic","type":"string"}},"required":["planId","billingInterval"],"type":"object"},"V1PortalSessionResponse":{"properties":{"expiresAt":{"description":"토큰 만료 시각이에요.","example":"2026-10-15T01:00:00.000Z","type":"string"},"mode":{"description":"test 또는 live 포털 환경을 알려줘요.","enum":["live","test"],"example":"live","type":"string"},"token":{"description":"포털 인증 토큰이에요.","example":"eyJhbGciOi...","type":"string"},"url":{"description":"구매자 포털에 접속할 URL이에요.","example":"https://payri.kr/portal#token=...","type":"string"}},"required":["mode","url","token","expiresAt"],"type":"object"},"V1ProductContentItem":{"properties":{"label":{"description":"콘텐츠 항목의 표시 이름이에요.","example":"강의 자료","type":"string"},"type":{"description":"콘텐츠 항목의 유형이에요.","enum":["file","license","access","service","support","update","guide","other"],"example":"file","type":"string"}},"required":["type","label"],"type":"object"},"V1ProductDeliverable":{"properties":{"fileName":{"description":"전달 파일 이름이에요.","example":null,"type":["string","null"]},"fileSize":{"description":"전달 파일 크기를 바이트로 알려줘요.","example":null,"type":["number","null"]},"licenseIssuance":{"description":"라이선스 발급 방식이에요.","enum":["payri","seller_server","pool","shared","manual",null],"example":"payri","type":["string","null"]},"maxActivations":{"description":"라이선스 최대 활성화 수예요. 무제한이면 null이에요.","example":null,"type":["number","null"]},"note":{"description":"전달 방식에 대한 안내예요.","example":null,"type":["string","null"]},"type":{"description":"상품 전달 유형이에요.","enum":["file","license","link"],"example":"file","type":"string"}},"required":["type","note","licenseIssuance","maxActivations","fileName","fileSize"],"type":"object"},"V1ProductPageResponse":{"properties":{"data":{"description":"페이지에 포함된 상품 목록이에요.","items":{"$ref":"#/components/schemas/V1ProductResponse"},"type":"array"},"limit":{"description":"페이지 크기예요.","example":20,"type":"number"},"page":{"description":"현재 페이지 번호예요.","example":1,"type":"number"},"total":{"description":"조건에 맞는 전체 항목 수예요.","example":1,"type":"number"}},"required":["page","limit","total","data"],"type":"object"},"V1ProductPenalty":{"properties":{"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"fixedAmount":{"description":"고정 위약금을 원 단위로 알려줘요.","example":0,"type":["number","null"]},"rateBps":{"description":"위약금 비율을 1만분율로 알려줘요.","example":0,"type":["number","null"]}},"required":["rateBps","fixedAmount","currency"],"type":"object"},"V1ProductPlan":{"properties":{"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"features":{"description":"플랜에 포함된 기능 목록이에요.","example":["다운로드 가능"],"items":{"type":"string"},"type":["array","null"]},"id":{"description":"플랜 식별자예요.","example":"plan_basic","type":"string"},"monthlyAmount":{"description":"월간 결제 금액을 원 단위로 알려줘요.","example":9900,"type":"number"},"name":{"description":"플랜 이름이에요.","example":"Basic","type":"string"},"tagline":{"description":"플랜 요약 문구예요.","example":null,"type":["string","null"]},"tier":{"description":"플랜 표시 순서예요.","example":1,"type":"number"},"yearlyAmount":{"description":"연간 결제 금액을 원 단위로 알려줘요.","example":99000,"type":["number","null"]}},"required":["id","name","tagline","features","monthlyAmount","yearlyAmount","currency","tier"],"type":"object"},"V1ProductPricing":{"properties":{"amount":{"description":"단건 상품의 결제 금액이에요.","example":5000,"type":["number","null"]},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"interval":{"description":"단건 상품의 결제 주기예요.","enum":["monthly","yearly",null],"example":null,"type":["string","null"]},"plans":{"description":"구독 상품의 플랜 목록이에요.","items":{"$ref":"#/components/schemas/V1ProductPlan"},"type":["array","null"]},"type":{"description":"가격 유형이에요.","enum":["one_time","subscription"],"example":"subscription","type":"string"}},"required":["type","currency","amount","interval","plans"],"type":"object"},"V1ProductRefundPolicy":{"properties":{"customText":{"description":"사용자에게 표시할 환불 안내예요.","example":null,"type":["string","null"]},"requireApproval":{"description":"환불 요청에 판매자 승인이 필요한지 알려줘요.","example":false,"type":["boolean","null"]},"subscription":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1ProductSubscriptionRefundTerms"}],"description":"구독 상품의 환불 조건이에요."},{"type":"null"}],"description":"구독 상품의 환불 조건이에요."},"type":{"description":"환불 정책 유형이에요.","enum":["no_refund","before_delivery","within_7days","custom",null],"example":"within_7days","type":["string","null"]}},"required":["type","customText","requireApproval","subscription"],"type":"object"},"V1ProductResponse":{"properties":{"contents":{"description":"상품에 포함된 콘텐츠예요.","items":{"$ref":"#/components/schemas/V1ProductContentItem"},"type":"array"},"createdAt":{"description":"상품이 생성된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"deliverable":{"allOf":[{"$ref":"#/components/schemas/V1ProductDeliverable"}],"description":"상품 전달 정보예요."},"description":{"description":"상품 상세 설명이에요.","example":"상품 상세 설명이에요.","type":"string"},"displayOrder":{"description":"스토어에서 상품 표시 순서예요.","example":0,"type":["number","null"]},"icon":{"description":"상품 아이콘 주소예요.","example":"","type":"string"},"iconColor":{"description":"아이콘 배경 색상 코드예요.","example":null,"type":["string","null"]},"id":{"description":"상품 식별자예요.","example":"prod_123","type":"string"},"imageUrl":{"description":"상품 이미지 주소예요.","example":null,"type":["string","null"]},"linkId":{"description":"결제 페이지 링크 식별자예요.","example":"link_123","type":"string"},"listed":{"description":"상품이 공개 판매 중인지 알려줘요.","example":true,"type":"boolean"},"mode":{"description":"test 또는 live 상품 환경을 알려줘요.","enum":["live","test"],"example":"live","type":"string"},"name":{"description":"상품 이름이에요.","example":"디지털 가이드","type":"string"},"pricing":{"allOf":[{"$ref":"#/components/schemas/V1ProductPricing"}],"description":"상품 가격과 구독 플랜 정보예요."},"refundPolicy":{"allOf":[{"$ref":"#/components/schemas/V1ProductRefundPolicy"}],"description":"상품 환불 정책이에요."},"saleEndsAt":{"description":"판매 종료 시각이에요.","example":null,"type":["string","null"]},"saleStartsAt":{"description":"판매 시작 시각이에요.","example":null,"type":["string","null"]},"status":{"description":"상품 상태예요.","enum":["draft","active","archived"],"example":"active","type":"string"},"stockLimit":{"description":"재고 상한이에요.","example":null,"type":["number","null"]},"summary":{"description":"상품 한 줄 소개예요.","example":"바로 내려받는 가이드예요.","type":"string"}},"required":["id","mode","name","summary","description","icon","pricing","linkId","deliverable","status","listed","contents","refundPolicy","createdAt","imageUrl","iconColor","stockLimit","saleStartsAt","saleEndsAt","displayOrder"],"type":"object"},"V1ProductSubscriptionRefundTerms":{"properties":{"dayRounding":{"description":"환불 일수 계산 방식이에요.","enum":["ceil","floor",null],"example":"ceil","type":["string","null"]},"initialFullRefundDays":{"description":"최초 결제의 전액 환불 가능 일수예요.","example":7,"type":["number","null"]},"penalty":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1ProductPenalty"}],"description":"환불 위약금 조건이에요."},{"type":"null"}],"description":"환불 위약금 조건이에요."},"renewalFullRefundDays":{"description":"갱신 결제의 전액 환불 가능 일수예요.","example":7,"type":["number","null"]},"restrictRepeatFullRefund":{"description":"반복 전액 환불 제한 여부예요.","example":false,"type":["boolean","null"]},"yearlyDiscountClawback":{"description":"연간 할인 환수 여부예요.","example":false,"type":["boolean","null"]}},"required":["dayRounding","initialFullRefundDays","renewalFullRefundDays","penalty","yearlyDiscountClawback","restrictRepeatFullRefund"],"type":"object"},"V1RefundActionResponse":{"properties":{"refundRequest":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1RefundRequestResponse"}],"description":"환불 요청 처리 후의 정보예요."},{"type":"null"}],"description":"환불 요청 처리 후의 정보예요."},"warnings":{"description":"처리 결과와 함께 전달하는 안내 목록이에요.","items":{"$ref":"#/components/schemas/V1Warning"},"type":"array"}},"required":["refundRequest","warnings"],"type":"object"},"V1RefundBreakdown":{"properties":{"orders":{"description":"환불 대상 주문별 금액이에요.","items":{"$ref":"#/components/schemas/V1RefundBreakdownOrder"},"type":"array"}},"required":["orders"],"type":"object"},"V1RefundBreakdownOrder":{"properties":{"amount":{"description":"대상 주문의 환불 금액이에요.","example":5000,"type":"number"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"orderId":{"description":"환불 대상 주문 식별자예요.","example":"ord_123","type":"string"}},"required":["orderId","amount","currency"],"type":"object"},"V1RefundHold":{"properties":{"heldAt":{"description":"보류 처리 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"reason":{"description":"보류 사유예요.","example":"추가 확인 중이에요.","type":["string","null"]},"type":{"description":"보류 유형이에요.","enum":["in_review","disputed"],"example":"in_review","type":"string"}},"required":["type","reason","heldAt"],"type":"object"},"V1RefundOrderDto":{"properties":{"amount":{"description":"부분 환불 금액을 원 단위로 지정해요.","example":5000,"minimum":1,"type":"number"},"reason":{"description":"환불 사유예요.","example":"고객 요청","type":"string"}},"type":"object"},"V1RefundRequestApproveDto":{"properties":{"acknowledgeMismatch":{"description":"환불 계산 안내를 확인했는지 표시해요.","example":true,"type":"boolean"},"amount":{"description":"승인할 환불 금액을 원 단위로 지정해요.","example":5000,"minimum":1,"type":"number"}},"type":"object"},"V1RefundRequestHoldDto":{"properties":{"reason":{"description":"보류 사유예요.","example":"추가 확인이 필요해요.","minLength":1,"type":"string"},"type":{"description":"보류 유형이에요.","enum":["in_review","disputed"],"example":"in_review","type":"string"}},"required":["type","reason"],"type":"object"},"V1RefundRequestPageResponse":{"properties":{"data":{"description":"페이지에 포함된 환불 요청 목록이에요.","items":{"$ref":"#/components/schemas/V1RefundRequestResponse"},"type":"array"},"limit":{"description":"페이지 크기예요.","example":20,"type":"number"},"page":{"description":"현재 페이지 번호예요.","example":1,"type":"number"},"total":{"description":"조건에 맞는 전체 항목 수예요.","example":1,"type":"number"}},"required":["page","limit","total","data"],"type":"object"},"V1RefundRequestRejectDto":{"properties":{"reason":{"description":"환불 요청을 거절하는 이유예요.","example":"환불 정책상 처리할 수 없어요.","minLength":1,"type":"string"}},"required":["reason"],"type":"object"},"V1RefundRequestResponse":{"properties":{"approvedAmount":{"description":"승인한 환불 금액을 원 단위로 알려줘요.","example":null,"type":["number","null"]},"autoApproveAt":{"description":"요청 후 72시간 안에 결정되지 않으면 자동 승인되는 시각이에요.","example":"2026-10-18T00:00:00.000Z","type":["string","null"]},"breakdown":{"allOf":[{"$ref":"#/components/schemas/V1RefundBreakdown"}],"description":"주문별 환불 금액 내역이에요."},"buyerEmail":{"description":"구매자 이메일 주소예요.","example":"buyer@example.com","type":"string"},"buyerReason":{"description":"구매자가 남긴 환불 사유예요.","example":null,"type":["string","null"]},"createdAt":{"description":"환불 요청이 생성된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"decidedAt":{"description":"요청이 결정된 시각이에요.","example":null,"type":["string","null"]},"decidedBy":{"description":"요청을 결정한 사용자 식별자예요.","example":null,"type":["string","null"]},"hold":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1RefundHold"}],"description":"보류 처리 정보예요."},{"type":"null"}],"description":"보류 처리 정보예요."},"id":{"description":"환불 요청 식별자예요.","example":"rfr_123","type":"string"},"kind":{"description":"환불 요청 유형이에요.","enum":["order","subscription_cancel"],"example":"order","type":"string"},"mode":{"description":"test 또는 live 환불 환경을 알려줘요.","enum":["live","test"],"example":"test","type":"string"},"orderId":{"description":"환불 요청의 주문 식별자예요.","example":"ord_123","type":"string"},"productId":{"description":"환불 요청의 상품 식별자예요.","example":"prod_123","type":"string"},"refundableAmount":{"description":"현재 환불 가능한 금액을 원 단위로 알려줘요.","example":10000,"type":"number"},"rejectReason":{"description":"거절 사유예요.","example":null,"type":["string","null"]},"requestedAmount":{"description":"요청한 환불 금액을 원 단위로 알려줘요.","example":10000,"type":"number"},"status":{"description":"환불 요청 상태예요.","enum":["requested","on_hold","processing","approved","rejected","withdrawn"],"example":"requested","type":"string"},"statutory":{"description":"법정 청약 철회 요청인지 알려줘요.","example":false,"type":"boolean"},"subscriptionId":{"description":"환불 요청의 구독 식별자예요.","example":null,"type":["string","null"]},"updatedAt":{"description":"환불 요청이 수정된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"warnings":{"description":"환불 처리 전에 확인할 안내 목록이에요.","items":{"$ref":"#/components/schemas/V1Warning"},"type":"array"}},"required":["id","kind","status","orderId","subscriptionId","productId","requestedAmount","approvedAmount","currency","breakdown","buyerEmail","buyerReason","rejectReason","hold","autoApproveAt","decidedAt","decidedBy","statutory","mode","createdAt","updatedAt"],"type":"object"},"V1SubscriptionChange":{"properties":{"amount":{"description":"변경 시 적용된 금액을 원 단위로 알려줘요.","example":null,"type":["number","null"]},"currency":{"description":"변경 금액 통화예요.","enum":["KRW",null],"example":null,"type":["string","null"]},"effectiveAt":{"description":"변경 효력이 발생하는 시각이에요.","example":null,"type":["string","null"]},"extensionDays":{"description":"구독 기간 연장 일수예요.","example":null,"type":["number","null"]},"from":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1PlanInterval"}],"description":"변경 전 플랜과 주기예요."},{"type":"null"}],"description":"변경 전 플랜과 주기예요."},"kind":{"description":"구독에 발생한 변경 유형이에요.","enum":["created","plan_changed","plan_change_scheduled","billing_interval_changed","billing_interval_change_scheduled","cancel_scheduled","cancel_resumed","period_renewed","period_extended","price_change_scheduled","price_change_consented"],"example":"plan_changed","type":"string"},"orderId":{"description":"변경과 연결된 주문 식별자예요.","example":null,"type":["string","null"]},"prorationAmount":{"description":"차액 결제 금액을 원 단위로 알려줘요.","example":null,"type":["number","null"]},"to":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1PlanInterval"}],"description":"변경 후 플랜과 주기예요."},{"type":"null"}],"description":"변경 후 플랜과 주기예요."}},"required":["kind","from","to","prorationAmount","orderId","effectiveAt","extensionDays","amount","currency"],"type":"object"},"V1SubscriptionHistoryEntry":{"properties":{"at":{"description":"변경이 기록된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"},"effectiveAt":{"description":"변경 효력이 발생하는 시각이에요.","example":null,"type":["string","null"]},"extensionDays":{"description":"구독 기간 연장 일수예요.","example":null,"type":["number","null"]},"from":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1PlanInterval"}],"description":"변경 전 플랜과 주기예요."},{"type":"null"}],"description":"변경 전 플랜과 주기예요."},"note":{"description":"이전 변경 기록의 메모예요.","example":null,"type":["string","null"]},"orderId":{"description":"변경과 연결된 주문 식별자예요.","example":null,"type":["string","null"]},"prorationAmount":{"description":"차액 결제 금액, 또는 갱신·가격 변경 이력의 금액을 원 단위로 알려줘요.","example":null,"type":["number","null"]},"to":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1PlanInterval"}],"description":"변경 후 플랜과 주기예요."},{"type":"null"}],"description":"변경 후 플랜과 주기예요."},"type":{"description":"내부 변경 기록 유형이에요.","enum":["created","renewed","upgraded","downgrade_scheduled","downgrade_applied","interval_changed","cancel_scheduled","cancel_undone","ended","refunded","canceled_with_refund","comp_upgraded","period_extended","payment_failed","price_change_noticed","price_change_consented",null],"example":"renewed","type":["string","null"]}},"required":["at","type","from","to","prorationAmount","orderId","effectiveAt","extensionDays","note"],"type":"object"},"V1SubscriptionListAmounts":{"properties":{"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"monthly":{"description":"월간 기준 금액이에요.","example":null,"type":["number","null"]},"yearly":{"description":"연간 기준 금액이에요.","example":null,"type":["number","null"]}},"required":["monthly","yearly","currency"],"type":"object"},"V1SubscriptionPageResponse":{"properties":{"data":{"description":"페이지에 포함된 구독 목록이에요.","items":{"$ref":"#/components/schemas/V1SubscriptionResponse"},"type":"array"},"limit":{"description":"페이지 크기예요.","example":20,"type":"number"},"page":{"description":"현재 페이지 번호예요.","example":1,"type":"number"},"total":{"description":"조건에 맞는 전체 항목 수예요.","example":1,"type":"number"}},"required":["page","limit","total","data"],"type":"object"},"V1SubscriptionPenalty":{"properties":{"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"fixedAmount":{"description":"고정 위약금을 원 단위로 알려줘요.","example":null,"type":["number","null"]},"rateBps":{"description":"위약금 비율을 1만분율로 알려줘요.","example":null,"type":["number","null"]}},"required":["rateBps","fixedAmount","currency"],"type":"object"},"V1SubscriptionPendingPriceChange":{"properties":{"amount":{"description":"고지된 새 구독 금액을 원 단위로 알려줘요.","example":12000,"type":"number"},"consentedAt":{"description":"구매자가 새 가격에 동의한 시각이에요.","example":null,"type":["string","null"]},"currency":{"description":"고지된 금액의 통화예요.","enum":["KRW"],"example":"KRW","type":"string"},"effectiveFrom":{"description":"새 가격이 적용될 갱신일이에요.","example":"2026-11-01T00:00:00.000Z","type":"string"},"noticedAt":{"description":"가격 인상을 고지한 시각이에요.","example":"2026-10-01T00:00:00.000Z","type":"string"}},"required":["amount","currency","noticedAt","effectiveFrom","consentedAt"],"type":"object"},"V1SubscriptionRefundTerms":{"properties":{"dayRounding":{"description":"일수 계산 방식이에요.","enum":["ceil","floor",null],"example":null,"type":["string","null"]},"initialFullRefundDays":{"description":"최초 결제 전액 환불 가능 일수예요.","example":null,"type":["number","null"]},"listAmounts":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionListAmounts"}],"description":"환불 계산에 사용하는 기준 금액이에요."},{"type":"null"}],"description":"환불 계산에 사용하는 기준 금액이에요."},"penalty":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionPenalty"}],"description":"환불 위약금 조건이에요."},{"type":"null"}],"description":"환불 위약금 조건이에요."},"policyType":{"description":"구독 환불 정책 유형이에요.","enum":["no_refund","before_delivery","within_7days","custom",null],"example":null,"type":["string","null"]},"renewalFullRefundDays":{"description":"갱신 결제 전액 환불 가능 일수예요.","example":null,"type":["number","null"]},"requireApproval":{"description":"환불 요청에 승인이 필요한지 알려줘요.","example":false,"type":["boolean","null"]},"restrictRepeatFullRefund":{"description":"반복 전액 환불 제한 여부예요.","example":null,"type":["boolean","null"]},"yearlyDiscountClawback":{"description":"연간 할인 환수 여부예요.","example":null,"type":["boolean","null"]}},"required":["policyType","requireApproval","dayRounding","initialFullRefundDays","renewalFullRefundDays","penalty","yearlyDiscountClawback","restrictRepeatFullRefund","listAmounts"],"type":"object"},"V1SubscriptionResponse":{"properties":{"amount":{"description":"갱신할 때 청구하는 주기당 금액의 상한을 원 단위 정수로 알려줘요. 상품 가격이 내려가면 다음 갱신부터 낮아지고, 인상은 고지 후 구매자가 동의해야 적용돼요.","example":9900,"type":"number"},"billingInterval":{"description":"구독 결제 주기예요.","enum":["monthly","yearly"],"example":"monthly","type":"string"},"buyerEmail":{"description":"구매자 이메일 주소예요.","example":"buyer@example.com","type":"string"},"buyerName":{"description":"구매자 이름이에요.","example":"홍길동","type":"string"},"cancelAtPeriodEnd":{"description":"다음 기간 종료 시 해지하도록 예약했는지 알려줘요.","example":false,"type":"boolean"},"currency":{"description":"금액 통화를 알려줘요.","enum":["KRW"],"example":"KRW","type":"string"},"currentPeriodEnd":{"description":"현재 결제 기간 종료 시각이에요.","example":"2026-11-01T00:00:00.000Z","type":"string"},"currentPeriodStart":{"description":"현재 결제 기간 시작 시각이에요.","example":"2026-10-01T00:00:00.000Z","type":"string"},"endReason":{"description":"구독 종료 사유예요.","enum":["canceled","refunded","payment_failed","product_unavailable","plan_unavailable","pg_canceled","price_increase_declined",null],"example":null,"type":["string","null"]},"endedAt":{"description":"구독이 종료된 시각이에요.","example":null,"type":["string","null"]},"history":{"description":"구독 변경 이력이에요.","items":{"$ref":"#/components/schemas/V1SubscriptionHistoryEntry"},"type":["array","null"]},"id":{"description":"구독 식별자예요.","example":"sub_123","type":"string"},"mode":{"description":"test 또는 live 구독 환경을 알려줘요.","enum":["live","test"],"example":"test","type":"string"},"pastDueSince":{"description":"결제 실패 상태가 시작된 시각이에요.","example":null,"type":["string","null"]},"pendingPriceChange":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionPendingPriceChange"}],"description":"가격 인상 고지와 구매자 동의 상태예요."},{"type":"null"}],"description":"가격 인상 고지와 구매자 동의 상태예요."},"planId":{"description":"구독 플랜 식별자예요.","example":"plan_basic","type":"string"},"productId":{"description":"상품 식별자예요.","example":"prod_123","type":"string"},"productName":{"description":"상품 이름이에요.","example":"멤버십","type":"string"},"refundEligibleUntil":{"description":"최초 결제 환불 가능 기한이에요.","example":"2026-10-08T00:00:00.000Z","type":"string"},"refundTerms":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionRefundTerms"}],"description":"구독 환불 조건의 스냅샷이에요."},"scheduledChange":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionScheduledChange"}],"description":"예약된 구독 변경 정보예요."},{"type":"null"}],"description":"예약된 구독 변경 정보예요."},"startedAt":{"description":"구독이 시작된 시각이에요.","example":"2026-10-01T00:00:00.000Z","type":"string"},"status":{"description":"구독의 공개 상태예요. past_due 는 결제가 밀린 상태예요. 결제가 밀린 채 해지를 예약해도 past_due 이고 cancelAtPeriodEnd 가 true 예요.","enum":["active","past_due","ended"],"example":"active","type":"string"},"testRenewalOutcome":{"description":"test 갱신 결과 설정이에요.","enum":["succeed","fail",null],"example":"succeed","type":["string","null"]}},"required":["id","mode","testRenewalOutcome","productId","productName","buyerEmail","buyerName","planId","billingInterval","amount","currency","status","cancelAtPeriodEnd","endReason","currentPeriodStart","currentPeriodEnd","startedAt","refundEligibleUntil","refundTerms","history","scheduledChange","pendingPriceChange","endedAt","pastDueSince"],"type":"object"},"V1SubscriptionScheduledChange":{"properties":{"billingInterval":{"description":"예약된 구독 청구 주기예요.","enum":["monthly","yearly",null],"example":null,"type":["string","null"]},"effectiveAt":{"description":"예약 변경 효력이 발생하는 시각이에요.","example":"2026-11-01T00:00:00.000Z","type":"string"},"planId":{"description":"예약된 구독 플랜 식별자예요.","example":null,"type":["string","null"]},"type":{"description":"예약 변경 유형이에요.","enum":["downgrade","interval_change","cancel"],"example":"cancel","type":"string"}},"required":["effectiveAt","type","planId","billingInterval"],"type":"object"},"V1Warning":{"properties":{"code":{"description":"환불 안내를 구분하는 코드예요.","enum":["STATUTORY_LOCKED","SUBSCRIPTION_CANCEL_REFUND_RIGHT","POLICY_DECISION"],"example":"POLICY_DECISION","type":"string"},"message":{"description":"환불 처리 시 참고할 안내예요.","example":"환불 가능 기간이 지났어요.","type":"string"}},"required":["code","message"],"type":"object"},"V1WebhookData_license_issue":{"allOf":[{"$ref":"#/components/schemas/V1LicenseIssueRequestData"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode"],"type":"object"}],"title":"license.issue webhook data"},"V1WebhookData_order_paid":{"allOf":[{"$ref":"#/components/schemas/V1OrderResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode","subscriptionEvent"],"type":"object"}],"title":"order.paid webhook data"},"V1WebhookData_order_refunded":{"allOf":[{"$ref":"#/components/schemas/V1OrderResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"refund":{"$ref":"#/components/schemas/V1OrderRefundDetail","description":"주문 환불의 상세 정보예요."}},"required":["mode","refund"],"type":"object"}],"title":"order.refunded webhook data"},"V1WebhookData_refund_approved":{"allOf":[{"$ref":"#/components/schemas/V1RefundRequestResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode"],"type":"object"}],"title":"refund.approved webhook data"},"V1WebhookData_refund_on_hold":{"allOf":[{"$ref":"#/components/schemas/V1RefundRequestResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode"],"type":"object"}],"title":"refund.on_hold webhook data"},"V1WebhookData_refund_rejected":{"allOf":[{"$ref":"#/components/schemas/V1RefundRequestResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode"],"type":"object"}],"title":"refund.rejected webhook data"},"V1WebhookData_refund_requested":{"allOf":[{"$ref":"#/components/schemas/V1RefundRequestResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode"],"type":"object"}],"title":"refund.requested webhook data"},"V1WebhookData_refund_withdrawn":{"allOf":[{"$ref":"#/components/schemas/V1RefundRequestResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode"],"type":"object"}],"title":"refund.withdrawn webhook data"},"V1WebhookData_subscription_created":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionResponse"},{"properties":{"change":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionChange"},{"properties":{"kind":{"description":"이 이벤트에서 발생한 구독 변경 유형이에요.","enum":["created"],"type":"string"}},"required":["kind"],"type":"object"}],"description":"새 구독이 만들어진 변경 정보예요."},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode","change"],"type":"object"}],"title":"subscription.created webhook data"},"V1WebhookData_subscription_ended":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionResponse"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"refundAmount":{"description":"즉시 해지로 환불한 금액이에요. 환불을 수반한 즉시 해지에서 전달해요.","example":10000,"type":"integer"}},"required":["mode"],"type":"object"}],"title":"subscription.ended webhook data"},"V1WebhookData_subscription_payment_failed":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionResponse"},{"properties":{"amount":{"description":"실패한 결제 금액이에요.","example":9900,"type":"integer"},"attempts":{"description":"누적 결제 실패 횟수예요.","example":2,"type":"integer"},"currency":{"description":"결제 금액 통화예요.","enum":["KRW"],"type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode","attempts","amount","currency"],"type":"object"}],"title":"subscription.payment_failed webhook data"},"V1WebhookData_subscription_updated":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionResponse"},{"properties":{"change":{"allOf":[{"$ref":"#/components/schemas/V1SubscriptionChange"},{"properties":{"kind":{"description":"이 이벤트에서 발생한 구독 변경 유형이에요.","enum":["plan_changed","plan_change_scheduled","billing_interval_changed","billing_interval_change_scheduled","cancel_scheduled","cancel_resumed","period_renewed","period_extended","price_change_scheduled","price_change_consented"],"type":"string"}},"required":["kind"],"type":"object"}],"description":"구독의 변경 전후 플랜 정보예요."},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode","change"],"type":"object"}],"title":"subscription.updated webhook data"},"V1WebhookData_webhook_test":{"allOf":[{"$ref":"#/components/schemas/V1WebhookTestData"},{"properties":{"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"}},"required":["mode"],"type":"object"}],"title":"webhook.test webhook data"},"V1WebhookEnvelope_license_issue":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_license_issue","description":"라이선스 발급을 요청하는 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"license.issue","description":"구독한 웹훅 이벤트 이름이에요.","enum":["license.issue"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"license.issue webhook envelope","type":"object"},"V1WebhookEnvelope_order_paid":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_order_paid","description":"결제가 완료된 주문 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"order.paid","description":"구독한 웹훅 이벤트 이름이에요.","enum":["order.paid"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"order.paid webhook envelope","type":"object"},"V1WebhookEnvelope_order_refunded":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_order_refunded","description":"환불이 완료된 주문 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"order.refunded","description":"구독한 웹훅 이벤트 이름이에요.","enum":["order.refunded"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"order.refunded webhook envelope","type":"object"},"V1WebhookEnvelope_refund_approved":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_refund_approved","description":"승인된 환불 요청 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"refund.approved","description":"구독한 웹훅 이벤트 이름이에요.","enum":["refund.approved"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"refund.approved webhook envelope","type":"object"},"V1WebhookEnvelope_refund_on_hold":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_refund_on_hold","description":"보류된 환불 요청 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"refund.on_hold","description":"구독한 웹훅 이벤트 이름이에요.","enum":["refund.on_hold"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"refund.on_hold webhook envelope","type":"object"},"V1WebhookEnvelope_refund_rejected":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_refund_rejected","description":"거절된 환불 요청 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"refund.rejected","description":"구독한 웹훅 이벤트 이름이에요.","enum":["refund.rejected"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"refund.rejected webhook envelope","type":"object"},"V1WebhookEnvelope_refund_requested":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_refund_requested","description":"새 환불 요청 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"refund.requested","description":"구독한 웹훅 이벤트 이름이에요.","enum":["refund.requested"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"refund.requested webhook envelope","type":"object"},"V1WebhookEnvelope_refund_withdrawn":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_refund_withdrawn","description":"철회된 환불 요청 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"refund.withdrawn","description":"구독한 웹훅 이벤트 이름이에요.","enum":["refund.withdrawn"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"refund.withdrawn webhook envelope","type":"object"},"V1WebhookEnvelope_subscription_created":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_subscription_created","description":"새 구독 생성 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"subscription.created","description":"구독한 웹훅 이벤트 이름이에요.","enum":["subscription.created"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"subscription.created webhook envelope","type":"object"},"V1WebhookEnvelope_subscription_ended":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_subscription_ended","description":"구독 종료 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"subscription.ended","description":"구독한 웹훅 이벤트 이름이에요.","enum":["subscription.ended"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"subscription.ended webhook envelope","type":"object"},"V1WebhookEnvelope_subscription_payment_failed":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_subscription_payment_failed","description":"구독 결제 실패 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"subscription.payment_failed","description":"구독한 웹훅 이벤트 이름이에요.","enum":["subscription.payment_failed"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"subscription.payment_failed webhook envelope","type":"object"},"V1WebhookEnvelope_subscription_updated":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_subscription_updated","description":"구독 변경 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"subscription.updated","description":"구독한 웹훅 이벤트 이름이에요.","enum":["subscription.updated"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"subscription.updated webhook envelope","type":"object"},"V1WebhookEnvelope_webhook_test":{"additionalProperties":false,"properties":{"createdAt":{"description":"이벤트가 생성된 시각이에요.","format":"date-time","type":"string"},"data":{"$ref":"#/components/schemas/V1WebhookData_webhook_test","description":"웹훅 수신을 확인하는 테스트 이벤트 데이터예요."},"id":{"description":"이벤트를 유일하게 구분해요.","example":"evt_123","type":"string"},"mode":{"description":"이벤트의 결제 환경이에요.","enum":["live","test"],"type":"string"},"type":{"const":"webhook.test","description":"구독한 웹훅 이벤트 이름이에요.","enum":["webhook.test"],"type":"string"}},"required":["id","type","createdAt","mode","data"],"title":"webhook.test webhook envelope","type":"object"},"V1WebhookTestData":{"properties":{"endpointId":{"description":"테스트 이벤트를 보낸 엔드포인트 식별자예요.","example":"wh_123","type":"string"},"mode":{"description":"test 또는 live 웹훅 환경을 알려줘요.","enum":["live","test"],"example":"test","type":"string"},"sentAt":{"description":"테스트 이벤트가 발송된 시각이에요.","example":"2026-10-15T00:00:00.000Z","type":"string"}},"required":["endpointId","mode","sentAt"],"type":"object"}},"securitySchemes":{"bearerAuth":{"bearerFormat":"PayRi API key","description":"서버용 API 키를 Authorization: Bearer <API 키>로 전달해요.","scheme":"bearer","type":"http"}}},"info":{"contact":{},"description":"PayRi 외부 API의 단일 계약이에요. 모든 시각은 ISO 8601 형식이고, 금액은 통화와 함께 원 단위 정수로 전달해요.\n\n## 인증과 환경 분리\n서버용 API 키는 'Authorization: Bearer <API 키>' 헤더로 보내요. 키는 발급할 때 정한 'live' 또는 'test' 환경에 고정돼요. test 키로 만든 결제 세션은 실제 PG를 호출하지 않으며 주문, 구독, 환불, 웹훅 데이터도 live 환경과 분리해요. API 키로 접근하는 리소스는 키의 환경과 상품 범위 안에서만 보여요.\n\n## 멱등 요청\nAPI 키가 필요한 모든 POST 요청에 'Idempotency-Key' 헤더를 보내요. 서버는 키와 요청 본문을 24시간 보관해요. 같은 키와 같은 본문을 다시 보내면 저장한 응답을 돌려줘요. 같은 키로 다른 본문을 보내면 '409 IDEMPOTENCY_KEY_CONFLICT'를 돌려줘요. '400 VALIDATION_FAILED' 응답은 멱등 키에 저장하지 않고, 같은 요청을 다시 검증해요. 라이선스 앱의 verify·activate·deactivate 요청은 이 규칙에서 제외해요.\n\n## 호출 제한\nAPI 키 요청은 키별 분당 300회까지 허용해요. 라이선스 앱 API는 IP별 분당 60회, 라이선스 키별 분당 30회까지 허용해요. 10분 안에 존재하지 않는 라이선스 키를 10회 조회하면 해당 IP의 조회를 15분 동안 차단해요. 제한 응답의 'Retry-After' 헤더를 확인해요.\n\n## 웹훅 검증\n웹훅 본문은 '{ id, type, createdAt, mode, data }' 형식이에요. 'webhook-id'는 본문 'id'와 같고, 'webhook-timestamp'는 서명 시각이에요. 수신한 원문 본문으로 'webhook-id.webhook-timestamp.rawBody'를 HMAC-SHA256 서명하고 'whsec_' 시크릿으로 'webhook-signature'의 'v1' 값을 검증해요. 재시도에도 이벤트 ID는 같지만 시각과 서명은 다시 계산해요.\n\n## 라이선스 앱 응답 서명\n라이선스 앱 요청에는 hex 또는 base64 형식의 'nonce'를 보내요. 디코딩한 값은 16바이트 이상이어야 하고, 32바이트 hex 사용을 권장해요. 응답의 원문 본문은 Ed25519로 서명하며 'Payri-Signature' 헤더에 'kid'와 서명을 담아요. 앱은 응답 서명, 요청 nonce 일치, 'issuedAt'이 현재 시각에서 5분 이내인지 모두 확인해요. 서명 검증 공개키는 API 키 없이 'GET /v1/licenses/signing-keys'에서 조회해요. 공개 라이선스 검증 API의 응답은 PII와 다른 기기 정보를 포함하지 않아요.\n\n모든 API 오류는 '{ statusCode, code, message, details? }' 형식이에요. 오류 메시지는 한국어로 제공해요.","title":"PayRi API","version":"1"},"jsonSchemaDialect":"https://spec.openapis.org/oas/3.1/dialect/base","openapi":"3.1.0","paths":{"/v1/checkout/sessions":{"post":{"description":"상품 식별자로 test 또는 live 결제 세션을 만들어요. 공개 연락처 인증이 끝나지 않은 스토어는 409 응답을 돌려줘요. Idempotency-Key는 24시간 보관해요.","operationId":"CheckoutV1Controller_create","parameters":[{"description":"POST 요청의 중복 실행을 막는 키예요. 24시간 보관하며 본문이 다른 요청에는 같은 키를 쓸 수 없어요.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"단건 결제 세션","value":{"customer":{"email":"buyer@example.com"},"productId":"prod_123","successUrl":"https://shop.example.com/complete"}}},"schema":{"$ref":"#/components/schemas/V1CreateCheckoutSessionDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"cancelUrl":"https://shop.example.com/cancel","createdAt":"2026-10-15T00:00:00.000Z","customer":{"email":"buyer@example.com","name":"홍길동","phone":null},"expiresAt":"2026-10-15T00:30:00.000Z","id":"cs_123","metadata":{"campaign":"fall"},"mode":"test","orderId":null,"productId":"prod_123","status":"open","successUrl":"https://shop.example.com/complete","url":"https://payri.kr/checkout/cs_123"},"schema":{"$ref":"#/components/schemas/V1CheckoutSessionResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"결제 세션 생성","tags":["결제 세션"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","PRODUCT_NOT_FOUND","PRODUCT_ARCHIVED","SOLD_OUT","NOT_STARTED","ENDED","PUBLIC_CONTACT_VERIFICATION_REQUIRED","CHECKOUT_URL_INVALID","RETURN_URL_NOT_ALLOWED","METADATA_INVALID","CHECKOUT_NOT_CONFIGURED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_IN_PROGRESS","INTERNAL_ERROR"],"x-payri-idempotent":true,"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"customer":{"email":"buyer@example.com"},"productId":"prod_123","successUrl":"https://shop.example.com/complete"},"headers":{"Idempotency-Key":"checkout-prod-123-001"},"method":"POST","url":"https://api.payri.kr/v1/checkout/sessions"},"x-payri-response-example":{"cancelUrl":"https://shop.example.com/cancel","createdAt":"2026-10-15T00:00:00.000Z","customer":{"email":"buyer@example.com","name":"홍길동","phone":null},"expiresAt":"2026-10-15T00:30:00.000Z","id":"cs_123","metadata":{"campaign":"fall"},"mode":"test","orderId":null,"productId":"prod_123","status":"open","successUrl":"https://shop.example.com/complete","url":"https://payri.kr/checkout/cs_123"},"x-payri-scope":["checkout:write"]}},"/v1/checkout/sessions/{id}":{"get":{"description":"세션 식별자로 만료 시각과 결제 상태를 조회해요.","operationId":"CheckoutV1Controller_get","parameters":[{"description":"조회할 결제 세션 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"cs_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"cancelUrl":"https://shop.example.com/cancel","createdAt":"2026-10-15T00:00:00.000Z","customer":{"email":"buyer@example.com","name":"홍길동","phone":null},"expiresAt":"2026-10-15T00:30:00.000Z","id":"cs_123","metadata":{"campaign":"fall"},"mode":"test","orderId":null,"productId":"prod_123","status":"open","successUrl":"https://shop.example.com/complete","url":"https://payri.kr/checkout/cs_123"},"schema":{"$ref":"#/components/schemas/V1CheckoutSessionResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"결제 세션 조회","tags":["결제 세션"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","CHECKOUT_SESSION_NOT_FOUND","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/checkout/sessions/cs_123"},"x-payri-response-example":{"cancelUrl":"https://shop.example.com/cancel","createdAt":"2026-10-15T00:00:00.000Z","customer":{"email":"buyer@example.com","name":"홍길동","phone":null},"expiresAt":"2026-10-15T00:30:00.000Z","id":"cs_123","metadata":{"campaign":"fall"},"mode":"test","orderId":null,"productId":"prod_123","status":"open","successUrl":"https://shop.example.com/complete","url":"https://payri.kr/checkout/cs_123"},"x-payri-scope":["checkout:read"]}},"/v1/licenses":{"get":{"description":"API 키의 test 또는 live 환경과 상품 범위에 속한 라이선스를 필터와 함께 조회해요.","operationId":"LicenseV1Controller_list","parameters":[{"description":"조회할 페이지 번호예요.","in":"query","name":"page","required":false,"schema":{"default":1,"example":1,"minimum":1,"type":"number"}},{"description":"페이지마다 조회할 항목 수예요.","in":"query","name":"limit","required":false,"schema":{"default":20,"example":20,"maximum":100,"minimum":1,"type":"number"}},{"description":"라이선스 상태로 결과를 좁혀요.","in":"query","name":"status","required":false,"schema":{"enum":["active","expired","revoked","pending","failed"],"example":"active","type":"string"}},{"description":"상품 식별자로 라이선스를 좁혀요.","in":"query","name":"productId","required":false,"schema":{"example":"prod_123","type":"string"}},{"description":"라이선스 키로 결과를 좁혀요.","in":"query","name":"key","required":false,"schema":{"example":"PAYRI-ABCDE-FGHIJ-KLMNP-QRSTU","type":"string"}},{"description":"주문 식별자로 라이선스를 좁혀요.","in":"query","name":"orderId","required":false,"schema":{"example":"ord_123","type":"string"}},{"description":"구매자 이메일 문자열로 라이선스를 좁혀요.","in":"query","name":"buyerEmail","required":false,"schema":{"example":"buyer@example.com","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"activationCount":1,"activations":[{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"}],"buyerEmail":"buyer@example.com","buyerName":"홍길동","expiresAt":null,"id":"lic_123","issuedAt":"2026-10-15T00:01:00.000Z","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","maxActivations":null,"mode":"test","orderId":"ord_123","orderItemId":"item_123","productId":"prod_123","productName":"디지털 가이드","revokeReason":null,"revokedAt":null,"rotatedFrom":null,"status":"active"}],"limit":20,"page":1,"total":1},"schema":{"$ref":"#/components/schemas/V1LicensePageResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"라이선스 목록 조회","tags":["라이선스"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/licenses?page=1&limit=20&status=active&productId=prod_123"},"x-payri-response-example":{"data":[{"activationCount":1,"activations":[{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"}],"buyerEmail":"buyer@example.com","buyerName":"홍길동","expiresAt":null,"id":"lic_123","issuedAt":"2026-10-15T00:01:00.000Z","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","maxActivations":null,"mode":"test","orderId":"ord_123","orderItemId":"item_123","productId":"prod_123","productName":"디지털 가이드","revokeReason":null,"revokedAt":null,"rotatedFrom":null,"status":"active"}],"limit":20,"page":1,"total":1},"x-payri-scope":["licenses:read"]}},"/v1/licenses/activate":{"post":{"description":"서버가 새 활성화 식별자를 발급하고 서명된 라이선스 상태를 돌려줘요. 활성화 식별자는 요청에서 지정하지 않아요.","operationId":"LicenseAppV1Controller_activate","parameters":[],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"기기 활성화","value":{"key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","label":"내 컴퓨터","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","productId":"prod_123"}}},"schema":{"$ref":"#/components/schemas/V1LicenseActivateRequestDto"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"activation":{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"},"activationCount":1,"expiresAt":null,"issuedAt":"2026-10-15T00:02:30.000Z","maxActivations":null,"mode":"test","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","status":"active"},"schema":{"$ref":"#/components/schemas/V1LicenseAppResponse"}}},"description":"요청 결과를 반환해요.","headers":{"Payri-Signature":{"description":"응답 본문의 Ed25519 서명이에요.","schema":{"example":"kid=2026-10, ed25519=base64...","type":"string"}}}},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"429":{"content":{"application/json":{"example":{"code":"LICENSE_RATE_LIMITED","message":"라이선스 API 호출 한도를 초과했어요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"summary":"라이선스 활성화","tags":["라이선스 앱 API"],"x-payri-error-codes":["VALIDATION_FAILED","LICENSE_RATE_LIMITED","LICENSE_LOOKUP_BLOCKED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","label":"내 컴퓨터","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","productId":"prod_123"},"headers":{"Content-Type":"application/json"},"method":"POST","url":"https://api.payri.kr/v1/licenses/activate"},"x-payri-response-example":{"activation":{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"},"activationCount":1,"expiresAt":null,"issuedAt":"2026-10-15T00:02:30.000Z","maxActivations":null,"mode":"test","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","status":"active"},"x-payri-scope":[]}},"/v1/licenses/deactivate":{"post":{"description":"라이선스 키와 활성화 식별자로 한 기기의 활성화를 해제하고 서명된 상태를 돌려줘요.","operationId":"LicenseAppV1Controller_deactivate","parameters":[],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"기기 비활성화","value":{"activationId":"act_123","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","productId":"prod_123"}}},"schema":{"$ref":"#/components/schemas/V1LicenseDeactivateRequestDto"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"activation":{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":"2026-10-15T00:03:00.000Z","id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"},"activationCount":0,"expiresAt":null,"issuedAt":"2026-10-15T00:03:00.000Z","maxActivations":null,"mode":"test","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","status":"active"},"schema":{"$ref":"#/components/schemas/V1LicenseAppResponse"}}},"description":"요청 결과를 반환해요.","headers":{"Payri-Signature":{"description":"응답 본문의 Ed25519 서명이에요.","schema":{"example":"kid=2026-10, ed25519=base64...","type":"string"}}}},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"429":{"content":{"application/json":{"example":{"code":"LICENSE_RATE_LIMITED","message":"라이선스 API 호출 한도를 초과했어요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"summary":"라이선스 비활성화","tags":["라이선스 앱 API"],"x-payri-error-codes":["VALIDATION_FAILED","LICENSE_RATE_LIMITED","LICENSE_LOOKUP_BLOCKED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"activationId":"act_123","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","productId":"prod_123"},"headers":{"Content-Type":"application/json"},"method":"POST","url":"https://api.payri.kr/v1/licenses/deactivate"},"x-payri-response-example":{"activation":{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":"2026-10-15T00:03:00.000Z","id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"},"activationCount":0,"expiresAt":null,"issuedAt":"2026-10-15T00:03:00.000Z","maxActivations":null,"mode":"test","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","status":"active"},"x-payri-scope":[]}},"/v1/licenses/signing-keys":{"get":{"description":"키 식별자별 Ed25519 공개키를 조회해 라이선스 응답 서명을 검증해요.","operationId":"LicenseAppV1Controller_signingKeys","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"keys":[{"createdAt":"2026-10-01T00:00:00.000Z","kid":"2026-10","publicKey":"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="}]},"schema":{"$ref":"#/components/schemas/V1LicenseSigningKeysResponse"}}},"description":"요청 결과를 반환해요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"summary":"라이선스 서명 공개키 조회","tags":["라이선스 앱 API"],"x-payri-error-codes":["INTERNAL_ERROR"],"x-payri-mode-isolated":false,"x-payri-request-example":{"headers":{},"method":"GET","url":"https://api.payri.kr/v1/licenses/signing-keys"},"x-payri-response-example":{"keys":[{"createdAt":"2026-10-01T00:00:00.000Z","kid":"2026-10","publicKey":"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="}]},"x-payri-scope":[]}},"/v1/licenses/verify":{"post":{"description":"상품과 라이선스 키의 상태를 검증하고 nonce가 포함된 응답에 Ed25519 서명을 붙여요.","operationId":"LicenseAppV1Controller_verify","parameters":[],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"활성화 상태 검증","value":{"activationId":"act_123","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","productId":"prod_123"}}},"schema":{"$ref":"#/components/schemas/V1LicenseVerifyRequestDto"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"activation":{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"},"activationCount":1,"expiresAt":null,"issuedAt":"2026-10-15T00:02:30.000Z","maxActivations":null,"mode":"test","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","status":"active"},"schema":{"$ref":"#/components/schemas/V1LicenseAppResponse"}}},"description":"요청 결과를 반환해요.","headers":{"Payri-Signature":{"description":"응답 본문의 Ed25519 서명이에요.","schema":{"example":"kid=2026-10, ed25519=base64...","type":"string"}}}},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"429":{"content":{"application/json":{"example":{"code":"LICENSE_RATE_LIMITED","message":"라이선스 API 호출 한도를 초과했어요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"summary":"라이선스 검증","tags":["라이선스 앱 API"],"x-payri-error-codes":["VALIDATION_FAILED","LICENSE_RATE_LIMITED","LICENSE_LOOKUP_BLOCKED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"activationId":"act_123","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","productId":"prod_123"},"headers":{"Content-Type":"application/json"},"method":"POST","url":"https://api.payri.kr/v1/licenses/verify"},"x-payri-response-example":{"activation":{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"},"activationCount":1,"expiresAt":null,"issuedAt":"2026-10-15T00:02:30.000Z","maxActivations":null,"mode":"test","nonce":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","status":"active"},"x-payri-scope":[]}},"/v1/licenses/{id}":{"get":{"description":"라이선스 식별자로 발급 정보와 활성화 정보를 조회해요.","operationId":"LicenseV1Controller_get","parameters":[{"description":"조회할 라이선스 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"lic_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"activationCount":1,"activations":[{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"}],"buyerEmail":"buyer@example.com","buyerName":"홍길동","expiresAt":null,"id":"lic_123","issuedAt":"2026-10-15T00:01:00.000Z","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","maxActivations":null,"mode":"test","orderId":"ord_123","orderItemId":"item_123","productId":"prod_123","productName":"디지털 가이드","revokeReason":null,"revokedAt":null,"rotatedFrom":null,"status":"active"},"schema":{"$ref":"#/components/schemas/V1LicenseResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"라이선스 상세 조회","tags":["라이선스"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","LICENSE_NOT_FOUND","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/licenses/lic_123"},"x-payri-response-example":{"activationCount":1,"activations":[{"activatedAt":"2026-10-15T00:02:00.000Z","deactivatedAt":null,"id":"act_123","label":"내 컴퓨터","lastVerifiedAt":"2026-10-15T00:02:30.000Z"}],"buyerEmail":"buyer@example.com","buyerName":"홍길동","expiresAt":null,"id":"lic_123","issuedAt":"2026-10-15T00:01:00.000Z","key":"PAYRI-TEST-ABCDE-FGHIJ-KLMNP-QRSTU","maxActivations":null,"mode":"test","orderId":"ord_123","orderItemId":"item_123","productId":"prod_123","productName":"디지털 가이드","revokeReason":null,"revokedAt":null,"rotatedFrom":null,"status":"active"},"x-payri-scope":["licenses:read"]}},"/v1/openapi.json":{"get":{"description":"PayRi API의 OpenAPI 3.1 JSON 문서를 조회해요.","operationId":"OpenApiV1Controller_getOpenApiDocument","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"info":{"title":"PayRi API","version":"1"},"openapi":"3.1.0"},"schema":{"type":"object"}}},"description":"OpenAPI JSON 문서를 반환해요.","headers":{"Cache-Control":{"description":"문서를 5분 동안 공개 캐시할 수 있어요.","schema":{"example":"public, max-age=300","type":"string"}}}},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"summary":"OpenAPI 문서 조회","tags":["명세"],"x-payri-error-codes":["INTERNAL_ERROR"],"x-payri-mode-isolated":false,"x-payri-request-example":{"headers":{},"method":"GET","url":"https://api.payri.kr/v1/openapi.json"},"x-payri-response-example":{"info":{"title":"PayRi API","version":"1"},"openapi":"3.1.0"},"x-payri-scope":[]}},"/v1/orders":{"get":{"description":"API 키의 test 또는 live 환경과 상품 범위에 속한 주문을 페이지 단위로 조회해요.","operationId":"OrdersV1Controller_list","parameters":[{"description":"조회할 페이지 번호예요.","in":"query","name":"page","required":false,"schema":{"default":1,"example":1,"minimum":1,"type":"number"}},{"description":"페이지마다 조회할 항목 수예요.","in":"query","name":"limit","required":false,"schema":{"default":20,"example":20,"maximum":100,"minimum":1,"type":"number"}},{"description":"구매자 이메일로 주문을 찾아요.","in":"query","name":"buyerEmail","required":false,"schema":{"example":"buyer@example.com","format":"email","type":"string"}},{"description":"주문 상태로 결과를 좁혀요.","in":"query","name":"status","required":false,"schema":{"enum":["pending","paid","failed","refunded"],"example":"paid","type":"string"}},{"description":"상품 식별자로 주문을 좁혀요.","in":"query","name":"productId","required":false,"schema":{"example":"prod_123","type":"string"}},{"description":"결제 세션 식별자로 주문을 좁혀요.","in":"query","name":"checkoutSessionId","required":false,"schema":{"example":"cs_123","type":"string"}},{"description":"이 시각 이후 생성된 주문을 조회해요.","in":"query","name":"createdFrom","required":false,"schema":{"example":"2026-10-01T00:00:00.000Z","format":"date-time","type":"string"}},{"description":"이 시각 이전 생성된 주문을 조회해요.","in":"query","name":"createdTo","required":false,"schema":{"example":"2026-10-15T00:00:00.000Z","format":"date-time","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":0,"refundedAt":null,"refunds":[],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"}],"limit":20,"page":1,"total":1},"schema":{"$ref":"#/components/schemas/V1OrderPageResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"주문 목록 조회","tags":["주문"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/orders?page=1&limit=20&status=paid"},"x-payri-response-example":{"data":[{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":0,"refundedAt":null,"refunds":[],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"}],"limit":20,"page":1,"total":1},"x-payri-scope":["orders:read"]}},"/v1/orders/{id}":{"get":{"description":"주문 식별자로 상세 정보와 환불 내역을 조회해요.","operationId":"OrdersV1Controller_get","parameters":[{"description":"조회할 주문 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"ord_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":0,"refundedAt":null,"refunds":[],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"schema":{"$ref":"#/components/schemas/V1OrderResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"주문 상세 조회","tags":["주문"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","ORDER_NOT_FOUND","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/orders/ord_123"},"x-payri-response-example":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":0,"refundedAt":null,"refunds":[],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"x-payri-scope":["orders:read"]}},"/v1/orders/{id}/refund":{"post":{"description":"전액 또는 부분 환불을 요청해요. Idempotency-Key를 24시간 기억하며 같은 키에 다른 본문을 보내면 409 응답을 돌려줘요.","operationId":"OrdersV1Controller_refund","parameters":[{"description":"환불할 주문 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"ord_123","type":"string"}},{"description":"POST 요청의 중복 실행을 막는 키예요. 24시간 보관하며 본문이 다른 요청에는 같은 키를 쓸 수 없어요.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"부분 환불 요청","value":{"amount":5000,"reason":"고객 요청"}}},"schema":{"$ref":"#/components/schemas/V1RefundOrderDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":5000,"refundedAt":null,"refunds":[{"amount":5000,"at":"2026-10-15T00:02:00.000Z","currency":"KRW","reason":"고객 요청"}],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"schema":{"$ref":"#/components/schemas/V1OrderResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"주문 환불","tags":["주문"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","ORDER_NOT_FOUND","REFUND_NOT_PAID","REFUND_REQUEST_PENDING","REFUND_SETTLED","REFUND_NONE_LEFT","REFUND_AMOUNT_INVALID","REFUND_EXCEEDS","REFUND_IN_PROGRESS","PG_REFUND_FAILED","PG_REFUND_AMBIGUOUS","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_IN_PROGRESS","INTERNAL_ERROR"],"x-payri-idempotent":true,"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"amount":5000,"reason":"고객 요청"},"headers":{"Idempotency-Key":"refund-ord-123-001"},"method":"POST","url":"https://api.payri.kr/v1/orders/ord_123/refund"},"x-payri-response-example":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":5000,"refundedAt":null,"refunds":[{"amount":5000,"at":"2026-10-15T00:02:00.000Z","currency":"KRW","reason":"고객 요청"}],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"x-payri-scope":["refunds:write"]}},"/v1/portal-sessions":{"post":{"description":"구독 식별자 또는 구매자 이메일로 제한된 구매자 포털 세션을 만들어요. Idempotency-Key는 24시간 보관해요.","operationId":"PortalSessionsV1Controller_create","parameters":[{"description":"POST 요청의 중복 실행을 막는 키예요. 24시간 보관하며 본문이 다른 요청에는 같은 키를 쓸 수 없어요.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"구독 기반 포털 세션","value":{"returnUrl":"https://shop.example.com/account","subscriptionId":"sub_123"}}},"schema":{"$ref":"#/components/schemas/CreatePortalSessionV1Dto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"expiresAt":"2026-10-15T01:00:00.000Z","mode":"test","token":"eyJhbGciOi...","url":"https://payri.kr/portal#token=eyJhbGciOi..."},"schema":{"$ref":"#/components/schemas/V1PortalSessionResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"구매자 포털 세션 생성","tags":["포털 세션"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","BAD_REQUEST","NOT_FOUND","SUBSCRIPTION_NOT_FOUND","CHECKOUT_URL_INVALID","RETURN_URL_NOT_ALLOWED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_IN_PROGRESS","INTERNAL_ERROR"],"x-payri-idempotent":true,"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"returnUrl":"https://shop.example.com/account","subscriptionId":"sub_123"},"headers":{"Idempotency-Key":"portal-sub-123-001"},"method":"POST","url":"https://api.payri.kr/v1/portal-sessions"},"x-payri-response-example":{"expiresAt":"2026-10-15T01:00:00.000Z","mode":"test","token":"eyJhbGciOi...","url":"https://payri.kr/portal#token=eyJhbGciOi..."},"x-payri-scope":["subscriptions:write"]}},"/v1/products":{"get":{"description":"API 키의 test 또는 live 환경과 공개 상품 범위에 속한 상품을 페이지 단위로 조회해요.","operationId":"ProductsV1Controller_list","parameters":[{"description":"조회할 페이지 번호예요.","in":"query","name":"page","required":false,"schema":{"default":1,"example":1,"minimum":1,"type":"number"}},{"description":"페이지마다 조회할 항목 수예요.","in":"query","name":"limit","required":false,"schema":{"default":20,"example":20,"maximum":100,"minimum":1,"type":"number"}},{"description":"상품 상태로 결과를 좁혀요.","in":"query","name":"status","required":false,"schema":{"enum":["draft","active","archived"],"example":"active","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"contents":[{"label":"가이드 PDF","type":"file"}],"createdAt":"2026-10-01T00:00:00.000Z","deliverable":{"fileName":"guide.pdf","fileSize":102400,"licenseIssuance":null,"maxActivations":null,"note":null,"type":"file"},"description":"상품 상세 설명이에요.","displayOrder":0,"icon":"","iconColor":null,"id":"prod_123","imageUrl":null,"linkId":"link_123","listed":true,"mode":"test","name":"디지털 가이드","pricing":{"amount":10000,"currency":"KRW","interval":null,"plans":null,"type":"one_time"},"refundPolicy":{"customText":null,"requireApproval":false,"subscription":null,"type":"within_7days"},"saleEndsAt":null,"saleStartsAt":null,"status":"active","stockLimit":null,"summary":"바로 내려받는 가이드예요."}],"limit":20,"page":1,"total":1},"schema":{"$ref":"#/components/schemas/V1ProductPageResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"상품 목록 조회","tags":["상품"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/products?page=1&limit=20&status=active"},"x-payri-response-example":{"data":[{"contents":[{"label":"가이드 PDF","type":"file"}],"createdAt":"2026-10-01T00:00:00.000Z","deliverable":{"fileName":"guide.pdf","fileSize":102400,"licenseIssuance":null,"maxActivations":null,"note":null,"type":"file"},"description":"상품 상세 설명이에요.","displayOrder":0,"icon":"","iconColor":null,"id":"prod_123","imageUrl":null,"linkId":"link_123","listed":true,"mode":"test","name":"디지털 가이드","pricing":{"amount":10000,"currency":"KRW","interval":null,"plans":null,"type":"one_time"},"refundPolicy":{"customText":null,"requireApproval":false,"subscription":null,"type":"within_7days"},"saleEndsAt":null,"saleStartsAt":null,"status":"active","stockLimit":null,"summary":"바로 내려받는 가이드예요."}],"limit":20,"page":1,"total":1},"x-payri-scope":["products:read"]}},"/v1/products/{id}":{"get":{"description":"상품 식별자로 가격과 전달 정보를 조회해요.","operationId":"ProductsV1Controller_get","parameters":[{"description":"조회할 상품 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"prod_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"contents":[{"label":"가이드 PDF","type":"file"}],"createdAt":"2026-10-01T00:00:00.000Z","deliverable":{"fileName":"guide.pdf","fileSize":102400,"licenseIssuance":null,"maxActivations":null,"note":null,"type":"file"},"description":"상품 상세 설명이에요.","displayOrder":0,"icon":"","iconColor":null,"id":"prod_123","imageUrl":null,"linkId":"link_123","listed":true,"mode":"test","name":"디지털 가이드","pricing":{"amount":10000,"currency":"KRW","interval":null,"plans":null,"type":"one_time"},"refundPolicy":{"customText":null,"requireApproval":false,"subscription":null,"type":"within_7days"},"saleEndsAt":null,"saleStartsAt":null,"status":"active","stockLimit":null,"summary":"바로 내려받는 가이드예요."},"schema":{"$ref":"#/components/schemas/V1ProductResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"상품 상세 조회","tags":["상품"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","PRODUCT_NOT_FOUND","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/products/prod_123"},"x-payri-response-example":{"contents":[{"label":"가이드 PDF","type":"file"}],"createdAt":"2026-10-01T00:00:00.000Z","deliverable":{"fileName":"guide.pdf","fileSize":102400,"licenseIssuance":null,"maxActivations":null,"note":null,"type":"file"},"description":"상품 상세 설명이에요.","displayOrder":0,"icon":"","iconColor":null,"id":"prod_123","imageUrl":null,"linkId":"link_123","listed":true,"mode":"test","name":"디지털 가이드","pricing":{"amount":10000,"currency":"KRW","interval":null,"plans":null,"type":"one_time"},"refundPolicy":{"customText":null,"requireApproval":false,"subscription":null,"type":"within_7days"},"saleEndsAt":null,"saleStartsAt":null,"status":"active","stockLimit":null,"summary":"바로 내려받는 가이드예요."},"x-payri-scope":["products:read"]}},"/v1/refund-requests":{"get":{"description":"API 키의 test 또는 live 환경에 속한 환불 요청을 페이지 단위로 조회해요.","operationId":"RefundRequestsV1Controller_list","parameters":[{"description":"조회할 페이지 번호예요.","in":"query","name":"page","required":false,"schema":{"default":1,"example":1,"minimum":1,"type":"number"}},{"description":"페이지마다 조회할 항목 수예요.","in":"query","name":"limit","required":false,"schema":{"default":20,"example":20,"maximum":100,"minimum":1,"type":"number"}},{"description":"환불 요청 상태로 결과를 좁혀요.","in":"query","name":"status","required":false,"schema":{"enum":["requested","on_hold","processing","approved","rejected","withdrawn"],"example":"requested","type":"string"}},{"description":"주문 식별자로 환불 요청을 좁혀요.","in":"query","name":"orderId","required":false,"schema":{"example":"ord_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]}],"limit":20,"page":1,"total":1},"schema":{"$ref":"#/components/schemas/V1RefundRequestPageResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"환불 요청 목록 조회","tags":["환불 요청"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/refund-requests?page=1&limit=20&status=requested"},"x-payri-response-example":{"data":[{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]}],"limit":20,"page":1,"total":1},"x-payri-scope":["refunds:read"]}},"/v1/refund-requests/{id}":{"get":{"description":"환불 요청 식별자로 요청, 결정과 환불 계산 정보를 조회해요.","operationId":"RefundRequestsV1Controller_get","parameters":[{"description":"조회할 환불 요청 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"rfr_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"schema":{"$ref":"#/components/schemas/V1RefundRequestResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"환불 요청 상세 조회","tags":["환불 요청"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","REFUND_REQUEST_NOT_FOUND","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/refund-requests/rfr_123"},"x-payri-response-example":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"x-payri-scope":["refunds:read"]}},"/v1/refund-requests/{id}/approve":{"post":{"description":"환불 요청을 승인해요. Idempotency-Key는 24시간 보관해요.","operationId":"RefundRequestsV1Controller_approve","parameters":[{"description":"승인할 환불 요청 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"rfr_123","type":"string"}},{"description":"POST 요청의 중복 실행을 막는 키예요. 24시간 보관하며 본문이 다른 요청에는 같은 키를 쓸 수 없어요.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"환불 요청 승인","value":{"acknowledgeMismatch":true,"amount":10000}}},"schema":{"$ref":"#/components/schemas/V1RefundRequestApproveDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"refundRequest":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"warnings":[]},"schema":{"$ref":"#/components/schemas/V1RefundActionResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"환불 요청 승인","tags":["환불 요청"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","REFUND_REQUEST_NOT_FOUND","REFUND_REQUEST_NOT_ACTIONABLE","REFUND_STATUTORY_LOCKED","REFUND_AMOUNT_INVALID","REFUND_AMOUNT_EXCEEDS","REFUND_AMOUNT_MISMATCH","ORDER_NOT_FOUND","REFUND_NOT_PAID","REFUND_SETTLED","REFUND_NONE_LEFT","REFUND_EXCEEDS","REFUND_IN_PROGRESS","PG_REFUND_FAILED","PG_REFUND_AMBIGUOUS","SUBSCRIPTION_REFUND_AMOUNT_INVALID","SUBSCRIPTION_REFUND_NONE_LEFT","SUBSCRIPTION_REFUND_SETTLED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_IN_PROGRESS","INTERNAL_ERROR"],"x-payri-idempotent":true,"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"acknowledgeMismatch":true,"amount":10000},"headers":{"Idempotency-Key":"approve-rfr-123-001"},"method":"POST","url":"https://api.payri.kr/v1/refund-requests/rfr_123/approve"},"x-payri-response-example":{"refundRequest":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"warnings":[]},"x-payri-scope":["refunds:write"]}},"/v1/refund-requests/{id}/hold":{"post":{"description":"추가 확인이 필요한 환불 요청을 보류해요. Idempotency-Key는 24시간 보관해요.","operationId":"RefundRequestsV1Controller_hold","parameters":[{"description":"보류할 환불 요청 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"rfr_123","type":"string"}},{"description":"POST 요청의 중복 실행을 막는 키예요. 24시간 보관하며 본문이 다른 요청에는 같은 키를 쓸 수 없어요.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"검토 중 보류","value":{"reason":"구매 내역을 확인 중이에요.","type":"in_review"}}},"schema":{"$ref":"#/components/schemas/V1RefundRequestHoldDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"refundRequest":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"warnings":[]},"schema":{"$ref":"#/components/schemas/V1RefundActionResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"환불 요청 보류","tags":["환불 요청"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","REFUND_REQUEST_NOT_FOUND","REFUND_REQUEST_NOT_ACTIONABLE","REFUND_STATUTORY_LOCKED","REFUND_REASON_REQUIRED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_IN_PROGRESS","INTERNAL_ERROR"],"x-payri-idempotent":true,"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"reason":"구매 내역을 확인 중이에요.","type":"in_review"},"headers":{"Idempotency-Key":"hold-rfr-123-001"},"method":"POST","url":"https://api.payri.kr/v1/refund-requests/rfr_123/hold"},"x-payri-response-example":{"refundRequest":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"warnings":[]},"x-payri-scope":["refunds:write"]}},"/v1/refund-requests/{id}/reject":{"post":{"description":"환불 요청을 거절하고 사유를 기록해요. Idempotency-Key는 24시간 보관해요.","operationId":"RefundRequestsV1Controller_reject","parameters":[{"description":"거절할 환불 요청 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"rfr_123","type":"string"}},{"description":"POST 요청의 중복 실행을 막는 키예요. 24시간 보관하며 본문이 다른 요청에는 같은 키를 쓸 수 없어요.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"거절 사유","value":{"reason":"환불 정책상 처리할 수 없어요."}}},"schema":{"$ref":"#/components/schemas/V1RefundRequestRejectDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"refundRequest":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"warnings":[]},"schema":{"$ref":"#/components/schemas/V1RefundActionResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"환불 요청 거절","tags":["환불 요청"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","REFUND_REQUEST_NOT_FOUND","REFUND_REQUEST_NOT_ACTIONABLE","REFUND_STATUTORY_LOCKED","REFUND_REASON_REQUIRED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_IN_PROGRESS","INTERNAL_ERROR"],"x-payri-idempotent":true,"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"reason":"환불 정책상 처리할 수 없어요."},"headers":{"Idempotency-Key":"reject-rfr-123-001"},"method":"POST","url":"https://api.payri.kr/v1/refund-requests/rfr_123/reject"},"x-payri-response-example":{"refundRequest":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"warnings":[]},"x-payri-scope":["refunds:write"]}},"/v1/subscriptions":{"get":{"description":"API 키의 test 또는 live 환경과 상품 범위에 속한 구독을 페이지 단위로 조회해요.","operationId":"SubscriptionsV1Controller_list","parameters":[{"description":"조회할 페이지 번호예요.","in":"query","name":"page","required":false,"schema":{"default":1,"example":1,"minimum":1,"type":"number"}},{"description":"페이지마다 조회할 항목 수예요.","in":"query","name":"limit","required":false,"schema":{"default":20,"example":20,"maximum":100,"minimum":1,"type":"number"}},{"description":"구매자 이메일로 구독을 찾아요.","in":"query","name":"buyerEmail","required":false,"schema":{"example":"buyer@example.com","format":"email","type":"string"}},{"description":"구독의 공개 상태로 결과를 좁혀요. 결제가 밀린 채 해지를 예약한 구독도 past_due 로 조회돼요.","in":"query","name":"status","required":false,"schema":{"enum":["active","past_due","ended"],"example":"active","type":"string"}},{"description":"상품 식별자로 구독을 좁혀요.","in":"query","name":"productId","required":false,"schema":{"example":"prod_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"}],"limit":20,"page":1,"total":1},"schema":{"$ref":"#/components/schemas/V1SubscriptionPageResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"구독 목록 조회","tags":["구독"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/subscriptions?page=1&limit=20&status=active"},"x-payri-response-example":{"data":[{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"}],"limit":20,"page":1,"total":1},"x-payri-scope":["subscriptions:read"]}},"/v1/subscriptions/{id}":{"get":{"description":"구독의 공개 상태, 청구 기간과 예약 변경 정보를 조회해요.","operationId":"SubscriptionsV1Controller_get","parameters":[{"description":"조회할 구독 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"sub_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"schema":{"$ref":"#/components/schemas/V1SubscriptionResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"구독 상세 조회","tags":["구독"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","SUBSCRIPTION_NOT_FOUND","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/subscriptions/sub_123"},"x-payri-response-example":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"x-payri-scope":["subscriptions:read"]}},"/v1/subscriptions/{id}/cancel":{"post":{"description":"기간 종료 시점 또는 즉시 해지해요. timing은 필수예요. Idempotency-Key는 24시간 보관해요.","operationId":"SubscriptionsV1Controller_cancel","parameters":[{"description":"해지할 구독 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"sub_123","type":"string"}},{"description":"POST 요청의 중복 실행을 막는 키예요. 24시간 보관하며 본문이 다른 요청에는 같은 키를 쓸 수 없어요.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"기간 종료 시 해지","value":{"reason":"이용 종료","timing":"period_end"}}},"schema":{"$ref":"#/components/schemas/V1CancelSubscriptionDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"example":{"currency":"KRW","refundAmount":0,"refundOrderId":null,"refundedOrderIds":[],"subscription":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":true,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":{"billingInterval":null,"effectiveAt":"2026-11-01T00:00:00.000Z","planId":null,"type":"cancel"},"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"timing":"period_end"},"schema":{"$ref":"#/components/schemas/V1CancelResultResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"구독 해지","tags":["구독"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","VALIDATION_FAILED","SUBSCRIPTION_NOT_FOUND","REFUND_REQUEST_PENDING","REFUND_IN_PROGRESS","SUBSCRIPTION_REFUND_SETTLED","SUBSCRIPTION_REFUND_NONE_LEFT","ORDER_NOT_FOUND","PG_REFUND_FAILED","PG_REFUND_AMBIGUOUS","ALREADY_ENDED","ALREADY_CANCELED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_IN_PROGRESS","INTERNAL_ERROR"],"x-payri-idempotent":true,"x-payri-mode-isolated":true,"x-payri-request-example":{"body":{"reason":"이용 종료","timing":"period_end"},"headers":{"Idempotency-Key":"cancel-sub-123-001"},"method":"POST","url":"https://api.payri.kr/v1/subscriptions/sub_123/cancel"},"x-payri-response-example":{"currency":"KRW","refundAmount":0,"refundOrderId":null,"refundedOrderIds":[],"subscription":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":true,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":{"billingInterval":null,"effectiveAt":"2026-11-01T00:00:00.000Z","planId":null,"type":"cancel"},"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"timing":"period_end"},"x-payri-scope":["subscriptions:write"]}},"/v1/subscriptions/{id}/cancel-preview":{"get":{"description":"기간 종료 해지와 즉시 해지의 적용 시점과 환불 금액을 비교해요.","operationId":"SubscriptionsV1Controller_previewCancel","parameters":[{"description":"미리보기할 구독 식별자예요.","in":"path","name":"id","required":true,"schema":{"example":"sub_123","type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"immediate":{"blockedReason":null,"breakdown":[{"amount":5000,"currency":"KRW","orderId":"ord_123"}],"clawback":0,"clawbackCurrency":"KRW","currency":"KRW","deduction":0,"deductionCap":0,"deductionCapCurrency":"KRW","deductionCurrency":"KRW","fullRefund":false,"penalty":0,"penaltyCurrency":"KRW","reason":"prorated","refundAmount":5000,"requiresApproval":false,"statutory":false,"totalDays":30,"usedDays":5},"mode":"test","pendingRefundRequest":null,"periodEnd":{"effectiveAt":"2026-11-01T00:00:00.000Z"}},"schema":{"$ref":"#/components/schemas/V1CancelPreviewResponse"}}},"description":"요청 결과를 반환해요."},"400":{"content":{"application/json":{"example":{"code":"VALIDATION_FAILED","details":{"fields":[{"field":"productId","message":"필수 값이에요."}]},"message":"요청 필드를 확인해 주세요.","statusCode":400},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청 값이 올바르지 않아요."},"401":{"content":{"application/json":{"example":{"code":"API_KEY_INVALID","message":"API 키가 없거나 올바르지 않아요.","statusCode":401},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"API 키가 없거나 올바르지 않아요."},"403":{"content":{"application/json":{"example":{"code":"API_KEY_SCOPE_MISSING","details":{"required":["orders:read"]},"message":"요청에 필요한 권한이 없어요.","statusCode":403},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"키의 IP 주소가 허용되지 않거나 필요한 권한이 없어요."},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","message":"요청한 리소스를 찾을 수 없어요.","statusCode":404},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청한 리소스를 찾을 수 없어요."},"409":{"content":{"application/json":{"example":{"code":"IDEMPOTENCY_KEY_CONFLICT","message":"같은 Idempotency-Key 를 다른 요청에 사용할 수 없어요.","statusCode":409},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"현재 상태에서 처리할 수 없거나 멱등키 충돌이 있어요."},"429":{"content":{"application/json":{"example":{"code":"RATE_LIMITED","message":"잠시 후 다시 시도해 주세요.","statusCode":429},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"호출 한도를 초과했어요."},"500":{"content":{"application/json":{"example":{"code":"INTERNAL_ERROR","message":"요청을 처리하는 중 오류가 발생했어요.","statusCode":500},"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"요청을 처리하는 중 오류가 발생했어요."}},"security":[{"bearerAuth":[]}],"summary":"구독 해지 미리보기","tags":["구독"],"x-payri-error-codes":["API_KEY_INVALID","API_KEY_IP_NOT_ALLOWED","API_KEY_SCOPE_MISSING","RATE_LIMITED","SUBSCRIPTION_NOT_FOUND","INTERNAL_ERROR"],"x-payri-mode-isolated":true,"x-payri-request-example":{"headers":{"Authorization":"Bearer <API key>"},"method":"GET","url":"https://api.payri.kr/v1/subscriptions/sub_123/cancel-preview"},"x-payri-response-example":{"immediate":{"blockedReason":null,"breakdown":[{"amount":5000,"currency":"KRW","orderId":"ord_123"}],"clawback":0,"clawbackCurrency":"KRW","currency":"KRW","deduction":0,"deductionCap":0,"deductionCapCurrency":"KRW","deductionCurrency":"KRW","fullRefund":false,"penalty":0,"penaltyCurrency":"KRW","reason":"prorated","refundAmount":5000,"requiresApproval":false,"statutory":false,"totalDays":30,"usedDays":5},"mode":"test","pendingRefundRequest":null,"periodEnd":{"effectiveAt":"2026-11-01T00:00:00.000Z"}},"x-payri-scope":["subscriptions:read"]}}},"servers":[{"description":"운영 서버예요.","url":"https://api.payri.kr"}],"tags":[],"webhooks":{"license.issue":{"post":{"description":"판매자가 발급한 라이선스 키가 필요한 상품의 결제 뒤 동기 발급을 요청해요. 응답 처리가 5회 모두 실패하면 라이선스 상태를 failed로 바꿔요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_license_issue","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"license.issue 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"buyer":{"email":"buyer@example.com","name":"홍길동"},"expiresAt":null,"interval":null,"licenseId":"lic_123","maxActivations":null,"mode":"test","orderId":"ord_123","planId":null,"productId":"prod_123"},"id":"evt_123","mode":"test","type":"license.issue"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_license_issue"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"expiresAt":"2027-10-15T00:00:00.000Z","key":"VENDOR-12345-ABCDE","maxActivations":3},"schema":{"$ref":"#/components/schemas/V1LicenseIssueResponse"}}},"description":"라이선스 키를 동기 응답으로 전달해요."}},"security":[],"summary":"license.issue","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"buyer":{"email":"buyer@example.com","name":"홍길동"},"expiresAt":null,"interval":null,"licenseId":"lic_123","maxActivations":null,"mode":"test","orderId":"ord_123","planId":null,"productId":"prod_123"},"id":"evt_123","mode":"test","type":"license.issue"},"x-payri-response-example":{"expiresAt":"2027-10-15T00:00:00.000Z","key":"VENDOR-12345-ABCDE","maxActivations":3},"x-payri-scope":[]}},"order.paid":{"post":{"description":"최초 결제, 갱신 또는 차액 결제가 완료되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_order_paid","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"order.paid 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":0,"refundedAt":null,"refunds":[],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"id":"evt_123","mode":"test","type":"order.paid"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_order_paid"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"order.paid","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refundedAmount":0,"refundedAt":null,"refunds":[],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"id":"evt_123","mode":"test","type":"order.paid"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"order.refunded":{"post":{"description":"부분 또는 전체 환불이 확정되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_order_refunded","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"order.refunded 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refund":{"amount":5000,"currency":"KRW","id":"ref_123","reason":"고객 요청","refundedAt":"2026-10-15T00:02:00.000Z"},"refundedAmount":5000,"refundedAt":null,"refunds":[{"amount":5000,"at":"2026-10-15T00:02:00.000Z","currency":"KRW","reason":"고객 요청"}],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"id":"evt_123","mode":"test","type":"order.refunded"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_order_refunded"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"order.refunded","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":10000,"billingInterval":null,"buyerEmail":"buyer@example.com","buyerName":"홍길동","buyerPhone":"01012345678","checkoutSessionId":"cs_123","confirmedAt":null,"coupon":null,"createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","id":"ord_123","metadata":{"campaign":"fall"},"method":"card","mode":"test","paidAt":"2026-10-15T00:01:00.000Z","periodEnd":null,"periodStart":null,"planId":null,"productId":"prod_123","productName":"디지털 가이드","refund":{"amount":5000,"currency":"KRW","id":"ref_123","reason":"고객 요청","refundedAt":"2026-10-15T00:02:00.000Z"},"refundedAmount":5000,"refundedAt":null,"refunds":[{"amount":5000,"at":"2026-10-15T00:02:00.000Z","currency":"KRW","reason":"고객 요청"}],"status":"paid","subscriptionEvent":null,"subscriptionId":null,"withdrawalNoticeAgreedAt":"2026-10-15T00:00:00.000Z"},"id":"evt_123","mode":"test","type":"order.refunded"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"refund.approved":{"post":{"description":"환불 요청이 승인되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_refund_approved","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"refund.approved 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":10000,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:02:00.000Z","decidedBy":"seller","hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"approved","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:02:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.approved"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_refund_approved"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"refund.approved","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":10000,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:02:00.000Z","decidedBy":"seller","hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"approved","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:02:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.approved"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"refund.on_hold":{"post":{"description":"환불 요청 처리가 보류되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_refund_on_hold","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"refund.on_hold 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":null,"breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:01:00.000Z","decidedBy":"seller","hold":{"heldAt":"2026-10-15T00:01:00.000Z","reason":"추가 확인 중이에요.","type":"in_review"},"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"on_hold","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:01:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.on_hold"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_refund_on_hold"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"refund.on_hold","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":null,"breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:01:00.000Z","decidedBy":"seller","hold":{"heldAt":"2026-10-15T00:01:00.000Z","reason":"추가 확인 중이에요.","type":"in_review"},"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"on_hold","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:01:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.on_hold"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"refund.rejected":{"post":{"description":"환불 요청이 거절되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_refund_rejected","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"refund.rejected 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:02:00.000Z","decidedBy":"seller","hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":"환불 정책에 따라 승인할 수 없어요.","requestedAmount":10000,"status":"rejected","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:02:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.rejected"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_refund_rejected"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"refund.rejected","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:02:00.000Z","decidedBy":"seller","hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":"환불 정책에 따라 승인할 수 없어요.","requestedAmount":10000,"status":"rejected","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:02:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.rejected"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"refund.requested":{"post":{"description":"구매자가 환불을 요청하면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_refund_requested","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"refund.requested 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.requested"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_refund_requested"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"refund.requested","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":null,"decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"requested","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:00:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.requested"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"refund.withdrawn":{"post":{"description":"구매자가 환불 요청을 철회하면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_refund_withdrawn","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"refund.withdrawn 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:02:00.000Z","decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"withdrawn","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:02:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.withdrawn"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_refund_withdrawn"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"refund.withdrawn","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"approvedAmount":null,"autoApproveAt":"2026-10-18T00:00:00.000Z","breakdown":{"orders":[{"amount":10000,"currency":"KRW","orderId":"ord_123"}]},"buyerEmail":"buyer@example.com","buyerReason":"상품을 환불하고 싶어요.","createdAt":"2026-10-15T00:00:00.000Z","currency":"KRW","decidedAt":"2026-10-15T00:02:00.000Z","decidedBy":null,"hold":null,"id":"rfr_123","kind":"order","mode":"test","orderId":"ord_123","productId":"prod_123","refundableAmount":10000,"rejectReason":null,"requestedAmount":10000,"status":"withdrawn","statutory":true,"subscriptionId":null,"updatedAt":"2026-10-15T00:02:00.000Z","warnings":[]},"id":"evt_123","mode":"test","type":"refund.withdrawn"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"subscription.created":{"post":{"description":"새 구독이 생성되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_subscription_created","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"subscription.created 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"change":{"amount":null,"currency":null,"effectiveAt":null,"extensionDays":null,"from":null,"kind":"created","orderId":null,"prorationAmount":null,"to":null},"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"id":"evt_123","mode":"test","type":"subscription.created"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_subscription_created"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"subscription.created","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"change":{"amount":null,"currency":null,"effectiveAt":null,"extensionDays":null,"from":null,"kind":"created","orderId":null,"prorationAmount":null,"to":null},"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"id":"evt_123","mode":"test","type":"subscription.created"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"subscription.ended":{"post":{"description":"구독이 종료되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_subscription_ended","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"subscription.ended 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":"refunded","endedAt":"2026-10-15T00:02:00.000Z","history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundAmount":10000,"refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"ended","testRenewalOutcome":"succeed"},"id":"evt_123","mode":"test","type":"subscription.ended"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_subscription_ended"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"subscription.ended","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":"refunded","endedAt":"2026-10-15T00:02:00.000Z","history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundAmount":10000,"refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"ended","testRenewalOutcome":"succeed"},"id":"evt_123","mode":"test","type":"subscription.ended"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"subscription.payment_failed":{"post":{"description":"구독 갱신 결제가 실패하면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_subscription_payment_failed","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"subscription.payment_failed 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"attempts":2,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":"2026-10-15T00:02:00.000Z","pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"past_due","testRenewalOutcome":"fail"},"id":"evt_123","mode":"test","type":"subscription.payment_failed"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_subscription_payment_failed"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"subscription.payment_failed","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"attempts":2,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":"2026-10-15T00:02:00.000Z","pendingPriceChange":null,"planId":"plan_basic","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"past_due","testRenewalOutcome":"fail"},"id":"evt_123","mode":"test","type":"subscription.payment_failed"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"subscription.updated":{"post":{"description":"플랜, 주기, 기간 또는 해지 예약이 변경되면 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_subscription_updated","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"subscription.updated 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"change":{"amount":9900,"currency":"KRW","effectiveAt":null,"extensionDays":null,"from":{"billingInterval":"monthly","planId":"plan_basic"},"kind":"plan_changed","orderId":null,"prorationAmount":0,"to":{"billingInterval":"monthly","planId":"plan_pro"}},"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_pro","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"id":"evt_123","mode":"test","type":"subscription.updated"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_subscription_updated"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"subscription.updated","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"amount":9900,"billingInterval":"monthly","buyerEmail":"buyer@example.com","buyerName":"홍길동","cancelAtPeriodEnd":false,"change":{"amount":9900,"currency":"KRW","effectiveAt":null,"extensionDays":null,"from":{"billingInterval":"monthly","planId":"plan_basic"},"kind":"plan_changed","orderId":null,"prorationAmount":0,"to":{"billingInterval":"monthly","planId":"plan_pro"}},"currency":"KRW","currentPeriodEnd":"2026-11-01T00:00:00.000Z","currentPeriodStart":"2026-10-01T00:00:00.000Z","endReason":null,"endedAt":null,"history":[],"id":"sub_123","mode":"test","pastDueSince":null,"pendingPriceChange":null,"planId":"plan_pro","productId":"prod_123","productName":"멤버십","refundEligibleUntil":"2026-10-08T00:00:00.000Z","refundTerms":{"dayRounding":"ceil","initialFullRefundDays":7,"listAmounts":null,"penalty":null,"policyType":"within_7days","renewalFullRefundDays":7,"requireApproval":false,"restrictRepeatFullRefund":false,"yearlyDiscountClawback":false},"scheduledChange":null,"startedAt":"2026-10-01T00:00:00.000Z","status":"active","testRenewalOutcome":"succeed"},"id":"evt_123","mode":"test","type":"subscription.updated"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}},"webhook.test":{"post":{"description":"콘솔에서 테스트 발송을 요청하면 실제 이벤트와 구분되는 테스트 이벤트를 보내요. 본문과 data의 mode는 test 또는 live예요.","operationId":"webhook_webhook_test","parameters":[{"description":"이벤트 ID예요. 본문 id와 같고 재시도에도 유지돼요.","in":"header","name":"webhook-id","required":true,"schema":{"example":"evt_123","type":"string"}},{"description":"서명 시각을 초 단위 문자열로 전달해요.","in":"header","name":"webhook-timestamp","required":true,"schema":{"example":"1792022400","type":"string"}},{"description":"HMAC-SHA256 v1 서명 목록이에요.","in":"header","name":"webhook-signature","required":true,"schema":{"example":"v1,base64...","type":"string"}}],"requestBody":{"content":{"application/json":{"examples":{"default":{"summary":"webhook.test 이벤트 예시","value":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"endpointId":"wh_123","mode":"test","sentAt":"2026-10-15T00:00:00.000Z"},"id":"evt_123","mode":"test","type":"webhook.test"}}},"schema":{"$ref":"#/components/schemas/V1WebhookEnvelope_webhook_test"}}},"required":true},"responses":{"2XX":{"content":{"application/json":{"example":{"received":true},"schema":{"type":"object"}}},"description":"이벤트를 수신했어요."}},"security":[],"summary":"webhook.test","x-payri-error-codes":[],"x-payri-mode-isolated":true,"x-payri-request-example":{"createdAt":"2026-10-15T00:00:00.000Z","data":{"endpointId":"wh_123","mode":"test","sentAt":"2026-10-15T00:00:00.000Z"},"id":"evt_123","mode":"test","type":"webhook.test"},"x-payri-response-example":{"received":true},"x-payri-scope":[]}}},"x-payri-error-catalog":{"ALREADY_CANCELED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"ALREADY_ENDED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"API_KEY_INVALID":{"generic":true,"message":"API 키가 없거나 올바르지 않아요.","status":401},"API_KEY_IP_NOT_ALLOWED":{"message":"허용된 IP 주소에서 요청해야 해요.","status":403},"API_KEY_SCOPE_MISSING":{"message":"요청에 필요한 권한이 없어요.","status":403},"BAD_REQUEST":{"generic":true,"message":"요청 필드를 확인해 주세요.","status":400},"CHECKOUT_NOT_CONFIGURED":{"message":"요청을 처리하는 중 오류가 발생했어요.","status":500},"CHECKOUT_SESSION_NOT_FOUND":{"message":"요청한 리소스를 찾을 수 없어요.","status":404},"CHECKOUT_URL_INVALID":{"message":"요청 필드를 확인해 주세요.","status":400},"ENDED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"IDEMPOTENCY_IN_PROGRESS":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"IDEMPOTENCY_KEY_CONFLICT":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"INTERNAL_ERROR":{"generic":true,"message":"요청을 처리하는 중 오류가 발생했어요.","status":500},"LICENSE_LOOKUP_BLOCKED":{"message":"API 키 호출 한도를 초과했어요. 잠시 후 다시 시도해 주세요.","status":429},"LICENSE_NOT_FOUND":{"message":"요청한 리소스를 찾을 수 없어요.","status":404},"LICENSE_RATE_LIMITED":{"message":"API 키 호출 한도를 초과했어요. 잠시 후 다시 시도해 주세요.","status":429},"METADATA_INVALID":{"message":"요청 필드를 확인해 주세요.","status":400},"NOT_FOUND":{"generic":true,"message":"요청한 리소스를 찾을 수 없어요.","status":404},"NOT_STARTED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"ORDER_NOT_FOUND":{"message":"요청한 리소스를 찾을 수 없어요.","status":404},"PG_REFUND_AMBIGUOUS":{"message":"요청을 처리하는 중 오류가 발생했어요.","status":502},"PG_REFUND_FAILED":{"message":"요청을 처리하는 중 오류가 발생했어요.","status":502},"PRODUCT_ARCHIVED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"PRODUCT_NOT_FOUND":{"message":"요청한 리소스를 찾을 수 없어요.","status":404},"PUBLIC_CONTACT_VERIFICATION_REQUIRED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"RATE_LIMITED":{"generic":true,"message":"API 키 호출 한도를 초과했어요. 잠시 후 다시 시도해 주세요.","status":429},"REFUND_AMOUNT_EXCEEDS":{"message":"요청 필드를 확인해 주세요.","status":400},"REFUND_AMOUNT_INVALID":{"message":"요청 필드를 확인해 주세요.","status":400},"REFUND_AMOUNT_MISMATCH":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"REFUND_EXCEEDS":{"message":"요청 필드를 확인해 주세요.","status":400},"REFUND_IN_PROGRESS":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"REFUND_NONE_LEFT":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"REFUND_NOT_PAID":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"REFUND_REASON_REQUIRED":{"message":"요청 필드를 확인해 주세요.","status":400},"REFUND_REQUEST_NOT_ACTIONABLE":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"REFUND_REQUEST_NOT_FOUND":{"message":"요청한 리소스를 찾을 수 없어요.","status":404},"REFUND_REQUEST_PENDING":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"REFUND_SETTLED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"REFUND_STATUTORY_LOCKED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"RETURN_URL_NOT_ALLOWED":{"message":"요청 필드를 확인해 주세요.","status":400},"SOLD_OUT":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"SUBSCRIPTION_NOT_FOUND":{"message":"요청한 리소스를 찾을 수 없어요.","status":404},"SUBSCRIPTION_REFUND_AMOUNT_INVALID":{"message":"요청 필드를 확인해 주세요.","status":400},"SUBSCRIPTION_REFUND_NONE_LEFT":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"SUBSCRIPTION_REFUND_SETTLED":{"message":"요청을 현재 상태에서 처리할 수 없어요.","status":409},"VALIDATION_FAILED":{"generic":true,"message":"요청 필드를 확인해 주세요.","status":400}}}