---
title: "Create Plan"
method: POST
path: "/plans"
tags: ["Plans"]
---

# Create Plan

`POST /plans`

Create a new pricing plan for a product. The plan defines the billing interval, price, and availability for customers.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `account_id` string — The unique identifier of the account to create this plan for. Defaults to the caller's account.
  - `adaptive_pricing_enabled` boolean, nullable — Whether this plan accepts local currency payments via adaptive pricing.
  - `billing_period` integer, nullable — Recurring billing interval in days, such as 30 for monthly or 365 for annual.
  - `checkout_styling` object, nullable — Checkout styling overrides for this plan.
  - `currency` string — The three-letter ISO currency code for the plan's pricing. Defaults to USD.
  - `custom_fields` object[], nullable — An array of custom field definitions to collect from customers at checkout. Omitting this field clears existing custom fields.
    - `field_type` 'text' — The type of the custom field.
    - `id` string — The ID of the custom field (if being updated).
    - `name` string — The name of the custom field.
    - `order` integer — The order of the field.
    - `placeholder` string, nullable — An example response displayed in the input field.
    - `required` boolean — Whether or not the field is required.
  - `description` string, nullable — A text description of the plan displayed to customers on the product page.
  - `expiration_days` integer, nullable — Access duration in days before the membership expires.
  - `image` object, nullable — An image displayed on the product page to represent this plan.
    - `direct_upload_id` string
    - `id` string
  - `initial_price` number, nullable — Initial amount charged in the plan's currency, e.g. 10.43 for $10.43.
  - `internal_notes` string, nullable — Private notes visible only to the account owner. Not shown to customers.
  - `metadata` object, nullable — Custom key-value pairs to store on the plan. Included in webhook payloads for payment and membership events. Max 50 keys, 100 chars per key, 500 chars per string value.
  - `override_tax_type` string — Override the default tax classification for this specific plan.
  - `payment_method_configuration` object, nullable — Explicit payment method configuration for the plan. When not provided, the account's defaults apply.
    - `disabled` string[]
    - `enabled` string[]
    - `include_platform_defaults` boolean
  - `plan_type` string — Plan billing type, such as `one_time` or `renewal`.
  - `product_id` string — The unique identifier of the product to attach this plan to.
  - `release_method` string — Sales method for this plan.
  - `renewal_price` number, nullable — The amount charged each billing period for recurring plans, in the plan's currency.
  - `split_pay_required_payments` integer, nullable — Installment payments required before the subscription pauses.
  - `stock` integer, nullable — The maximum number of units available for purchase. Ignored when unlimited_stock is true.
  - `three_ds_level` 'mandate_challenge' | 'frictionless' — 3D Secure behavior for this plan. Send `null` to inherit the account default.
  - `title` string, nullable — The display name of the plan shown to customers on the product page.
  - `trial_period_days` integer, nullable — Free trial duration before the first recurring charge.
  - `unlimited_stock` boolean, nullable — Whether the plan has unlimited stock. When true, the stock field is ignored.
  - `visibility` string — Whether the plan is visible to customers or hidden from public view.

## Response `200`

plan created

