Line Item

Line Item

A line item represents a subscription or fee attached to a deal. Line items are the basis for revenue recognition in Planhat - mrr, arr, and value roll up from line items to their parent deal and company.

Line items have two product types: **subscription** (recurring revenue with a start and end dates and recurring revenue) and **fee** (one-off charges with a start date and value). Different field rules apply depending on the type.

Subscriptions can either have fixedPeriod be true, in which case fromDate, toDate, length and mrr/arr/value must be defined, or they can have fixedPeriod be false (AKA an evergreen subscription), in which case only fromDate and mrr/arr must be defined. Once an evergreen line item is cancelled, you can set its status as such, and populate an end date.

If you provide the productId when creating a line item, any fields defined on the product level not defined in the creation payload will be autofilled on the new line item, appending the data you provided. E.g. if creating a line item and providing fromDate but no toDate, toDate and length will be populated on the line item from the product catalog.

Line items must belong to a Deal. The recurring or non-recurring revenue (mrr/arr or value) on a line item is recognised as contracted revenue when the parent deal stage is set to Closed Won.

The status of a line item is auto-set to ongoing, but can be set to renewed or lost. This is not important for revenue recognition as that is based on the deal stage and the date-span of line items, not their status, but it can be useful if using Planhat's native auto-renewal features.

mrr and arr are bidirectionally calculated fields, meaning that if one value is provided, the other will be calculated by the system. This also extends to the value field, in cases where the line item has both a fromDate and toDate.

Property

Required

Type

Description

_id


objectId

Planhat identifier.

externalId


string

The line item id in your own system.

sourceId


string

The line item id from an integration (Salesforce, HubSpot, etc).

dealId

Yes

objectId

Related deal id (Planhat identifier).

dealName


string

Deal name. (Autogenerated).

companyId


objectId

Related company id. Inherited from the deal. (Autogenerated).

companyName


string

Company name. (Autogenerated).

productId


objectId

Related product id (Planhat identifier).

productName


string

Product name. (Autogenerated).

productType


string

Type of line item. Either subscription or fee. Defaults to subscription. Locked once a product is selected.

package


string

Package name associated with the line item.

fromDate

Yes

date

Start date of the line item.

toDate

Conditional

date

End date of the line item. Required when fixedPeriod is true and no length is set, or when status is renewed or lost and no length is set. Locked when productType is fee.

status


string

Status of the line item. One of ongoing, renewed, lost. Defaults to ongoing.

fixedPeriod


boolean

Whether the line item has a fixed end date. Locked when productType is fee.

autoRenews


boolean

Whether the line item auto-renews.

length


number

Length of the subscription period in months. Can be used instead of toDate. Locked when productType is fee.

mrr

Conditional

number

Monthly Recurring Revenue. Required for subscriptions unless arr or value is provided. Locked when productType is fee.

arr

Conditional

number

Annual Recurring Revenue. Calculated from mrr. Required for subscriptions unless mrr or value is provided. Locked when productType is fee.

value

Conditional

number

Total value. Required when productType is fee. Also accepted in place of mrr/arr for subscriptions.

currency


string

Currency of the line item. (Autogenerated from company).

revenueRecognized


boolean

Whether revenue has been recognized. (Autogenerated).

renewalDate


date

Expected renewal date.

renewalDaysFromNow


number

Days until renewal from today.

renewalPeriod


number

Renewal period length in months.

renewalUnit


string

Unit for the renewal period. Can be "day", "week", or "month". Defaults to

"month". (Autogenerated)

renewalMrr


number

Expected MRR at renewal.

renewalArr


number

Expected ARR at renewal. Calculated from renewalMrr.

noticePeriod


number

Notice period length.

noticeUnit


string

Unit for the notice period. One of day, week, month.

fcNewMrr


number

MRR forecast.

fcNewArr


number

ARR forecast. Calculated from fcNewMrr.

fcNewMrrOptimistic


number

Optimistic MRR forecast.

fcNewArrOptimistic


number

Optimistic ARR forecast. Calculated from fcNewMrrOptimistic.

fcNewMrrPessimistic


number

Pessimistic MRR forecast.

fcNewArrPessimistic


number

Pessimistic ARR forecast. Calculated from fcNewMrrPessimistic.

parent


objectId

The parent line item this was renewed from.

custom


object

A flexible object with custom data.

