---
title: "Create Subscription"
method: POST
path: "/v1/subscriptions"
tags: ["Billing Subscriptions"]
---

# Create Subscription

`POST /v1/subscriptions`

## Request

- Base URL: `https://api.xdata.kr` (the document declares no server; this is the origin it was published from)
- URL: `https://api.xdata.kr/v1/subscriptions`
- Auth: one of:
  - HTTP basic
  - OAuth 2 (authorization code, authorization URL `https://api.xdata.kr/oauth/authorize`, token URL `https://api.xdata.kr/oauth/token`)

구독 생성 + 첫 결제 PG 제출.

## Query parameters

- `env_scope` 'production' | 'real_test' | 'sandbox', nullable: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.

## Headers

- `Idempotency-Key` string, required
- `Authorization` string, nullable
- `X-Env-Scope` 'production' | 'real_test' | 'sandbox', nullable: 환경을 고릅니다. 값은 production · real_test · sandbox 중 하나입니다. 경로 접두(/v1/sandbox/... · /v1/test/... · /v1/production/...) · X-Env-Scope 헤더 · env_scope 쿼리 가운데 한 통로로 반드시 보내야 합니다. 빼면 자동으로 채우지 않고 거절하며, 두 통로에 서로 다른 값을 담아도 거절합니다. 거절은 HTTP 422 이고 오류 코드는 VALIDATION_ENV_SCOPE_MISMATCH 입니다.

## Request body

- SubscriptionCreateRequest: 구독 생성 요청. 처리 흐름: 1) AuthPolicyService 평가(`request_kind='billing'`, OWNER/ADMIN) 2) plan/payment_method 소유권·상태·env_scope 검증 3) `subscriptions` 행 PENDING 생성 4) `invoices` DRAFT→OPEN 발행 5) 결제 요청 → `payments` INITIATED→PENDING 6) 동기 응답: 202 Accepted + 현재 상태 스냅샷 `organization_id`는 주체(`PrincipalContext.organization_id`)와 일치 강제(라우트 검증). 조직당 활성 구독 1건 룰은 서비스 계층이 SCHEMA `uq_subscriptions_org_active`로 보장. `metadata`는 입력만 허용(응답 미노출). PII/secret/credential 적재 금지. 키 화이트리스트는 후속 ADR(`source`/`utm_*`/`referrer` 등 운영 메타).
  - `organization_id` integer, required: 구독 소유 조직 PK. 주체 조직과 일치 강제.
  - `plan_id` integer, required: plans.id (ACTIVE 상태만 허용).
  - `payment_method_id` integer, required: payment_methods.id (ACTIVE 상태 + 본인 조직 소유만 허용).
  - `metadata` object, nullable: 운영 메타데이터 (예: source, utm_*, referrer). PII/secret 적재 금지. 키 화이트리스트는 별도 결정.
  - `addon_product_ids` integer[], nullable: Optional purchasable add-on api_products.id list. Must match ACTIVE plan_addon_offers for plan_id + env_scope.

## Response `202`

Successful Response

- SubscriptionCreateResponse: 구독 생성 응답 - `202 Accepted` 의 몸통. 조회 응답과 다른 객체: - 본 응답은 **첫 청구/결제 식별자**(`first_invoice_id`/`first_payment_id`)를 포함하여 BFF가 즉시 결제 진행 상태를 폴링/구독할 수 있도록 한다. - 본 응답에는 nested `plan` 객체 없음(생성 시점에 plan 변경 없음 + 응답 크기 최소화). 조회는 `GET /v1/subscriptions/{id}`(`SubscriptionResponse`) 사용.
  - `subscription_id` integer, required: subscriptions.id.
  - `organization_id` integer, required: 소유 조직 PK.
  - `plan_id` integer, required: plans.id.
  - `payment_method_id` integer, nullable: NULL = 결제창 인증 경로.
  - `status` 'PENDING' | 'ACTIVE' | 'PAUSED' | 'CANCELED' | 'EXPIRED' | 'PAYMENT_FAILED', required: 구독 상태. 본 응답은 보통 PENDING(202 Accepted).
  - `env_scope` 'sandbox' | 'real_test' | 'production', required: 환경 스코프.
  - `first_invoice_id` integer, required: 구독 생성과 함께 발행된 첫 인보이스 ID(invoices.id, OPEN 상태).
  - `first_payment_id` integer, required: 구독 생성과 함께 시도된 첫 결제 ID(payments.id, INITIATED/PENDING 상태).
  - `created_at` string, date-time, required: 구독 생성 시각 (aware datetime, naive 입력 시 422).

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/xdata/apis/xboss-api.md) · [All operations](https://skmtc.dev/xdata/apis/xboss-api/llms.txt) · [OpenAPI document](https://skmtc.dev/xdata/apis/xboss-api/revisions/816de78950db?raw)
