변경 및 조회
구독 엔드포인트는 두 그룹으로 나뉩니다.
직접 조회 및 변경. 이 호출은 Checkout Session을 사용하지 않습니다. 구독과 주문 내역, 인보이스 링크, 진행 중인 요금제 변경을 표시하거나, 판매자 측에서 구독 또는 대기 중인 요금제 변경을 취소할 때 사용합니다. 직접 취소는 즉시 적용됩니다.
- 구독 목록 조회, 구독 조회 — 구독을 표시합니다.
- 구독의 주문 목록 조회, 인보이스 링크 — 주문 내역과 인보이스를 표시합니다.
- 요금제 변경 목록 조회 — 진행 중인 요금제 변경을 표시합니다.
- 구독 취소, 요금제 변경 취소 — 판매자 측에서 구독 또는 대기 중인 변경을 취소합니다.
고객 확인이 필요한 요청. 이 호출은 Checkout Session을 반환합니다. 고객을 해당 url로 이동시키세요. 고객이 확인하기 전까지 구독은 바뀌지 않습니다. 고객이 취소를 요청한 경우, 요금제 변경에 고객 승인이 필요한 경우, 새 결제 수단을 받아야 하는 경우처럼 고객의 조작이나 동의가 필요할 때 사용합니다.
- 고객 취소 요청 — 고객의 요청에 따라 취소합니다.
- 요금제 변경 요청 — 고객이 새 요금제를 승인합니다.
- 결제 수단 변경 요청 — 고객이 새 카드를 등록합니다.
금액 형식: 금액 값(amount 필드 등)은 각 통화의 최소 단위로 표시합니다. 지원 통화를 참고하세요.
결과는 API 키의 판매자와 테스트 모드에 해당하는 데이터로 한정됩니다.
구독 목록 조회
GET /v2/subscription은 인증된 판매자의 구독을 ID 내림차순(최신순)으로 반환합니다.
reference와 customerId는 완전 일치 조건이며 AND로 결합됩니다. limit은 1~100이며 기본값은 20입니다. 첫 페이지는 cursor를 생략하고, 다음 페이지는 pagination.nextCursor 값을 그대로 cursor로 전달하세요.
curl --request GET \
--url 'https://api.tokenz.one/v2/subscription?customerId=customer_123&limit=20' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
응답
{
"data": [
{
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active",
"test": true,
"reference": "Pro Plan (Monthly)",
"customerId": "customer_123",
"items": [
{
"id": "item_1p4LS47fB1i_t",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"interval": { "unit": "MONTH", "count": 1 },
"provideAccess": true,
"currentBillingPeriodEnd": "2026-08-01T00:00:00Z",
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-01T00:00:00Z"
}
],
"pagination": {
"nextCursor": "subscription_1p4LC47fB2a_t"
}
}
마지막 페이지에는 pagination.nextCursor가 없습니다.
구독 조회
GET /v2/subscription/{id}는 구독 하나를 반환합니다. ID가 존재하지 않거나, 다른 판매자의 구독이거나, API 키의 테스트 모드와 일치하지 않으면 404로 실패합니다.
curl --request GET \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
응답
{
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active",
"test": true,
"reference": "Pro Plan (Monthly)",
"customerId": "customer_123",
"items": [
{
"id": "item_1p4LS47fB1i_t",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"interval": { "unit": "MONTH", "count": 1 },
"provideAccess": true,
"currentBillingPeriodEnd": "2026-08-01T00:00:00Z",
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-01T00:00:00Z"
}
구독 취소
POST /v2/subscription/{id}/cancel은 구독을 즉시 취소합니다. 요청 본문은 없습니다. 취소하려면 구독이 trialing, active, unpaid 중 하나여야 합니다. 이미 canceled인 구독은 변경되지 않으며, 그 밖의 상태에서는 코드 subscription.status-invalid와 함께 422가 반환됩니다.
취소하면 canceledAt이 설정되고 이후 갱신 주문 생성이 중단되며 subscription.canceled가 전송됩니다. 취소는 되돌릴 수 없습니다. 이용 권한과 진행 중인 주문의 처리는 수명 주기 및 청구를 참고하세요.
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/cancel \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
응답
{
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "canceled",
"test": true,
"items": [
{
"id": "item_1p4LS47fB1i_t",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"interval": { "unit": "MONTH", "count": 1 },
"provideAccess": true,
"provideAccessUntil": "2026-08-01T00:00:00Z",
"canceledAt": "2026-07-15T12:00:00Z",
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
고객 취소 요청
POST /v2/subscription/{id}/request/cancel은 구독을 직접 취소하지 않습니다. 고객이 취소를 확인할 Checkout Session을 생성합니다. 반환된 url로 고객을 이동시키세요. 고객이 확인하면 subscription.canceled 웹훅 전송을 포함해 직접 취소와 같은 방식으로 구독이 취소됩니다.
필수 본문 필드:
successUrl: 고객이 확인을 마친 후 이동하는 URL입니다.pendingUrl: 확인이 아직 대기 중일 때 고객이 이동하는 URL입니다.cancelUrl: 고객이 흐름을 중단했을 때 이동하는 URL입니다.
theme은 선택 사항입니다(LIGHT 또는 DARK).
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/cancel \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel"
}'
응답
201과 함께 Checkout Session을 반환합니다. 고객이 확인하기 전까지 구독은 현재 상태를 유지합니다.
{
"id": "checkoutsession_1p4LC47fB2a_t",
"object": "checkoutsession",
"url": "https://checkout.tokenz.one/1p4LC47fB2a_t",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel",
"test": true,
"subscription": {
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active"
},
"createdAt": "2026-07-15T12:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
결제 수단 변경 요청
POST /v2/subscription/{id}/request/payment-method-change는 고객이 새 카드를 등록할 Checkout Session을 생성합니다. 고객을 url로 이동시키세요. 새 카드에 대한 동의는 해당 호스팅 페이지에서 받습니다. 결제 수단 및 동의를 참고하세요.
본문은 고객 취소 요청과 같은 세 가지 리디렉션 URL(successUrl, pendingUrl, cancelUrl)과 선택 사항인 theme입니다.
구독이 unpaid이면 미납 주문의 결제를 위한 Checkout Session이 반환됩니다. 이 주문을 결제하면 결제 수단이 교체되고 구독이 다시 활성화됩니다. 결제에 성공하면 Tokenz가 subscription.activated 웹훅을 전송합니다.
active 또는 trialing 구독이면 결제 수단 업데이트용 Checkout Session이 반환됩니다. 업데이트에 성공하면 Tokenz가 subscription.payment_method_updated 웹훅을 전송합니다.
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/payment-method-change \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel"
}'
응답
{
"id": "checkoutsession_1p4LP47fB3b_t",
"object": "checkoutsession",
"url": "https://checkout.tokenz.one/1p4LP47fB3b_t",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel",
"test": true,
"subscription": {
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active"
},
"createdAt": "2026-07-15T12:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
요금제 변경 요청
POST /v2/subscription/{id}/request/plan-change는 새 아이템과 청구 주기를 승인하도록 고객에게 요청합니다. 고객이 반환된 Checkout Session에서 승인하기 전까지 변경은 적용되지 않습니다.
구독은 active 또는 trialing 상태여야 하며, 그 밖의 상태에서는 코드 subscription.status-invalid와 함께 422가 반환됩니다. 본문에는 itemDetails, replacementMode, successUrl, pendingUrl, cancelUrl이 포함되어야 합니다. itemDetails는 구독의 현재 아이템을 대체합니다. quantity가 1인 할인되지 않은 아이템을 정확히 하나만 지정하세요. 아이템의 통화는 구독의 통화와 같아야 하며, 다르면 코드 currency.inconsistent와 함께 400 오류가 반환됩니다. interval은 새 청구 주기를 지정합니다: { "unit": "WEEK" | "MONTH" | "YEAR", "count": <integer ≥ 1> }. successUrl은 즉시 변경이 적용된 후에, pendingUrl은 예약 변경이 승인된 후에 사용됩니다.
replacementMode:
IMMEDIATE_PRORATION: 기간제 구독(예: 프리미엄 요금제)에서 고객이 주문을 승인하는 즉시 변경을 적용합니다. 구독이 active이면 현재 청구 기간의 남은 금액을 일할 계산하여 고객에게 크레딧으로 적용하고, 청구 기준일을 승인 일자로 설정합니다. 구독이 trialing이면 추가 크레딧 없이 체험이 즉시 종료되고 새 요금제로 구독이 시작됩니다. 계산된 크레딧이 새 아이템 가격보다 크면 코드subscription.plan-replacement-invalid와 함께422오류가 반환됩니다. 아이템형 구독(예: 매월 재화 구매)에는 이 모드를 사용하지 마세요. 아이템형 구독에 업그레이드 옵션이 필요하면 Tokenz에 문의하세요.DEFERRED: 현재 청구 기간이 끝난 후 변경을 적용합니다. 승인 시subscription.plan_change_scheduled가 전송되며, 요금제는 다음 청구 기간의 주문이 결제될 때 실제로 바뀝니다.
요금제가 적용되면(즉시 또는 다음 기간에) Tokenz가 subscription.plan_changed 웹훅을 전송합니다.
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/plan-change \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"itemDetails": [{
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"],
"taxCategory": "SAAS"
}
}],
"interval": { "unit": "YEAR", "count": 1 },
"replacementMode": "DEFERRED",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel"
}'
같은 요금제를 고객이 승인하는 즉시 적용하려면 "replacementMode": "IMMEDIATE_PRORATION"을 사용하세요. 이 모드는 아이템형 구독이 아닌 기간제 구독에 사용합니다.
응답
201과 함께 Checkout Session과 대기 중인 변경을 반환합니다.
{
"id": "checkoutsession_1p4LR47fB4c_t",
"object": "checkoutsession",
"url": "https://checkout.tokenz.one/1p4LR47fB4c_t",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel",
"test": true,
"subscriptionChange": {
"id": "subscriptionchange_1p4LC9aB2cD_t",
"object": "subscriptionchange",
"status": "pending",
"replacementMode": "DEFERRED",
"interval": { "unit": "YEAR", "count": 1 },
"items": [
{
"id": "item_1p4LS47fB1j_t",
"detail": {
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
]
},
"createdAt": "2026-07-15T12:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
고객을 url로 이동시키세요. 나중에 변경을 조회하거나 취소하려면 subscriptionChange.id를 저장하세요.
요금제 변경 목록 조회
GET /v2/subscription/{id}/plan-change는 구독의 진행 중인 변경, 즉 pending 또는 approved 상태인 변경을 반환합니다. canceled와 applied 상태의 변경은 포함되지 않습니다.
변경은 pending(고객 승인 대기), approved(승인됨, 예약 변경이면 아직 적용 전), applied, canceled 상태를 거칩니다.
curl --request GET \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
응답
{
"data": [
{
"id": "subscriptionchange_1p4LC9aB2cD_t",
"object": "subscriptionchange",
"status": "approved",
"replacementMode": "DEFERRED",
"interval": { "unit": "YEAR", "count": 1 },
"items": [
{
"id": "item_1p4LS47fB1j_t",
"detail": {
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
]
}
]
}
요금제 변경 취소
POST /v2/subscription/{id}/plan-change/{changeId}/cancel은 적용 전인 pending 또는 approved 변경을 취소합니다. 요청 본문은 없습니다. applied, expired, canceled 상태의 변경을 취소하면 subscription.change-status-invalid와 함께 422가 반환됩니다. 예약 변경은 상태가 아직 approved이더라도 다음 청구 기간의 주문이 생성되면 취소할 수 없으며, 이때 취소를 시도하면 subscription.change-status-invalid와 함께 422가 반환됩니다.
이미 승인된 예약 변경을 취소하면 subscription.plan_change_canceled가 전송됩니다.
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change/subscriptionchange_1p4LC9aB2cD_t/cancel \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
응답
{
"id": "subscriptionchange_1p4LC9aB2cD_t",
"object": "subscriptionchange",
"status": "canceled",
"replacementMode": "DEFERRED",
"interval": { "unit": "YEAR", "count": 1 },
"items": [
{
"id": "item_1p4LS47fB1j_t",
"detail": {
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
]
}
구독의 주문 목록 조회
Order 서비스의 GET /v2/order는 구독 하나에 대해 생성된 주문 목록을 반환합니다. subscriptionId는 필수입니다. limit(1~100, 기본값 20)과 cursor는 구독 목록 조회와 같은 방식으로 페이지를 나눕니다. pagination.nextCursor 값을 그대로 cursor로 전달하세요. 주문은 ID 내림차순(최신순)으로 반환되며, API 키의 테스트 모드와 일치하는 주문만 포함됩니다.
각 주문에는 subscriptionId가 포함됩니다. 아이템에는 해당 주문이 청구한 기간을 나타내는 billedPeriodStart(포함)와 billedPeriodEnd(미포함)가 있을 수 있습니다.
curl --request GET \
--url 'https://api.tokenz.one/v2/order?subscriptionId=subscription_1p4LS47fB1h_t&limit=20' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
응답
{
"data": [
{
"id": "order_1D5xA9BnKfv_t",
"object": "order",
"status": "succeeded",
"test": true,
"subscriptionId": "subscription_1p4LS47fB1h_t",
"amount": { "amount": 1000, "currency": "USD" },
"items": [
{
"id": "item_1p4LO47fB1k_t",
"billedPeriodStart": "2026-07-01T00:00:00Z",
"billedPeriodEnd": "2026-08-01T00:00:00Z",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-01T00:00:05Z"
}
],
"pagination": {
"nextCursor": "order_1p4LC47fB2a_t"
}
}
인보이스 링크
GET /v2/order/{id}/invoice는 구독 갱신 주문을 포함한 주문의 구매자용 호스팅 인보이스 링크를 반환합니다. displayUrl은 호스팅 인보이스 페이지입니다. downloadUrl은 PDF이며 PDF가 생성된 후에만 포함됩니다. Tokenz가 생성한 서명이 담긴 프래그먼트까지 포함한 전체 URL로 고객을 이동시키세요.
curl --request GET \
--url https://api.tokenz.one/v2/order/order_1D5xA9BnKfv_t/invoice \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
응답
{
"displayUrl": "https://invoice.tokenz.one/i/1D5xA9BnKfv_t#generated-invoice-signature",
"downloadUrl": "https://invoice.tokenz.one/i/1D5xA9BnKfv_t/download#generated-invoice-signature"
}
PDF가 생성되기 전에는 응답에 displayUrl만 포함됩니다.
웹훅
이 엔드포인트를 폴링하지 말고 웹훅으로 자체 기록을 동기화하세요. 이 페이지의 작업과 관련된 이벤트는 다음과 같습니다.
subscription.canceled— 직접 취소 또는 고객이 확인한 취소가 완료되었습니다.subscription.payment_method_updated— 고객이 새 카드를 확인했습니다.subscription.plan_change_scheduled— 고객이 예약 요금제 변경을 승인했습니다.subscription.plan_change_canceled— 예약된 요금제 변경이 적용 전에 취소되었습니다.subscription.plan_changed— 즉시 또는 예약 요금제 변경이 적용되었습니다. 페이로드의items와interval이 새 요금제입니다.
페이로드 구조는 웹훅을 참고하세요.