- Plan
  - `account` object, nullable, required — Account that sells this plan; `null` for standalone invoice plans.
  - `adaptive_pricing_enabled` boolean, required — Whether adaptive pricing is enabled for this plan. Raw setting — does not check processor compatibility or feature flags.
  - `billing_period` number, nullable, required — Number of days between recurring charges, such as 30 for monthly or 365 for annual. `null` for one-time plans.
  - `cancel_discount_intervals` number, nullable, required — Billing intervals the cancellation discount applies to (`0` forever, `1` first payment, or a month count). `null` when none is offered or the actor lacks the `plan:basic:read` scope.
  - `cancel_discount_percentage` number, nullable, required — Cancellation discount as a whole-number percentage. `null` when none is offered or the actor lacks the `plan:basic:read` scope.
  - `checkout_styling` object, nullable, required — Plan-level checkout styling (`background_color`, `button_color`, `font_family`, `border_style`); `null` inherits the account default.
  - `collect_tax` boolean, required — Whether tax is collected on purchases of this plan, based on the account's tax configuration.
  - `created_at` string, required — When the plan was created, as an ISO 8601 timestamp.
  - `currency` 'usd' | 'sgd' | 'inr' | 'aud' | 'brl' | 'cad' | 'dkk' | 'eur' | 'nok' | 'gbp' | 'sek' | 'chf' | 'hkd' | 'huf' | 'jpy' | 'mxn' | 'myr' | 'pln' | 'czk' | 'nzd' | 'aed' | 'eth' | 'ape' | 'cop' | 'ron' | 'thb' | 'bgn' | 'idr' | 'dop' | 'php' | 'try' | 'krw' | 'twd' | 'vnd' | 'pkr' | 'clp' | 'uyu' | 'ars' | 'zar' | 'dzd' | 'tnd' | 'mad' | 'kes' | 'kwd' | 'jod' | 'all' | 'xcd' | 'amd' | 'bsd' | 'bhd' | 'bob' | 'bam' | 'khr' | 'crc' | 'xof' | 'egp' | 'etb' | 'gmd' | 'ghs' | 'gtq' | 'gyd' | 'ils' | 'jmd' | 'mop' | 'mga' | 'mur' | 'mdl' | 'mnt' | 'nad' | 'ngn' | 'mkd' | 'omr' | 'pyg' | 'pen' | 'qar' | 'rwf' | 'sar' | 'rsd' | 'lkr' | 'tzs' | 'ttd' | 'uzs' | 'rub' | 'btc' | 'cny' | 'usdt' | 'kzt' | 'awg' | 'whop_usd' | 'xau', required — Three-letter ISO currency code for this plan's prices.
  - `custom_fields` PlanCustomField[], required
    - `field_type` 'text', required — Custom field input type.
    - `id` string, required — Custom field ID, prefixed `field_`.
    - `name` string, required — Field label shown to customer at checkout.
    - `order` number, required — Field position on checkout form.
    - `placeholder` string, nullable, required — Placeholder text shown in the empty field. `null` if none is set.
    - `required` boolean, required — Whether the customer must complete this field to check out.
  - `deletable` boolean, nullable, required — Whether the plan can be deleted (it has no memberships or waitlist entries). `null` unless the actor has the `plan:basic:read` scope on the plan's account.
  - `description` string, nullable, required — Customer-visible plan description. Maximum 1000 characters. `null` if no description is set.
  - `expiration_days` number, nullable, required — Access duration in days for expiration-based plans, such as 365 for a one-year pass. `null` for plans without an expiration.
  - `formatted_price` string, required — Human-readable price for display (currency + interval), e.g. "$10 / month".
  - `id` string, required — Plan ID, prefixed `plan_`.
  - `image` object, nullable, required — Pricing-tier image (`url`, `blurhash`) shown on the product page; `null` when no image is set.
  - `initial_price` number, required — Initial purchase price in plan currency.
  - `internal_notes` string, nullable, required — Private notes not shown to customers. `null` unless the actor has the `plan:basic:read` scope on the plan's account.
  - `invoice` object, nullable, required — Invoice this plan was generated for; `null` unless created for an invoice.
  - `member_count` number, nullable, required — Active memberships through this plan. `null` unless the actor has the `plan:basic:read` scope on the plan's account.
  - `metadata` object, nullable, required — Custom key-value pairs stored on the plan. Included in webhook payloads for payment and membership events. Maximum 50 keys, 100 characters per key, 500 characters per value.
  - `offer_cancel_discount` boolean, nullable, required — Whether a cancellation discount is offered. `null` unless the actor has the `plan:basic:read` scope on the plan's account.
  - `payment_method_configuration` object, nullable, required — Payment method configuration (`enabled`, `disabled`, `include_platform_defaults`); `null` when plan uses default settings.
  - `plan_type` 'renewal' | 'one_time', required — Billing model for this plan.
  - `product` object, nullable, required — Product this plan belongs to; `null` for standalone plans.
  - `purchase_url` string, required — URL where customers can purchase this plan directly.
  - `release_method` 'buy_now' | 'waitlist', required — Sales method for this plan.
  - `renewal_price` number, required — Recurring price charged every billing period.
  - `split_pay_required_payments` number, nullable, required — Installment payments required before the subscription pauses. Must be greater than 1. `null` if split pay is not configured.
  - `stock` number, nullable, required — Units available for purchase. `null` unless the actor has the `plan:basic:read` scope on the plan's account.
  - `strike_through_initial_price` number, nullable, required — Original initial price shown with a strikethrough, in the plan's currency. `null` when no strikethrough is set.
  - `strike_through_renewal_price` number, nullable, required — Original renewal price shown with a strikethrough, in the plan's currency. `null` when no strikethrough is set.
  - `tax_type` 'inclusive' | 'exclusive' | 'unspecified', required — How tax is handled for this plan, including whether tax is included in the price, added at checkout, or not configured.
  - `three_ds_level` 'mandate_challenge' | 'frictionless' | 'null', nullable, required — 3D Secure behavior for this plan; `null` inherits the account default.
  - `title` string, nullable, required — Plan display name shown to customers. Maximum 30 characters. `null` if no title has been set.
  - `trial_period_days` number, nullable, required — Free trial days before the first renewal charge. `null` if no trial is configured or the user has already used a trial for this plan.
  - `unlimited_stock` boolean, required — Whether the plan has unlimited stock. When `true`, the `stock` field is ignored; waitlist plans always report `true`.
  - `updated_at` string, required — When the plan was last updated, as an ISO 8601 timestamp.
  - `visibility` 'visible' | 'hidden' | 'archived' | 'quick_link', required — Controls where this plan can be seen. When `hidden`, the plan is reachable only by its direct link.

## Other responses

- `400` — Invalid Parameters
- `401` — Unauthorized

---

[API](https://skmtc.net/whop/apis/whop-api.md) · [All operations](https://skmtc.net/whop/apis/whop-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/whop/whop-api/versions/db0883548bc5/schema)