createdAt


date time

ISO date when line item was created. (Autogenerated).

updatedAt


date time

ISO date when line item was last updated. (Autogenerated).

A line item represents a subscription or fee attached to a deal. Line items are the basis for revenue recognition in Planhat - mrr, arr, and value roll up from line items to their parent deal and company.

Line items have two product types: **subscription** (recurring revenue with a start and end dates and recurring revenue) and **fee** (one-off charges with a start date and value). Different field rules apply depending on the type.

Subscriptions can either have fixedPeriod be true, in which case fromDate, toDate, length and mrr/arr/value must be defined, or they can have fixedPeriod be false (AKA an evergreen subscription), in which case only fromDate and mrr/arr must be defined. Once an evergreen line item is cancelled, you can set its status as such, and populate an end date.

If you provide the productId when creating a line item, any fields defined on the product level not defined in the creation payload will be autofilled on the new line item, appending the data you provided. E.g. if creating a line item and providing fromDate but no toDate, toDate and length will be populated on the line item from the product catalog.

Line items must belong to a Deal. The recurring or non-recurring revenue (mrr/arr or value) on a line item is recognised as contracted revenue when the parent deal stage is set to Closed Won.

The status of a line item is auto-set to ongoing, but can be set to renewed or lost. This is not important for revenue recognition as that is based on the deal stage and the date-span of line items, not their status, but it can be useful if using Planhat's native auto-renewal features.

mrr and arr are bidirectionally calculated fields, meaning that if one value is provided, the other will be calculated by the system. This also extends to the value field, in cases where the line item has both a fromDate and toDate.

Property

Required

Type

Description

_id


objectId

Planhat identifier.

externalId


string

The line item id in your own system.

sourceId


string

The line item id from an integration (Salesforce, HubSpot, etc).

dealId

Yes

objectId

Related deal id (Planhat identifier).

dealName


string

Deal name. (Autogenerated).

companyId


objectId

Related company id. Inherited from the deal. (Autogenerated).

companyName


string

Company name. (Autogenerated).

productId


objectId

Related product id (Planhat identifier).

productName


string

Product name. (Autogenerated).

productType


string

Type of line item. Either subscription or fee. Defaults to subscription. Locked once a product is selected.

package


string

Package name associated with the line item.

fromDate

Yes

date

Start date of the line item.

toDate

Conditional

date

End date of the line item. Required when fixedPeriod is true and no length is set, or when status is renewed or lost and no length is set. Locked when productType is fee.

status


string

Status of the line item. One of ongoing, renewed, lost. Defaults to ongoing.

fixedPeriod


boolean

Whether the line item has a fixed end date. Locked when productType is fee.

autoRenews


boolean

Whether the line item auto-renews.

length


number

Length of the subscription period in months. Can be used instead of toDate. Locked when productType is fee.

mrr

Conditional

number

Monthly Recurring Revenue. Required for subscriptions unless arr or value is provided. Locked when productType is fee.

arr

Conditional

number

Annual Recurring Revenue. Calculated from mrr. Required for subscriptions unless mrr or value is provided. Locked when productType is fee.

value

Conditional

number

Total value. Required when productType is fee. Also accepted in place of mrr/arr for subscriptions.

currency


string

Currency of the line item. (Autogenerated from company).

revenueRecognized


boolean

Whether revenue has been recognized. (Autogenerated).

renewalDate


date

Expected renewal date.

renewalDaysFromNow


number

Days until renewal from today.

renewalPeriod


number

Renewal period length in months.

renewalUnit


string

Unit for the renewal period. Can be "day", "week", or "month". Defaults to

"month". (Autogenerated)

renewalMrr


number

Expected MRR at renewal.

renewalArr


number

Expected ARR at renewal. Calculated from renewalMrr.

noticePeriod


number

Notice period length.

noticeUnit


string

Unit for the notice period. One of day, week, month.

fcNewMrr


number

MRR forecast.

fcNewArr


number

ARR forecast. Calculated from fcNewMrr.

fcNewMrrOptimistic


number

Optimistic MRR forecast.

fcNewArrOptimistic


number

Optimistic ARR forecast. Calculated from fcNewMrrOptimistic.

fcNewMrrPessimistic


number

Pessimistic MRR forecast.

fcNewArrPessimistic


number

Pessimistic ARR forecast. Calculated from fcNewMrrPessimistic.

