Plan
Stored in the plans collection. createdAt and updatedAt are maintained automatically.
Returned by GET /plans, GET /plans/:id.
Example
One real Plan as returned by GET /plans, taken from the data array. Recorded from a live response, so the defaults, denormalised snapshots and populated fields are the actual ones:
{
"_id": "6a92bf047e50e22b4b82953e",
"name": "Free",
"description": "Starter free plan for basic CRM usage.",
"billingType": "free",
"countries": [],
"maxUsersAllowed": -1,
"features": [
{
"quantity": -1,
"feature": {
"_id": "6a92bda6ebbc3b463dbbec83",
"name": "Contact",
"status": "active"
},
"billingCycleQuantities": [],
"addOnPricing": [],
"fieldThreshold": 4
},
{
"quantity": -1,
"feature": {
"_id": "6a92bda6ebbc3b463dbbec84",
"name": "Lead",
"status": "active"
},
"billingCycleQuantities": [],
"addOnPricing": [],
"fieldThreshold": 4
},
"…and 12 more"
],
"enableTrial": false,
"enableAllowExtraDuration": false,
"isRecommended": false,
"status": "active",
"createdBy": {},
"updatedBy": {},
"billingCycles": [],
"__v": 1,
"createdAt": "2026-08-29T11:14:12.763Z",
"updatedAt": "2026-08-29T11:14:36.356Z",
"freePlanAlreadyUsed": true
}
:::note Trimmed for reading A populated reference is shown by the fields that identify it rather than in full — it arrives as the entire referenced document. Long arrays are cut to the first two entries and marked, long strings are truncated, and any field that could carry a credential is dropped rather than masked. :::
Fields
| Field | Type | Notes |
|---|---|---|
name | string | required |
description | string | |
billingType | string | required · one of free, paid |
currency | string | |
countries | string[] | default [] |
billingCycles | object[] | default [] |
billingCycles.type | string | required · one of Monthly, Quarterly, Half Yearly, Yearly |
billingCycles.price | number | required |
billingCycles.enableSalePrice | boolean | default false |
billingCycles.salePrice | number | |
billingCycles.saleDurationType | string | default noDate · one of noDate, custom |
billingCycles.saleStartDate | date | |
billingCycles.saleEndDate | date | |
billingCycles._id | ObjectId | |
maxUsersAllowed | number | required |
features | object[] | default [] |
features.feature | ObjectId -> Feature | required |
features.quantity | number | |
features.billingCycleQuantities | object[] | default [] |
features.billingCycleQuantities.billingCycle | string | required · one of Monthly, Quarterly, Half Yearly, Yearly |
features.billingCycleQuantities.quantity | number | |
features.addOnPricing | object[] | default [] |
features.addOnPricing.mode | string | required · one of billing_cycle, custom_duration, one_time |
features.addOnPricing.price | number | default 0 |
features.addOnPricing.durationUnit | string | default null · one of day, month, billing_cycle, null |
features.addOnPricing.defaultDurationValue | number | default null |
features.fieldThreshold | number | default 4 |
enableTrial | boolean | default false |
trialDurationType | string | one of 30, 60, 90, custom |
trialDurationCustom | number | |
enableAllowExtraDuration | boolean | default false |
allowExtraDurationType | string | one of 30, 60, 90, custom |
extraDurationCustom | number | |
isRecommended | boolean | default false |
status | string | default inactive · one of active, inactive |
company | ObjectId -> Company | |
createdBy | ObjectId -> Member | |
updatedBy | ObjectId -> Member | |
_id | ObjectId | |
createdAt | date | set once |
updatedAt | date |