Corpland Revenue

Features and plans

Manage the catalog from code. Most teams use the dashboard instead.

features.create

{
  "id": "credits",
  "name": "Credits",
  "type": "credit_system",
  "unit": "credits",
  "credit_schema": [
    { "feature_id": "videos", "credits": 10 },
    { "feature_id": "scripts", "credits": 2 }
  ],
  "credit_value_usd": 0.01,
  "markup": 0.3
}
  • type is metered, credit_system or boolean. For metered, consumable: false makes a count that never resets, such as seats.
  • event_names on a metered feature, such as ["message-sent"], lets one track with that event_name drain every feature that listens to it.
  • credit_value_usd and markup on a credit system let balances.track_tokens price AI tokens. With a value of 0.01 and a markup of 0.3, a call that cost $0.50 spends 65 credits.
  • Ids are lowercase letters, numbers and underscores, and never change.

features.update, features.get, features.delete, features.list

features.update takes { "feature_id", ...fields }. features.delete removes a feature no plan or balance uses, and archives it otherwise. features.list and features.get work with a publishable key.

plans.create

{
  "id": "pro",
  "name": "Pro",
  "interval": "month",
  "group": "main",
  "prices": [{ "currency": "USD", "amount": 2000 }, { "currency": "GHS", "amount": 30000 }],
  "trial_days": 7,
  "trial_card_required": true,
  "items": [
    { "feature_id": "messages", "included": 100, "interval": "month", "rollover": { "max": 50, "duration_cycles": 1 } },
    { "feature_id": "api_calls", "included": 1000, "usage_model": "usage_based", "unit_prices": [{ "currency": "USD", "amount": 100 }], "billing_units": 1000, "max_purchase": 5000 },
    { "feature_id": "seats", "included": 3, "usage_model": "usage_based", "unit_prices": [{ "currency": "USD", "amount": 500 }], "proration": "prorate_immediately" },
    { "feature_id": "sso" }
  ],
  "billing_controls": { "usage_limits": [{ "feature_id": "messages", "limit": 200, "interval": "day" }] }
}

Amounts are minor units: 2000 is $20.00 and 30000 is GHS 300.00.

Plan fieldMeaning
intervalBilling interval: week, month, quarter, semi_annual, year or one_off
groupPlans in a group replace each other. Add ons and other groups stack
is_default (or auto_enable)Free plans given to every new customer
is_add_onBought on top of a main plan
trial_days, trial_card_requiredA free trial, once per customer. With a card required, the card is checked with a small charge refunded at once and the plan bills when the trial ends
billing_controlsDefaults for every customer on the plan. A rule on the customer replaces the plan's for the same feature
Item fieldMeaning
includedAmount granted. unlimited: true never blocks
interval, interval_countHow often it resets: hour to year, or none. interval_count: 4 with hour resets every 4 hours
usage_modelincluded (default), prepaid (bought in packs with feature_quantities at attach) or usage_based (pay as you go, billed at the end of the period)
unit_prices, billing_unitsPrice per pack, such as USD 1.00 per 1,000 calls
tiers, tier_behavior[{ "up_to": 1000, "unit_prices": [...] }, { "up_to": null, ... }]. graduated prices each tier on its own; volume prices everything at the tier the total lands in
max_purchaseThe most a customer can use or buy, counting the included amount
reset_usage_when_enabledtrue (default) gives the full amount when the plan starts. false keeps usage from the plan before
rollover{ "max": 50, "duration_cycles": 1 } carries unused amounts into the next periods, up to max
prorationFor counts that never reset, such as seats: prorate_immediately charges extras for the days left, prorate_next_cycle and none wait for renewal

plans.update

{ "plan_id": "pro", ...fields }. Changing prices or items on a plan with customers creates a new version and answers new_version_created: true. Current customers keep their version, price included, until you migrate them. Send "disable_version": true to change the plan in place.

plans.versions and plans.migrate

plans.versions with { "plan_id": "pro" } lists every version with its subscriber count. plans.migrate with { "plan_id": "pro", "from_version"?: 1, "to_version"?: 2, "customer_ids"?: [...] } moves subscribers. Their grants change now and usage carries over; the new price applies from their next renewal.

plans.list, plans.get, plans.delete

plans.list and plans.get work with a publishable key, so a pricing page can read them from the browser. Pass customer_id with a secret key to get eligibility. plans.delete removes a plan nobody ever had and archives it otherwise.

On this page