Product Plans
Product plans define what you sell, both one-time purchases and recurring subscriptions. Each plan can have multiple price options with different billing intervals.
Create a product plan
POST
/product-plansRequest body
| Parameter | Type | Required | Description |
|---|---|---|---|
appId | string | Yes | Your app UUID |
name | string | Yes | Plan name (1–255 chars) |
prices | Price[] | Yes | Price options (min 1) |
description | string | No | Plan description (max 2000) |
imageUrl | string | No | Product image URL |
planType | "ONE_TIME" | "SUBSCRIPTION" | No | Plan type |
taxRateId | string | No | Default tax rate |
metadata | object | No | Arbitrary key-value metadata |
Price
| Field | Type | Required | Description |
|---|---|---|---|
amount | string | Yes | Price amount (decimal string) |
currency | string | No | Currency code (max 10, default: USD) |
billingInterval | string | No | MINUTE | DAY | WEEK | MONTH | YEAR |
billingIntervalCount | number | No | Interval multiplier (e.g. 3 for quarterly) |
trialPeriodDays | number | No | Free trial length in days |
nickname | string | No | Price label (max 100, e.g. "Monthly") |
sortOrder | number | No | Display ordering |
isDefault | boolean | No | Default price selection |
metadata | object | No | Price-level metadata |
List product plans
GET
/product-plansQuery parameters
| Parameter | Type | Description |
|---|---|---|
appId | string | Filter by app UUID |
planType | "ONE_TIME" | "SUBSCRIPTION" | Filter by plan type |
page | number | Page number (default: 1) |
pageSize | number | Items per page (max 100) |
Retrieve a product plan
GET
/product-plans/:idUpdate a product plan
PUT
/product-plans/:idAdd a price
POST
/product-plans/:id/pricesAdds a new price option to an existing product plan.
Update a price
PUT
/product-plans/:planId/prices/:priceId| Parameter | Type | Required | Description |
|---|---|---|---|
amount | string | No | Updated price amount |
nickname | string | No | Updated label |
sortOrder | number | No | Display order |
isDefault | boolean | No | Set as default |
isActive | boolean | No | Active/inactive |
trialPeriodDays | number | No | Trial days |
Deactivate a price
DELETE
/product-plans/:planId/prices/:priceIdDeactivates a price option (soft delete). Returns { deactivated: true }.
Response object
All responses are wrapped in { "success": true, "data": ... }. List endpoints add pagination.
ProductPlan fields
idstringUnique plan UUIDappIdstringApp this plan belongs tonamestringPlan display namedescriptionstring | nullPlan descriptionimageUrlstring | nullProduct image URLplanTypestringONE_TIME or SUBSCRIPTIONtaxRateIdstring | nullDefault tax rate UUIDisActivebooleanWhether the plan is activemetadataobjectArbitrary key-value pairscreatedAtstringISO 8601 creation timestampupdatedAtstringISO 8601 last-update timestamppricesProductPlanPrice[]Price options, sorted by sortOrder ascendingtaxRateTaxRate | nullFull tax rate object when linkedProductPlanPrice fields
idstringPrice UUIDproductPlanIdstringParent plan UUIDappIdstringApp UUIDamountstringPrice amount as decimal stringcurrencystringCurrency codebillingIntervalstring | nullMINUTE, DAY, WEEK, MONTH, or YEARbillingIntervalCountnumber | nullInterval multiplier (e.g. 3 for quarterly)trialPeriodDaysnumberFree trial length in daysnicknamestring | nullPrice label (e.g. 'Monthly')sortOrdernumberDisplay ordering (ascending)isDefaultbooleanWhether this is the default priceisActivebooleanWhether the price is activemetadataobjectPrice-level metadatacreatedAtstringISO 8601 creation timestampupdatedAtstringISO 8601 last-update timestamp💡
Endpoint variations
Retrieve additionally includes the
app object. Add price / update price return bare ProductPlanPrice scalars (no relations). Deactivate price returns { "deactivated": true }.