runlot
ReferenceAPI

billing

billing 범주의 API 작업 6개를 안내합니다.

MethodPathDescription
POST/v1/hooks/polarPolar 결제 웹훅 (docs/billing.md)
GET/v1/orgs/{orgSlug}/billing조직의 요금제와 결제 상태 (docs/billing.md)
POST/v1/orgs/{orgSlug}/billing/checkout프로 요금제 체크아웃 세션을 만든다
POST/v1/orgs/{orgSlug}/billing/portal고객 포털 세션을 만든다 (결제 수단·영수증·해지)
POST/v1/orgs/{orgSlug}/billing/session고객 세션 토큰 (결제 수단 임베드의 인증)
POST/v1/orgs/{orgSlug}/billing/cancel기간 끝 해지를 예약하거나 되돌린다

POST /v1/hooks/polar

사용자가 부르는 경로가 아니다. Polar 가 구독 사건을 여기에 배달한다. 인증은 토큰이 아니라 Standard Webhooks 서명이다 — webhook-id· webhook-timestamp·webhook-signature 셋과 서버의 RUNLOT_POLAR_WEBHOOK_SECRET 으로 검증한다 (아니면 403, 시각 ±5 분). 같은 webhook-id 는 한 번만 적용한다 (재전달은 200 이고 무시).

orgs.plan 을 바꾸는 유일한 자리다: subscription.active·updated 의 status active/trialing/past_due 는 pro, 그 밖(canceled·unpaid…)은 free. 서버에 토큰이 없으면 501. 클라이언트 라이브러리는 부르지 않는다.

operationId polarHook

Request body: application/json · object

StatusDescriptionResponse body
200받았다 (applied 가 참이면 요금제를 바꿨다)
400
403서명이 맞지 않는다
501결제가 꺼져 있다

GET /v1/orgs/{orgSlug}/billing

요금제(plan)와, 프로면 그 상태(status: active · past_due · canceled)와 현재 기간의 끝(periodEnd)을 준다. enabled 가 거짓이면 이 배치에 결제가 설정되지 않은 것이다 — 화면은 문의 주소만 둔다. sandbox 가 참이면 Polar 의 테스트 환경이라 실제 청구가 없다.

limits 는 두 요금제의 한도 표다 (cp/internal/plan). 화면에 숫자를 두지 않는 이유는 OrgMembership.projectLimit 과 같다. viewer 이상.

operationId getBilling

StatusDescriptionResponse body
200결제 상태BillingStatus
403
404

POST /v1/orgs/{orgSlug}/billing/checkout

Polar 체크아웃 세션 하나를 만들고 그 url 을 준다. 대시보드는 그 URL 을 자기 페이지 위의 iframe 으로 띄운다 (@polar-sh/checkout; 세션의 embed_originreturnTo 의 origin). 결제가 끝나도 그것이 요금제를 바꾸지는 않는다: 요금제는 웹훅(/v1/hooks/polar)이 바꾼다. 화면은 성공 사건 뒤 상태를 다시 읽는다.

returnTo 는 서버의 RUNLOT_PUBLIC_URL 아래여야 한다 (아니면 400). 이미 프로면 409 already_pro — 포털을 열어야 한다. admin.

operationId createBillingCheckout

Request body: application/json · object

StatusDescriptionResponse body
200체크아웃 세션object
400
403
404
409already_proError
501billing_off — 결제가 설정되지 않았다
502billing_unavailable — Polar 가 응답하지 않는다

POST /v1/orgs/{orgSlug}/billing/portal

Polar 고객 포털의 일회용 url 을 준다. 결제 수단 변경·영수증·해지는 전부 거기서 한다 — 우리 화면에 그 폼을 두지 않는다 (카드 번호가 우리 서버를 지나지 않는 것이 MoR 의 값이다). 한 번도 결제한 적 없는 org 는 404. admin.

operationId createBillingPortal

Request body: application/json · object

StatusDescriptionResponse body
200포털 세션object
400
403
404
501billing_off
502billing_unavailable

POST /v1/orgs/{orgSlug}/billing/session

@polar-sh/checkout 의 결제 수단 임베드가 요구하는 고객 세션 토큰. 1 시간, 그 고객 하나. 화면이 열릴 때마다 새로 받는다. 결제 이력 없는 org 는 404. admin.

operationId createBillingSession

StatusDescriptionResponse body
200고객 세션object
403
404
501billing_off
502billing_unavailable

POST /v1/orgs/{orgSlug}/billing/cancel

cancel: true 면 현재 기간이 끝나는 날 프로가 끝난다 (그날까지는 프로) — Polar 의 cancel_at_period_end. false 면 예약을 되돌린다. 즉시 회수는 없다: 낸 기간은 다 쓴다. 응답으로 우리 행의 status 를 바로 맞추고, 웹훅도 곧 같은 결론으로 온다. 프로가 아니면 409 not_pro. admin.

operationId cancelBilling

Request body: application/json · object

StatusDescriptionResponse body
200The updated statusobject
403
404
409not_proError
501billing_off
502billing_unavailable

On this page