parent


objectId

The parent line item this was renewed from.

custom


object

A flexible object with custom data.

createdAt


date time

ISO date when line item was created. (Autogenerated).

updatedAt


date time

ISO date when line item was last updated. (Autogenerated).

https://api.planhat.com/lineitems

To create a line item, `dealId` and `fromDate` are required. You can reference the deal using its externalId or sourceId: `"dealId": "extid-[deal externalId]"` or `"dealId": "srcid-[deal sourceId]"`.

For **subscriptions**: at least one of `mrr`, `arr`, or `value` is required. For **fees**: `value` is required.

Example Request
curl --location -g --request POST 'https://api.planhat.com/lineitems' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '{
    "dealId": "610091916d643a7c418aef42",
    "productId": "61009abc6d643a7c418aef99",
    "fromDate": "2026-06-01",
    "toDate": "2027-05-31",
    "mrr": 5000,
    "fixedPeriod": true
  }'
Example Response
{
  "_id": "610097ab6d643a7c418af100",
  "dealId": "610091916d643a7c418aef42",
  "dealName": "Acme Renewal 2026",
  "companyId": "61006bc89a3e0b702ed8ea49",
  "companyName": "Acme",
  "productId": "61009abc6d643a7c418aef99",
  "productName": "Platform",
  "productType": "subscription",
  "fromDate": "2026-06-01T00:00:00.000Z",
  "toDate": "2027-05-31T00:00:00.000Z",
  "mrr": 5000,
  "arr": 60000,
  "fixedPeriod": true,
  "status": "ongoing",
  "autoRenews": false,
  "createdAt": "2026-05-11T10:00:00.000Z",
  "updatedAt": "2026-05-11T10:00:00.000Z"
}
https://api.planhat.com/lineitems

To create a line item, `dealId` and `fromDate` are required. You can reference the deal using its externalId or sourceId: `"dealId": "extid-[deal externalId]"` or `"dealId": "srcid-[deal sourceId]"`.

For **subscriptions**: at least one of `mrr`, `arr`, or `value` is required. For **fees**: `value` is required.

Example Request
curl --location -g --request POST 'https://api.planhat.com/lineitems' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '{
    "dealId": "610091916d643a7c418aef42",
    "productId": "61009abc6d643a7c418aef99",
    "fromDate": "2026-06-01",
    "toDate": "2027-05-31",
    "mrr": 5000,
    "fixedPeriod": true
  }'
Example Response
{
  "_id": "610097ab6d643a7c418af100",
  "dealId": "610091916d643a7c418aef42",
  "dealName": "Acme Renewal 2026",
  "companyId": "61006bc89a3e0b702ed8ea49",
  "companyName": "Acme",
  "productId": "61009abc6d643a7c418aef99",
  "productName": "Platform",
  "productType": "subscription",
  "fromDate": "2026-06-01T00:00:00.000Z",
  "toDate": "2027-05-31T00:00:00.000Z",
  "mrr": 5000,
  "arr": 60000,
  "fixedPeriod": true,
  "status": "ongoing",
  "autoRenews": false,
  "createdAt": "2026-05-11T10:00:00.000Z",
  "updatedAt": "2026-05-11T10:00:00.000Z"
}
https://api.planhat.com/lineitems

To create a line item, `dealId` and `fromDate` are required. You can reference the deal using its externalId or sourceId: `"dealId": "extid-[deal externalId]"` or `"dealId": "srcid-[deal sourceId]"`.

For **subscriptions**: at least one of `mrr`, `arr`, or `value` is required. For **fees**: `value` is required.

Example Request
curl --location -g --request POST 'https://api.planhat.com/lineitems' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '{
    "dealId": "610091916d643a7c418aef42",
    "productId": "61009abc6d643a7c418aef99",
    "fromDate": "2026-06-01",
    "toDate": "2027-05-31",
    "mrr": 5000,
    "fixedPeriod": true
  }'
