Skip to main content
POST
/
plans
JavaScript
import Whop from '@whop/sdk';

const client = new Whop({
  apiKey: process.env['WHOP_API_KEY'], // This is the default and can be omitted
});

const plan = await client.plans.create({
  company_id: 'biz_xxxxxxxxxxxxxx',
  product_id: 'prod_xxxxxxxxxxxxx',
});

console.log(plan.id);
{
  "id": "plan_xxxxxxxxxxxxx",
  "created_at": "2023-12-01T05:00:00.401Z",
  "updated_at": "2023-12-01T05:00:00.401Z",
  "visibility": "visible",
  "plan_type": "renewal",
  "release_method": "buy_now",
  "currency": "usd",
  "company": {
    "id": "biz_xxxxxxxxxxxxxx",
    "title": "Pickaxe"
  },
  "product": {
    "id": "prod_xxxxxxxxxxxxx",
    "title": "Pickaxe Analytics"
  },
  "invoice": {
    "id": "inv_xxxxxxxxxxxxxx"
  },
  "billing_period": 42,
  "title": "Pro Monthly",
  "description": "Monthly access to all premium analytics dashboards and data exports.",
  "purchase_url": "https://whop.com/pickaxe-analytics/checkout/plan_abc123",
  "expiration_days": 42,
  "initial_price": 6.9,
  "renewal_price": 6.9,
  "trial_period_days": 42,
  "member_count": 42,
  "internal_notes": "Black Friday 2024 promo plan - expires Dec 1",
  "stock": 42,
  "unlimited_stock": true,
  "split_pay_required_payments": 42,
  "payment_method_configuration": {
    "enabled": [
      "acss_debit"
    ],
    "disabled": [
      "acss_debit"
    ],
    "include_platform_defaults": true
  },
  "tax_type": "inclusive",
  "collect_tax": true,
  "custom_fields": [
    {
      "id": "field_xxxxxxxxxxxx",
      "field_type": "<string>",
      "name": "<string>",
      "order": 42,
      "placeholder": "<string>",
      "required": true
    }
  ]
}

Authorizations

Authorization
string
header
required

A company API key, company scoped JWT, app API key, or user OAuth token. You must prepend your key/token with the word 'Bearer', which will look like Bearer ***************************

Body

application/json

Parameters for CreatePlan

company_id
string
required

The unique identifier of the company to create this plan for.

Example:

"biz_xxxxxxxxxxxxxx"

product_id
string
required

The unique identifier of the product to attach this plan to.

Example:

"prod_xxxxxxxxxxxxx"

billing_period
integer | null

The number of days between recurring charges. For example, 30 for monthly or 365 for yearly.

Example:

42

currency
enum<string> | null

The three-letter ISO currency code for the plan's pricing. Defaults to USD.

Available options:
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
custom_fields
object[] | null

An array of custom field definitions to collect from customers at checkout.

description
string | null

A text description of the plan displayed to customers on the product page.

expiration_days
integer | null

The number of days until the membership expires and access is revoked. Used for expiration-based plans.

Example:

42

image
FileInputWithId · object

An image displayed on the product page to represent this plan.

initial_price
number | null

The amount charged on the first purchase. For one-time plans, this is the full price. For recurring plans, this is an additional charge on top of the renewal price. Provided in the plan's currency (e.g., 10.43 for $10.43).

Example:

6.9

internal_notes
string | null

Private notes visible only to the business owner. Not shown to customers.

legacy_payment_method_controls
boolean | null

Whether this plan uses legacy payment method controls.

override_tax_type
enum<string> | null

Override the default tax classification for this specific plan.

Available options:
inclusive,
exclusive,
unspecified
payment_method_configuration
object

Explicit payment method configuration for the plan. When not provided, the company's defaults apply.

plan_type
enum<string> | null

The billing type of the plan, such as one_time or recurring.

Available options:
renewal,
one_time
release_method
enum<string> | null

The method used to sell this plan (e.g., buy_now, waitlist, application).

Available options:
buy_now,
waitlist
renewal_price
number | null

The amount charged each billing period for recurring plans. Provided in the plan's currency (e.g., 10.43 for $10.43).

Example:

6.9

split_pay_required_payments
integer | null

The number of installment payments required before the subscription pauses.

Example:

42

stock
integer | null

The maximum number of units available for purchase. Ignored when unlimited_stock is true.

Example:

42

title
string | null

The display name of the plan shown to customers on the product page.

trial_period_days
integer | null

