Dashboard
APIUpdate Plan API - Modify Subscription Settings | BotSubscription
api.botsubscription.com
GET/v1/endpoint
AuthenticationBearer
Token
Stays in this tab. Required for this endpoint — the value below is what gets sent.
Examples
curl --request GET \
  --url https://api.botsubscription.com/v1/endpoint \
  --header 'Authorization: Bearer sk_live_•••'

Update Project Plan - Modify Subscription Settings via API

Modify an existing subscription plan's settings. Change the name, adjust pricing, update the billing cycle, or toggle payment options. Omitted top-level fields remain unchanged. When supplying plan_data, send both billing flags explicitly as described below.

PATCH/v2/projects/{project_id}/plans/{plan_id}

Authorization

Bearer API KeyRequired

API key access: Unrestricted project API key required. Restricted keys cannot call this endpoint.

Path Parameters

project_idstringrequired

The unique identifier of the project.

plan_idstringrequired

The unique identifier of the plan to update.

Request Body

plan_namestring

Display name (3–50 characters). Supports letters in any language, numbers, spaces, hyphens, underscores, parentheses, square brackets, dot, comma, percent, plus, supported currency symbols and emojis.

plan_pricestring|number

Nonnegative price within the resulting currency's decimal limit. Prefer a decimal string such as 1.25; JSON numbers must also satisfy the numeric precision limits.

plan_currencystring

A supported currency code (e.g., USD, EUR).

plan_durationstring

Duration of the plan (e.g., '1 hour', '1 day', '1 month').

plan_price_formattedstring

Formatted price display string (e.g., '$10.00').

plan_targetsarray

Target selections, for example [{"kind":"role","external_id":"123456789012345678"}]. Each kind is role, channel or group; external_id is the platform numeric ID as a string.

plan_dataobject

Additional plan configuration options.

plan_data.plan_recurringboolean

Whether the plan supports recurring payments.

plan_data.plan_one_timeboolean

Whether the plan supports one-time payments.

plan_data.plan_trialstring

Trial duration, for example '1 day'. Use a positive relative duration for a trial, not an absolute date or lifetime '0'.

All listed top-level fields are optional; unknown top-level fields are rejected. Recognized plan_data properties merge with existing properties, but a supplied plan_data object defaults omitted plan_recurring to false and omitted plan_one_time to true. Include both flags when changing trial configuration.

For example, {"plan_data":{"plan_recurring":false,"plan_one_time":true,"plan_trial":"1 day"}} switches the plan to a nonrecurring trial. This changes configuration, not trial history: a customer with a completed checkout on the same plan does not become eligible again. See Create a Trial Plan and Automatic Trial Checkout.

Prices follow the decimal input rules and the resulting currency's precision. USD allows 2 decimal places, JPY 0, BTC 8, and ETH 18; trailing zeroes do not add precision. Changing only plan_currency validates the stored price against the new currency. For example, switching a plan priced at "10.01" to JPY returns 422 VALIDATION_ERROR.

An unchanged stored price can be retained even if it exceeds the currency's decimal limit. Unrelated edits do not require a price correction. Resending an unchanged price and currency must still satisfy the input schema. A changed price or currency must satisfy the resulting currency limit.

Recurring plans require a finite duration; lifetime "0" is not supported for recurring billing. plan_price_formatted is a separate display string; "1" is valid without a currency symbol.

A universal plan can return expanded applicable targets with is_universal: true; a populated plan_targets array does not make it a restricted plan.

Add or remove this plan's targets

plan_targets replaces the plan's explicit target selection. To add a target, send the existing selections plus the new one. To remove a target, send the selections you want to keep. Omitting plan_targets leaves the selection unchanged.

For example, this request selects a Telegram channel and group using their platform IDs as strings:

{
  "plan_targets": [
    { "kind": "channel", "external_id": "-1001234567890" },
    { "kind": "group", "external_id": "-1002345678901" }
  ]
}

To remove the channel from this plan, send only the group entry. Other plans using that channel keep their selections. Read the plan back to confirm is_universal: false and the expanded target objects.

Warning

Sending {"plan_targets":[]} removes the explicit restriction and makes the plan universal across applicable project targets. It does not disable access. The response uses is_universal: true and can contain a populated plan_targets array.

Changing a target's name or enabled state uses the separate target update endpoint and affects that shared target across plans.

Last updated: