create_product_rate_plan_charge
Create a new rate plan charge for a product subscription. Define charge type, model, tiers, billing cycle, and tax settings.
Instructions
Create a rate plan charge. POST /product-rateplan-charges. Required: ratePlanId (rate plan reference, URI: /product-rateplans/{ratePlanId}), name, chargeType (oneTime|recurring|usage), chargeModel (flatFeePricing|perUnitPricing|tieredPricing|volumePricing), billCycleType, category (physical|digital), chargeTier (array of {currency ex. 'USD', price in cents, optional startingUnit, endingUnit, priceFormat, tier}), taxable, weight. Optional: billingPeriod (day|week|month|year), billingTiming (inAdvance|inArrears), description, etc.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ratePlanId | Yes | Rate plan ID (URI: /product-rateplans/{ratePlanId}) | |
| name | Yes | Charge name | |
| chargeType | Yes | oneTime, recurring, or usage | |
| chargeModel | Yes | flatFeePricing, perUnitPricing, tieredPricing, or volumePricing | |
| billCycleType | Yes | Bill cycle type (e.g. chargeTriggerDay, specificDayOfMonth) | |
| category | Yes | physical or digital | |
| chargeTier | Yes | Array of {currency, price, optional startingUnit, endingUnit, priceFormat, tier} | |
| taxable | Yes | Whether taxable | |
| weight | Yes | Weight (integer) | |
| description | No | Description | |
| billingPeriod | No | day, week, month, or year (required if chargeType recurring) | |
| billingTiming | No | inAdvance or inArrears (required if chargeType recurring) | |
| billingPeriodAlignment | No | alignToCharge, alignToSubscriptionStart, alignToTermStart | |
| specificBillingPeriod | No | Specific billing period | |
| allowChangeQuantity | No | Allow change quantity | |
| billCycleDay | No | 1-31 when billCycleType specificDayOfMonth | |
| weeklyBillCycleDay | No | sunday..saturday when billCycleType specificDayOfWeek | |
| monthlyBillCycleYear | No | 1-12 when billCycleType specificMonthOfYear | |
| endDateCondition | Yes | subscriptionEnd or fixedPeriod (required) | |
| isFreeShipping | No | Free shipping | |
| maxQuantity | No | Max quantity | |
| minQuantity | No | Min quantity | |
| quantity | No | Quantity | |
| listPriceBase | No | perMonth, perBillingPeriod, or perWeek |
Implementation Reference
- Handler function that parses and validates input via Zod schema, constructs the request body from parsed data, then delegates to the service layer's createRatePlanCharge function via handleToolCall.
async function handler(client: Client, args: Record<string, unknown> | undefined) { const parsed = schema.safeParse(args); if (!parsed.success) { return errorResult(parsed.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ")); } const data = parsed.data; const body = { ratePlanId: data.ratePlanId, name: data.name, chargeType: data.chargeType, chargeModel: data.chargeModel, billCycleType: data.billCycleType, category: data.category, chargeTier: data.chargeTier, taxable: data.taxable, weight: data.weight, endDateCondition: data.endDateCondition, description: data.description, billingPeriod: data.billingPeriod, billingTiming: data.billingTiming, billingPeriodAlignment: data.billingPeriodAlignment, specificBillingPeriod: data.specificBillingPeriod, allowChangeQuantity: data.allowChangeQuantity, billCycleDay: data.billCycleDay, weeklyBillCycleDay: data.weeklyBillCycleDay, monthlyBillCycleYear: data.monthlyBillCycleYear, isFreeShipping: data.isFreeShipping, maxQuantity: data.maxQuantity, minQuantity: data.minQuantity, quantity: data.quantity, listPriceBase: data.listPriceBase, }; return handleToolCall(() => chargeService.createRatePlanCharge(client, body)); } export const createRatePlanChargeTool: Tool = { definition, handler, }; - Zod schema defining input validation for create_product_rate_plan_charge: required fields (ratePlanId, name, chargeType, chargeModel, billCycleType, category, chargeTier, taxable, weight, endDateCondition) plus many optional fields.
const chargeTierItemSchema = z.object({ currency: z.string().min(1), startingUnit: z.string().optional(), endingUnit: z.string().optional(), price: z.number().int(), priceFormat: z.string().optional(), tier: z.number().int().optional(), }); const schema = z.object({ ratePlanId: z.number().int().positive("ratePlanId is required"), name: z.string().min(1, "name is required"), chargeType: z.enum(chargeTypeEnum, { errorMap: () => ({ message: `chargeType must be one of: ${chargeTypeEnum.join(", ")}` }), }), chargeModel: z.enum(chargeModelEnum, { errorMap: () => ({ message: `chargeModel must be one of: ${chargeModelEnum.join(", ")}` }), }), billCycleType: z.enum(billCycleTypeEnum, { errorMap: () => ({ message: `billCycleType must be one of: ${billCycleTypeEnum.join(", ")}` }), }), category: z.enum(["physical", "digital"]), chargeTier: z.array(chargeTierItemSchema).min(1, "chargeTier must have at least one item"), taxable: z.boolean(), weight: z.coerce.number().int().min(0, "weight must be a non-negative number"), description: z.string().optional(), billingPeriod: z.enum(billingPeriodEnum).optional(), billingTiming: z.enum(billingTimingEnum).optional(), billingPeriodAlignment: z.string().optional(), specificBillingPeriod: z.number().int().optional(), allowChangeQuantity: z.boolean().optional(), billCycleDay: z.number().int().min(1).max(31).optional(), weeklyBillCycleDay: z.string().optional(), monthlyBillCycleYear: z.number().int().min(1).max(12).optional(), endDateCondition: z.enum(["subscriptionEnd", "fixedPeriod"]), isFreeShipping: z.boolean().optional(), maxQuantity: z.number().int().optional(), minQuantity: z.number().int().optional(), quantity: z.number().int().optional(), listPriceBase: z.enum(["perMonth", "perBillingPeriod", "perWeek"]).optional(), }); - src/tools/product_rate_plan_charges/index.ts:13-29 (registration)Registration function that includes createRatePlanChargeTool in the list of product rate plan charge tools. Called from src/tools/index.ts line 30.
export function registerProductRatePlanChargeTools(): Tool[] { return [ listRatePlanChargesTool, getRatePlanChargeTool, createRatePlanChargeTool, updateRatePlanChargeTool, deleteRatePlanChargeTool, ]; } export { listRatePlanChargesTool } from "./listRatePlanCharges.js"; export { getRatePlanChargeTool } from "./getRatePlanCharge.js"; export { createRatePlanChargeTool } from "./createRatePlanCharge.js"; export { updateRatePlanChargeTool } from "./updateRatePlanCharge.js"; export { deleteRatePlanChargeTool } from "./deleteRatePlanCharge.js"; - Helper utilities used by the create handler: errorResult, successResult, and handleToolCall for wrapping service calls with try/catch.
export function errorResult(message: string): ToolResult { return { content: [{ type: "text" as const, text: message }], isError: true, }; } export function successResult(data: unknown): ToolResult { return { content: [ { type: "text" as const, text: JSON.stringify(data, null, 2) }, ], }; } export async function handleToolCall<T>(fn: () => Promise<T>): Promise<ToolResult> { try { const data = await fn(); return successResult(data); } catch (err) { const message = err instanceof Error ? err.message : String(err); return errorResult(`Error: ${message}`); } } - Service layer function that normalizes weight and chargeTier (ensuring priceFormat defaults to ''), then POSTs to /product-rateplan-charges.
export async function createRatePlanCharge( client: Client, body: CreateRatePlanChargeBody ): Promise<unknown> { const payload = { ...body }; if (payload.weight != null) payload.weight = Number(payload.weight); if (payload.chargeTier?.length) payload.chargeTier = normalizeChargeTier(payload.chargeTier); return client.post<unknown>("/product-rateplan-charges", payload); }