Example Response
{
  "_id": "610097ab6d643a7c418af100",
  "dealId": "610091916d643a7c418aef42",
  "dealName": "Acme Renewal 2026",
  "companyId": "61006bc89a3e0b702ed8ea49",
  "companyName": "Acme",
  "productId": "61009abc6d643a7c418aef99",
  "productName": "Platform",
  "productType": "subscription",
  "fromDate": "2026-06-01T00:00:00.000Z",
  "toDate": "2027-05-31T00:00:00.000Z",
  "mrr": 5000,
  "arr": 60000,
  "fixedPeriod": true,
  "status": "ongoing",
  "autoRenews": false,
  "createdAt": "2026-05-11T10:00:00.000Z",
  "updatedAt": "2026-05-11T10:00:00.000Z"
}
https://api.planhat.com/lineitems/:_id

You can also use prefixed identifiers:

https://api.planhat.com/lineitems/extid-{{externalId}}

Or

https://api.planhat.com/lineitems/srcid-{{sourceId}}


Example Request
curl --location -g --request PUT 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '{
    "status": "renewed",
    "renewalMrr": 5500
  }'
https://api.planhat.com/lineitems/:_id

You can also use prefixed identifiers:

https://api.planhat.com/lineitems/extid-{{externalId}}

Or

https://api.planhat.com/lineitems/srcid-{{sourceId}}


Example Request
curl --location -g --request PUT 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '{
    "status": "renewed",
    "renewalMrr": 5500
  }'
https://api.planhat.com/lineitems/:_id

You can also use prefixed identifiers:

https://api.planhat.com/lineitems/extid-{{externalId}}

Or

https://api.planhat.com/lineitems/srcid-{{sourceId}}


Example Request
curl --location -g --request PUT 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '{
    "status": "renewed",
    "renewalMrr": 5500
  }'
https://api.planhat.com/lineitems/:_id

To get a specific line item, pass the _id in the request URL. Alternatively use a prefixed externalId or sourceId:

https://api.planhat.com/lineitems/extid-{{externalId}}

Or

https://api.planhat.com/lineitems/srcid-{{sourceId}}
Example Request
curl --location -g --request GET 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
https://api.planhat.com/lineitems/:_id

To get a specific line item, pass the _id in the request URL. Alternatively use a prefixed externalId or sourceId:

https://api.planhat.com/lineitems/extid-{{externalId}}

Or

https://api.planhat.com/lineitems/srcid-{{sourceId}}
Example Request
curl --location -g --request GET 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
https://api.planhat.com/lineitems/:_id

To get a specific line item, pass the _id in the request URL. Alternatively use a prefixed externalId or sourceId:

https://api.planhat.com/lineitems/extid-{{externalId}}

Or

https://api.planhat.com/lineitems/srcid-{{sourceId}}
Example Request
curl --location -g --request GET 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
https://api.planhat.com/lineitems

The following query params are available:

  • companyId — Filter by company id. Multiple ids can be separated by commas.

  • dealId — Filter by deal id.

  • limit — Limit the list length. Default 100, max 2000.

  • offset — Start the list at a specific integer index.

  • sort — Sort by a specific property. Prefix with - to reverse sort order.

  • select — Return specific properties only. Multiple properties separated by commas.

Example Request
curl --location -g --request GET 'https://api.planhat.com/lineitems?dealId=610091916d643a7c418aef42' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
https://api.planhat.com/lineitems

The following query params are available:

  • companyId — Filter by company id. Multiple ids can be separated by commas.

  • dealId — Filter by deal id.

  • limit — Limit the list length. Default 100, max 2000.

  • offset — Start the list at a specific integer index.

  • sort — Sort by a specific property. Prefix with - to reverse sort order.

  • select — Return specific properties only. Multiple properties separated by commas.

Example Request
curl --location -g --request GET 'https://api.planhat.com/lineitems?dealId=610091916d643a7c418aef42' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
https://api.planhat.com/lineitems

The following query params are available:

  • companyId — Filter by company id. Multiple ids can be separated by commas.

  • dealId — Filter by deal id.

  • limit — Limit the list length. Default 100, max 2000.

  • offset — Start the list at a specific integer index.

  • sort — Sort by a specific property. Prefix with - to reverse sort order.

  • select — Return specific properties only. Multiple properties separated by commas.

Example Request
curl --location -g --request GET 'https://api.planhat.com/lineitems?dealId=610091916d643a7c418aef42' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
https://api.planhat.com/lineitems/:_id

To delete a line item, pass the _id in the request URL.

Example Request
curl --location -g --request DELETE 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
Example Response
{
  "n": 1,
  "ok": 1,
  "deletedCount": 1
}
https://api.planhat.com/lineitems/:_id

To delete a line item, pass the _id in the request URL.

Example Request
curl --location -g --request DELETE 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
Example Response
{
  "n": 1,
  "ok": 1,
  "deletedCount": 1
}
https://api.planhat.com/lineitems/:_id

To delete a line item, pass the _id in the request URL.

Example Request
curl --location -g --request DELETE 'https://api.planhat.com/lineitems/610097ab6d643a7c418af100' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}'
Example Response
{
  "n": 1,
  "ok": 1,
  "deletedCount": 1
}
https://api.planhat.com/lineitems

To create a line item, dealId and fromDate are required. To update, specify one of the following keyables in the payload (in order of priority): _id, sourceId, externalId. There is an upper limit of 5,000 items per request.

Example Request
curl --location -g --request PUT 'https://api.planhat.com/lineitems' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '[
    {
      "externalId": "li-001",
      "dealId": "extid-deal-001",
      "fromDate": "2026-06-01",
      "toDate": "2027-05-31",
      "mrr": 5000,
      "fixedPeriod": true
    },
    {
      "externalId": "li-002",
      "dealId": "extid-deal-001",
      "fromDate": "2026-06-01",
      "productType": "fee",
      "value": 2000
    }
  ]

Example Response
{
  "created": 2,
  "createdErrors": [],
  "insertsKeys": [
    { "_id": "610097ab6d643a7c418af100", "externalId": "li-001" },
    { "_id": "610097ab6d643a7c418af101", "externalId": "li-002" }
  ],
  "updated": 0,
  "updatedErrors": [],
  "updatesKeys": [],
  "nonupdates": 0,
  "modified": [],
  "upsertedIds": ["610097ab6d643a7c418af100", "610097ab6d643a7c418af101"],
  "permissionErrors": []
}
https://api.planhat.com/lineitems

To create a line item, dealId and fromDate are required. To update, specify one of the following keyables in the payload (in order of priority): _id, sourceId, externalId. There is an upper limit of 5,000 items per request.

Example Request
curl --location -g --request PUT 'https://api.planhat.com/lineitems' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '[
    {
      "externalId": "li-001",
      "dealId": "extid-deal-001",
      "fromDate": "2026-06-01",
      "toDate": "2027-05-31",
      "mrr": 5000,
      "fixedPeriod": true
    },
    {
      "externalId": "li-002",
      "dealId": "extid-deal-001",
      "fromDate": "2026-06-01",
      "productType": "fee",
      "value": 2000
    }
  ]

Example Response
{
  "created": 2,
  "createdErrors": [],
  "insertsKeys": [
    { "_id": "610097ab6d643a7c418af100", "externalId": "li-001" },
    { "_id": "610097ab6d643a7c418af101", "externalId": "li-002" }
  ],
  "updated": 0,
  "updatedErrors": [],
  "updatesKeys": [],
  "nonupdates": 0,
  "modified": [],
  "upsertedIds": ["610097ab6d643a7c418af100", "610097ab6d643a7c418af101"],
  "permissionErrors": []
}
https://api.planhat.com/lineitems

To create a line item, dealId and fromDate are required. To update, specify one of the following keyables in the payload (in order of priority): _id, sourceId, externalId. There is an upper limit of 5,000 items per request.

Example Request
curl --location -g --request PUT 'https://api.planhat.com/lineitems' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer {{apiToken}}' \
  --data-raw '[
    {
      "externalId": "li-001",
      "dealId": "extid-deal-001",
      "fromDate": "2026-06-01",
      "toDate": "2027-05-31",
      "mrr": 5000,
      "fixedPeriod": true
    },
    {
      "externalId": "li-002",
      "dealId": "extid-deal-001",
      "fromDate": "2026-06-01",
      "productType": "fee",
      "value": 2000
    }
  ]

Example Response
{
  "created": 2,
  "createdErrors": [],
  "insertsKeys": [
    { "_id": "610097ab6d643a7c418af100", "externalId": "li-001" },
    { "_id": "610097ab6d643a7c418af101", "externalId": "li-002" }
  ],
  "updated": 0,
  "updatedErrors": [],
  "updatesKeys": [],
  "nonupdates": 0,
  "modified": [],
  "upsertedIds": ["610097ab6d643a7c418af100", "610097ab6d643a7c418af101"],
  "permissionErrors": []
}