---
title: "Update Variant"
method: PATCH
path: "/variants/{id}"
tags: ["Variants"]
---

# Update Variant

`PATCH /variants/{id}`

Update a variant's pricing, billing interval, visibility, stock, and other settings.

## Request body

- object
  - `adaptive_pricing_enabled` boolean, nullable — Whether this variant accepts local currency payments via adaptive pricing.
  - `attributes` object, nullable — Attribute values that make this variant one variant of its product, as a map of attribute name to value, e.g. `{"size": "Large", "color": "Blue"}`. Names are normalized to snake_case identifiers (`Ring Size` becomes `ring_size`) and come back in alphabetical order. Every variant on a product must carry the same attribute names and a distinct set of values. Send `null` to make the variant an ordinary pricing option again.
  - `billing_period` integer, nullable — Recurring billing interval in days, such as 30 for monthly or 365 for annual.
  - `cancel_discount_intervals` integer, nullable — How many renewals the retention discount applies to. Required when `offer_cancel_discount` is true.
  - `cancel_discount_percentage` integer, nullable — Percentage taken off each discounted renewal. Required when `offer_cancel_discount` is true.
  - `checkout_styling` object, nullable — Checkout styling overrides for this variant.
  - `currency` string — The three-letter ISO currency code for the variant'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 variant 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 variant.
    - `direct_upload_id` string
    - `id` string
  - `initial_price` number, nullable — Initial amount charged in the variant's currency, e.g. 10.43 for $10.43. A paid fiat variant charges at least 1.00 in its currency; use 0 for free.
  - `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 variant. 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 variant and are validated on save.
  - `offer_cancel_discount` boolean, nullable — Whether to offer a retention discount when a customer attempts to cancel.
  - `override_tax_type` string — Override the default tax classification for this specific variant.
  - `payment_method_configuration` object, nullable — Explicit payment method configuration for the variant. When not provided, the account's defaults apply. Send at least one of `enabled` or `disabled`; an omitted one is empty.
    - `disabled` PaymentMethodTypes[] — Payment method types explicitly disabled for this variant — the `type` values from the payment method types catalogue. Types Whop no longer offers, and the read-only `unknown` placeholder, are dropped.
    - `enabled` PaymentMethodTypes[] — Payment method types explicitly enabled for this variant — the `type` values from the payment method types catalogue. Types Whop no longer offers, and the read-only `unknown` placeholder, are dropped.
    - `include_platform_defaults` boolean
  - `release_method` string — Sales method for this variant.
  - `renewal_price` number, nullable — The amount charged each billing period for recurring variants, in the variant's currency. A paid fiat variant charges at least 1.00 in its currency.
  - `sku` string, nullable — Stock keeping unit for this variant. Maximum 100 characters. Free text, not enforced unique.
  - `stock` integer, nullable — The maximum number of units available for purchase. Ignored when unlimited_stock is true.
  - `strike_through_initial_price` number, nullable — A comparison price displayed with a strikethrough for the initial price.
  - `strike_through_renewal_price` number, nullable — A comparison price displayed with a strikethrough for the renewal price.
  - `three_ds_level` 'mandate_challenge' | 'mandate_if_required' | 'frictionless_if_required' | 'null', nullable — 3D Secure behavior for supported on-session card payments. `mandate_challenge` requires a 3DS challenge before payment processing; `mandate_if_required` mandates a challenge only when the payment processor requires it; `frictionless_if_required` uses the regular frictionless 3DS flow. Payments of $1,000 or more use `mandate_if_required` unless `mandate_challenge` is selected. Risk and authentication recovery requirements can override the preference. Send `null` to inherit the account default.
  - `title` string, nullable — The display name of the variant shown to customers on the product page. Maximum 30 characters.
  - `trial_period_days` integer, nullable — Free trial duration before the first recurring charge.
  - `unlimited_stock` boolean, nullable — Whether the variant has unlimited stock. When true, the stock field is ignored.
  - `visibility` string — Whether the variant is visible to customers or hidden from public view.

## Response `200`

variant updated

- Variant
  - `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 variant. Raw setting — does not check processor compatibility or feature flags.
  - `attributes` object, nullable, required — Attribute values that distinguish this variant within its product, as a map of attribute name to value, e.g. `{"color": "Blue", "size": "Large"}`. Names are snake_case identifiers and come back in alphabetical order. Every attributed variant on a product carries the same attribute names and a distinct set of values; the product lists the full option set as `variant_attributes`. `null` when the variant has no attributes.
  - `billing_period` number, nullable, required — Number of days between recurring charges, such as 30 for monthly or 365 for annual. `null` for one-time variants.
  - `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 — Variant-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 variant, based on the account's tax configuration.
  - `created_at` string, required — When the variant was created, as an ISO 8601 timestamp.
  - `currency` string, required — Three-letter ISO currency code for this variant'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 variant can be deleted (it has no memberships or waitlist entries). `null` unless the actor has the `plan:basic:read` scope on the variant's account.
  - `description` string, nullable, required — Customer-visible variant 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 variants, such as 365 for a one-year pass. `null` for variants without an expiration.
  - `formatted_price` string, required — Human-readable price for display (currency + interval), e.g. "$10 / month".
  - `id` string, required — Variant 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 variant currency.
  - `initial_price_due` Money, required
    - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
    - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
    - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
    - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
  - `internal_notes` string, nullable, required — Private notes not shown to customers. `null` unless the actor has the `plan:basic:read` scope on the variant's account.
  - `invoice` object, nullable, required — Invoice this variant was generated for; `null` unless created for an invoice.
  - `member_count` number, nullable, required — Active memberships through this variant. `null` unless the actor has the `plan:basic:read` scope on the variant's account.
  - `metadata` object, nullable, required — Custom key-value pairs stored on the variant. 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 variant.
  - `offer_cancel_discount` boolean, nullable, required — Whether a cancellation discount is offered. `null` unless the actor has the `plan:basic:read` scope on the variant's account.
  - `payment_method_configuration` object, nullable, required — Payment method configuration (`enabled`, `disabled`, `include_platform_defaults`); `null` when variant uses default settings.
  - `plan_type` 'renewal' | 'one_time', required — Billing model for this variant.
  - `product` object, nullable, required — Product this variant belongs to; `null` for standalone variants.
  - `purchase_url` string, required — URL where customers can purchase this variant directly.
  - `release_method` 'buy_now' | 'waitlist', required — Sales method for this variant.
  - `renewal_price` number, required — Recurring price charged every billing period.
  - `sku` string, nullable, required — Stock keeping unit, free text set by the seller (e.g. `TSHIRT-LARGE-BLUE`). Not enforced unique. `null` when unset.
  - `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 variant's account.
  - `strike_through_initial_price` number, nullable, required — Original initial price shown with a strikethrough, in the variant's currency. `null` when no strikethrough is set.
  - `strike_through_renewal_price` number, nullable, required — Original renewal price shown with a strikethrough, in the variant's currency. `null` when no strikethrough is set.
  - `tax_type` 'inclusive' | 'exclusive' | 'unspecified', required — How tax is handled for this variant, including whether tax is included in the price, added at checkout, or not configured.
  - `three_ds_level` 'mandate_challenge' | 'mandate_if_required' | 'frictionless_if_required' | 'null', nullable, required — 3D Secure behavior for supported on-session card payments. `mandate_challenge` requires a 3DS challenge before payment processing; `mandate_if_required` mandates a challenge only when the payment processor requires it; `frictionless_if_required` uses the regular frictionless 3DS flow. Payments of $1,000 or more use `mandate_if_required` unless `mandate_challenge` is selected. Risk and authentication recovery requirements can override the preference. `null` inherits the account default.
  - `title` string, nullable, required — Variant display name shown to customers. Maximum 30 characters. A variant created without one defaults to its attribute values joined with ` / `. `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 variant.
  - `unlimited_stock` boolean, required — Whether the variant has unlimited stock. When `true`, the `stock` field is ignored; waitlist variants always report `true`.
  - `updated_at` string, required — When the variant was last updated, as an ISO 8601 timestamp.
  - `visibility` 'visible' | 'hidden' | 'archived' | 'quick_link', required — Controls where this variant can be seen. When `hidden`, the variant is reachable only by its direct link.

## Other responses

- `401` — Unauthorized

## Changes

> 77 revisions in range; 1 not diffed.

- **2026-09-28** `06291fc035ed` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/whop/apis/whop-api/changes/variants/:id/patch.md)

---

[API](https://skmtc.dev/whop/apis/whop-api.md) · [All operations](https://skmtc.dev/whop/apis/whop-api/llms.txt) · [OpenAPI document](https://skmtc.dev/whop/apis/whop-api/revisions/30c41d3dae3c?raw)
