---
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. The reserved keys `custom_cta` (a checkout call-to-action button label — one of the product custom CTA values, e.g. `subscribe`, `get_offer`) and `custom_cta_url` (a URL the button links to; web or `tel:`) override the product's call to action for this plan and are validated on save.
  - `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', nullable — 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` AccountSummary, required
    - `id` string, required — Account ID, prefixed `biz_`.
    - `title` string, required — Account display name.
  - `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.
  - `effective_payment_method_configuration` CheckoutSessionPaymentMethodConfiguration, required
    - `disabled` string[], required
    - `enabled` string[], required
    - `include_platform_defaults` boolean, required — Whether Whop's default set is the starting point. When `false`, only `enabled` is offered.
  - `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. The reserved keys `custom_cta` and `custom_cta_url`, when set, override the product's checkout call to action for this plan.
  - `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
- `409` — Conflict

---

[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/revisions/6a23760847c8/schema)