The number of free trial days before the first charge on a recurring plan.

Example:

42

unlimited_stock
boolean | null

Whether the plan has unlimited stock. When true, the stock field is ignored. Defaults to true.

visibility
enum<string> | null

Whether the plan is visible to customers or hidden from public view.

Available options:
visible,
hidden,
archived,
quick_link

Response

A successful response

A plan defines pricing and billing terms for a checkout. Plans can optionally belong to a product, where they represent different pricing options such as one-time payments, recurring subscriptions, or free trials.

id
string
required

The unique identifier for the plan.

Example:

"plan_xxxxxxxxxxxxx"

created_at
string<date-time>
required

The datetime the plan was created.

Example:

"2023-12-01T05:00:00.401Z"

updated_at
string<date-time>
required

The datetime the plan was last updated.

Example:

"2023-12-01T05:00:00.401Z"

visibility
enum<string>
required

Controls whether the plan is visible to customers. When set to 'hidden', the plan is only accessible via direct link.

Available options:
visible,
hidden,
archived,
quick_link
plan_type
enum<string>
required

The billing model for this plan: 'renewal' for recurring subscriptions or 'one_time' for single payments.

Available options:
renewal,
one_time
release_method
enum<string>
required

The method used to sell this plan: 'buy_now' for immediate purchase or 'waitlist' for waitlist-based access.

Available options:
buy_now,
waitlist
currency
enum<string>
required

The currency used for all prices on this plan (e.g., 'usd', 'eur'). All monetary amounts on the plan are denominated in this currency.

Available options:
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
company
object
required

The company that sells this plan. Null for standalone invoice plans not linked to a company.

product
object
required

The product that this plan belongs to. Null for standalone one-off purchases not linked to a product.

invoice
object
required

The invoice this plan was generated for. Null if the plan was not created for a specific invoice.

billing_period
integer | null
required

The number of days between each recurring charge. Null for one-time plans. For example, 30 for monthly or 365 for annual billing.

Example:

42

title
string | null
required

The display name of the plan shown to customers on the product page and at checkout. Maximum 30 characters. Null if no title has been set.

Example:

"Pro Monthly"

description
string | null
required

A text description of the plan visible to customers. Maximum 500 characters. Null if no description is set.

Example:

"Monthly access to all premium analytics dashboards and data exports."

purchase_url
string
required

The full URL where customers can purchase this plan directly, bypassing the product page.

Example:

"https://whop.com/pickaxe-analytics/checkout/plan_abc123"

expiration_days
integer | null
required

The number of days until the membership expires (for expiration-based plans). For example, 365 for a one-year access pass.

Example:

42

initial_price
number
required

The initial purchase price in the plan's base_currency (e.g., 49.99 for $49.99). For one-time plans, this is the full price. For renewal plans, this is charged on top of the first renewal_price.

Example:

6.9

renewal_price
number
required

The recurring price charged every billing_period in the plan's base_currency (e.g., 9.99 for $9.99/period). Zero for one-time plans.

Example:

6.9

trial_period_days
integer | null
required

The number of free trial days before the first charge on a renewal plan. Null if no trial is configured or the current user has already used a trial for this plan.

Example:

42

member_count
integer | null
required

The number of users who currently hold an active membership through this plan. Only visible to authorized team members.

Example:

42

internal_notes
string | null
required

Private notes visible only to the company owner and team members. Not shown to customers. Null if no notes have been added.

Example:

"Black Friday 2024 promo plan - expires Dec 1"

stock
integer | null
required

The number of units available for purchase. Only visible to authorized team members. Null if the requester lacks permission.

Example:

42

unlimited_stock
boolean
required

When true, the plan has unlimited stock (stock field is ignored). When false, purchases are limited by the stock field.

split_pay_required_payments
integer | null
required

The total number of installment payments required before the subscription pauses. Null if split pay is not configured. Must be greater than 1.

Example:

42

payment_method_configuration
object
required

The explicit payment method configuration specifying which payment methods are enabled or disabled for this plan. Null if the plan uses default settings.

tax_type
enum<string>
required

How tax is handled for this plan: 'inclusive' (tax included in price), 'exclusive' (tax added at checkout), or 'unspecified' (tax not configured).

Available options:
inclusive,
exclusive,
unspecified
collect_tax
boolean
required

Whether tax is collected on purchases of this plan, based on the company's tax configuration.

custom_fields
object[]
required

Custom input fields displayed on the checkout form that collect additional information from the buyer.