> ## Documentation Index
> Fetch the complete documentation index at: https://developers.hubspot.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Contracts API (BETA)

> Create and manage contracts and contract changes programmatically.

export const ExpandableParameter = ({name, type, required, expanded = false, className, children}) => {
  const [isExpanded, setIsExpanded] = useState(expanded);
  const contentId = `param-${name.replace(/\s+/g, '-')}`;
  const toggleExpanded = () => {
    setIsExpanded(!isExpanded);
  };
  return <>
      <dt className={`parameter-element element-title expandable ${isExpanded ? 'expanded' : 'collapsed'}${className ? ` ${className}` : ''}`}>
        <div className={`chevron-icon ${isExpanded ? 'expanded' : 'collapsed'}`} onClick={toggleExpanded} role="button" tabIndex={0} aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${name} parameter`} onKeyDown={e => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      toggleExpanded();
    }
  }}>
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
            <path fillRule="evenodd" clipRule="evenodd" d="M3.38065 0.381075C3.46191 0.299739 3.55841 0.235216 3.66462 0.191193C3.77083 0.147171 3.88468 0.124512 3.99965 0.124512C4.11463 0.124512 4.22847 0.147171 4.33468 0.191193C4.4409 0.235216 4.53739 0.299739 4.61865 0.381075L9.61865 5.38107C9.69999 5.46234 9.76451 5.55883 9.80853 5.66504C9.85256 5.77125 9.87522 5.8851 9.87522 6.00007C9.87522 6.11505 9.85256 6.2289 9.80853 6.33511C9.76451 6.44132 9.69999 6.53781 9.61865 6.61907L4.61865 11.6191C4.45435 11.7834 4.23151 11.8757 3.99915 11.8757C3.76679 11.8757 3.54395 11.7834 3.37965 11.6191C3.21535 11.4548 3.12305 11.2319 3.12305 10.9996C3.12305 10.7672 3.21535 10.5444 3.37965 10.3801L7.76265 6.00007L3.37965 1.61907C3.29832 1.53781 3.23379 1.44132 3.18977 1.33511C3.14575 1.2289 3.12309 1.11505 3.12309 1.00007C3.12309 0.885101 3.14575 0.771255 3.18977 0.665043C3.23379 0.558831 3.29932 0.462337 3.38065 0.381075Z" fill="currentColor" />
          </svg>
        </div>
        <button onClick={toggleExpanded} aria-expanded={isExpanded} aria-controls={contentId} aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${name} parameter details`} type="button" className="parameter-button">
          <div className="parameter-header">
            <code className="parameter-name">{name}</code>
            {type && <span className="parameter-type code-style">{type}</span>}
            {required && <span className="required-indicator">required</span>}
          </div>
        </button>
      </dt>
      {isExpanded && <dd className="parameter-element parameter-description" id={contentId}>
          {children}
        </dd>}
    </>;
};

export const Parameter = ({name, type, required, className, children}) => {
  return <>
      <dt className={`parameter-element element-title${className ? ` ${className}` : ''}`}>
        <div className="parameter-header">
          <code className="parameter-name">{name}</code>
          {type && <span className="parameter-type code-style">{type}</span>}
          {required && <span className="required-indicator">required</span>}
        </div>
      </dt>
      {children && <dd className="parameter-element parameter-description">
          {children}
        </dd>}
    </>;
};

export const ParameterList = ({className, children}) => {
  return <dl className={`parameter-list${className ? ` ${className}` : ''}`}>
      {children}
    </dl>;
};

export const BetaDisclaimerBanner = () => <Warning>
        This functionality is currently in beta. By participating in this beta, you agree to HubSpot's <a href="https://legal.hubspot.com/developer-terms">Developer Terms</a> and <a href="https://legal.hubspot.com/developerbetaterms">Developer Beta Terms</a>. Note that the functionality is still under active development and is subject to change based on testing and feedback.
    </Warning>;

export const RequiredIndicator = () => {
  return <span className="required-indicator">
      required
    </span>;
};

export const ScopesList = ({scopes = [], description = "This API requires one of the following scopes:"}) => {
  if (!scopes || scopes.length === 0) {
    return null;
  }
  const sortedScopes = scopes.sort((a, b) => a.localeCompare(b));
  return <div>
      <div className="text-sm mb-2">{description}</div>
      <div>
        {sortedScopes.map((scope, index) => <div key={index}>
            <code>
              <span className="text-xs">{scope}</span>
            </code>
          </div>)}
      </div>
    </div>;
};

<Accordion title="Required Scopes" icon="key">
  <ScopesList
    scopes={[
  'revenue.contracts.read',
  'revenue.contracts.write'
]}
  />
</Accordion>

<BetaDisclaimerBanner />

A contract is HubSpot's centralized source of truth for committed revenue, including terms, pricing, duration, and purchased line items. Contracts are typically created from an accepted quote and managed throughout the customer lifecycle via billing, invoicing, and mid-contract adjustments. Learn more about how contracts work on [HubSpot's Knowledge Base](https://knowledge.hubspot.com/contracts/understand-contracts-in-hubspot).

<Tip>
  The Contracts API documented on this page supports creating and managing contracts programmatically. For retrieving individual contract CRM records, use the [Contracts object API](/docs/api-reference/latest/crm/objects/contracts/guide).
</Tip>

## Contracts

### Create a contract

To create a contract, make a `POST` request to `/commerce/contracts/2027-03-beta/contracts`.

The request body must include `name`, `billingContactId`, `currencyCode`, `contractEffectiveDate`, and at least one entry in `lineItems`.

<Tabs>
  <Tab title="Example request">
    ```json theme={null}
    {
      "name": "Enterprise Platform License",
      "currencyCode": "USD",
      "contractEffectiveDate": "2026-09-01",
      "billingContactId": "12345678901",
      "hubspotBillingEnabled": true,
      "paymentEnabled": false,
      "collectionProcess": "MANUAL_PAYMENTS",
      "netPaymentTerms": 30,
      "lineItems": [
        {
          "mode": "CUSTOM",
          "name": "Platform license",
          "quantity": 1,
          "pricing": {
            "pricingModel": "FLAT",
            "prices": [
              {
                "currencyCode": "USD",
                "price": "1200.00"
              }
            ]
          },
          "recurringBillingFrequency": "ANNUALLY",
          "recurringBillingTerms": "AUTOMATICALLY_RENEW"
        }
      ]
    }
    ```

    | Property                                      | Type    | Description                                                                                                                                                                                                                                                                                                                                                                                                       |
    | --------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `name` <RequiredIndicator />                  | String  | The contract name.                                                                                                                                                                                                                                                                                                                                                                                                |
    | `currencyCode` <RequiredIndicator />          | String  | ISO 4217 currency code (e.g., `"USD"`). Cannot be changed after creation.                                                                                                                                                                                                                                                                                                                                         |
    | `contractEffectiveDate` <RequiredIndicator /> | String  | The date the contract takes effect, in `YYYY-MM-DD` format. Cannot be changed after creation. If the date is today or in the past, the contract status will be set to `ACTIVE`. If the date is in the future, the contract is assigned the `DRAFT` status and will be set to `ACTIVE` on that date.                                                                                                               |
    | `billingContactId` <RequiredIndicator />      | String  | ID of the contact to bill.                                                                                                                                                                                                                                                                                                                                                                                        |
    | `lineItems` <RequiredIndicator />             | Array   | Line items to include. At least one is required. See [line item modes](#modes) below.                                                                                                                                                                                                                                                                                                                             |
    | `hubspotBillingEnabled`                       | Boolean | Whether HubSpot manages billing for this contract. Cannot be changed after creation.                                                                                                                                                                                                                                                                                                                              |
    | `paymentEnabled`                              | Boolean | Whether online payment is enabled at checkout. Cannot be changed after creation.                                                                                                                                                                                                                                                                                                                                  |
    | `billingCompanyId`                            | String  | ID of the billing company.                                                                                                                                                                                                                                                                                                                                                                                        |
    | `dealId`                                      | String  | ID of the deal to associate with this contract.                                                                                                                                                                                                                                                                                                                                                                   |
    | `ownerId`                                     | String  | ID of the contract owner.                                                                                                                                                                                                                                                                                                                                                                                         |
    | `collectionProcess`                           | String  | How payments are collected. Allowed values: `"MANUAL_PAYMENTS"`, `"AUTOMATIC_PAYMENTS"`. Cannot be changed after creation.                                                                                                                                                                                                                                                                                        |
    | `allowedPaymentMethods`                       | Array   | Accepted payment methods. Allowed values: `"CREDIT_OR_DEBIT_CARD"`, `"ACH"`, `"SEPA"`, `"BACS"`, `"PADS"`.                                                                                                                                                                                                                                                                                                        |
    | `netPaymentTerms`                             | Integer | Number of days the buyer has to pay each invoice. Defaults to `0`.                                                                                                                                                                                                                                                                                                                                                |
    | `locale`                                      | String  | IETF locale tag (e.g., `"en-US"`).                                                                                                                                                                                                                                                                                                                                                                                |
    | `automatedTaxesEnabled`                       | Boolean | Whether automated sales tax is enabled for the contract (must be [enabled in your account](https://knowledge.hubspot.com/payments/set-up-automated-tax-and-tax-rates)). Defaults to `false`. When `true`:<ul><li>`taxRateGroupId` cannot be set on line items</li><li>You must include the `billingAddress` fields `address`, `state`, `zip`, and `countryCode`. See [address format](#address-format).</li></ul> |
    | `addressTypesToCollect`                       | Array   | Address types to collect at checkout. Allowed values: `"BILLING_ADDRESS"`, `"SHIPPING_ADDRESS"`.                                                                                                                                                                                                                                                                                                                  |
    | `billingAddress`                              | Object  | Billing address. See [address format](#address-format) below.                                                                                                                                                                                                                                                                                                                                                     |
    | `poNumber`                                    | String  | Purchase order number.                                                                                                                                                                                                                                                                                                                                                                                            |
    | `sellerCompanyName`                           | String  | Seller's company name. Defaults to the account's company name if not provided.                                                                                                                                                                                                                                                                                                                                    |
    | `sellerCompanyDomain`                         | String  | Seller's company website domain (e.g., `"example.com"`).                                                                                                                                                                                                                                                                                                                                                          |
    | `sellerCompanyAddress`                        | Object  | Seller's company address. See [address format](#address-format).                                                                                                                                                                                                                                                                                                                                                  |
    | `sellerEmail`                                 | String  | Seller's email address.                                                                                                                                                                                                                                                                                                                                                                                           |
    | `sellerFirstName`                             | String  | Seller's first name.                                                                                                                                                                                                                                                                                                                                                                                              |
    | `sellerLastName`                              | String  | Seller's last name.                                                                                                                                                                                                                                                                                                                                                                                               |
    | `sellerPhone`                                 | String  | Seller's phone number.                                                                                                                                                                                                                                                                                                                                                                                            |
    | `billingStartDateOverride`                    | String  | Date when billing schedule entries begin for the contract's recurring line items, in `YYYY-MM-DD` format. If not provided, billing starts from `contractEffectiveDate`.                                                                                                                                                                                                                                           |
    | `externalPaymentMethodReferenceId`            | String  | Reference ID of a payment method managed outside of HubSpot (e.g., a Stripe payment method ID).                                                                                                                                                                                                                                                                                                                   |
    | `customProperties`                            | Object  | Custom CRM property values as a string-to-string map.                                                                                                                                                                                                                                                                                                                                                             |
  </Tab>

  <Tab title="Example response">
    ```json theme={null}
    {
      "id": "420963644724",
      "createdAt": "2026-08-07T18:58:34.855Z",
      "updatedAt": "2026-08-07T18:58:36.063Z",
      "status": "DRAFT",
      "name": "Enterprise Platform License",
      "currencyCode": "USD",
      "contractEffectiveDate": "2026-09-01",
      "startDate": "2026-09-01",
      "billingContactId": "102",
      "lineItems": [
        {
          "id": "24584111229",
          "createdAt": "2026-08-07T18:58:35.295Z",
          "updatedAt": "2026-08-07T18:58:35.295Z",
          "pricing": {
            "pricingModel": "FLAT",
            "prices": [
              {
                "currencyCode": "USD",
                "price": "1200.00"
              }
            ]
          },
          "name": "Platform license",
          "quantity": 1,
          "price": "1200.00",
          "amount": "1200.00",
          "pricingModel": "FLAT",
          "totalDiscount": "0.00",
          "preDiscountAmount": "1200.00",
          "effectiveUnitPrice": "1200.00",
          "postTaxAmount": "1200.00",
          "acv": "1200.00",
          "arr": "1200.00",
          "mrr": "100.00",
          "tcv": "1200.00",
          "lineItemCurrencyCode": "USD",
          "positionOnQuote": 0,
          "recurringBillingFrequency": "ANNUALLY",
          "recurringBillingStartDate": "2026-09-01",
          "recurringBillingTerms": "AUTOMATICALLY_RENEW",
          "billingCycleAnchorDate": "2026-09-01",
          "billingStartDelayType": "HS_RECURRING_BILLING_START_DATE",
          "rampKey": "35a2886a-d838-44e6-aa18-ecc547275f12"
        }
      ],
      "customProperties": {},
      "addressTypesToCollect": [],
      "allowedPaymentMethods": [],
      "collectionProcess": "MANUAL_PAYMENTS",
      "netPaymentTerms": 30,
      "sellerCompanyName": "Coffee Inc.",
      "automatedTaxesEnabled": false,
      "hubspotBillingEnabled": true,
      "paymentEnabled": false,
      "storePaymentMethodAtCheckout": false
    }
    ```
  </Tab>
</Tabs>

<Warning>
  **Please note:** the following properties cannot be changed after a contract is created: `currencyCode`, `contractEffectiveDate`, `collectionProcess`, `hubspotBillingEnabled`, `paymentEnabled`.
</Warning>

### Retrieve a contract

To retrieve a contract, make a `GET` request to `/commerce/contracts/2027-03-beta/contracts/{contractId}`.

<Note>
  To batch retrieve or retrieve all contract records, use the [Contracts object API](/docs/api-reference/latest/crm/objects/contracts/guide).
</Note>

The response returns the full contract object, including all line items and their current billing configuration.

```json expandable theme={null}
{
  "id": "420963644724",
  "createdAt": "2026-08-07T18:58:34.855Z",
  "updatedAt": "2026-08-07T18:58:46.249Z",
  "status": "DRAFT",
  "name": "Enterprise Platform License",
  "currencyCode": "USD",
  "contractEffectiveDate": "2026-09-01",
  "startDate": "2026-09-01",
  "billingContactId": "102",
  "lineItems": [
    {
      "id": "24584111229",
      "createdAt": "2026-08-07T18:58:35.295Z",
      "updatedAt": "2026-08-07T18:58:35.931Z",
      "pricing": {
        "pricingModel": "FLAT",
        "prices": [
          {
            "currencyCode": "USD",
            "price": "1200.00"
          }
        ]
      },
      "name": "Platform license",
      "quantity": 1,
      "price": "1200.00",
      "amount": "1200.00",
      "pricingModel": "FLAT",
      "totalDiscount": "0.00",
      "preDiscountAmount": "1200.00",
      "effectiveUnitPrice": "1200.00",
      "postTaxAmount": "1200.00",
      "acv": "1200.00",
      "arr": "1200.00",
      "mrr": "100.00",
      "tcv": "1200.00",
      "lineItemCurrencyCode": "USD",
      "positionOnQuote": 0,
      "recurringBillingFrequency": "ANNUALLY",
      "recurringBillingStartDate": "2026-09-01",
      "recurringBillingTerms": "AUTOMATICALLY_RENEW",
      "billingCycleAnchorDate": "2026-09-01",
      "billingStartDelayType": "HS_RECURRING_BILLING_START_DATE",
      "rampKey": "35a2886a-d838-44e6-aa18-ecc547275f12"
    }
  ],
  "customProperties": {},
  "addressTypesToCollect": [],
  "allowedPaymentMethods": [],
  "collectionProcess": "MANUAL_PAYMENTS",
  "netPaymentTerms": 30,
  "sellerCompanyName": "Coffee Inc.",
  "totalBilledAmount": 1200.00,
  "totalBilledAmountPreTax": 1200.00,
  "totalPaidAmount": 0.00,
  "automatedTaxesEnabled": false,
  "hubspotBillingEnabled": true,
  "paymentEnabled": false,
  "storePaymentMethodAtCheckout": false
}
```

### Update a contract

To update a contract's properties, make a `PATCH` request to `/commerce/contracts/2027-03-beta/contracts/{contractId}`.

In the request body, include the properties to update. Properties not included will remain unchanged.

```json theme={null}
{
  "name": "Enterprise Platform License — Renewed",
  "poNumber": "PO-2026-0042",
  "netPaymentTerms": 30
}
```

<Note>Line item modifications are not supported via this endpoint. To add, update, or remove line items on an active contract, use the [contract changes](#contract-changes) process instead.</Note>

The following contract properties can be updated:

| Property                           | Type    | Description                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                             | String  | The contract name.                                                                                                                                                                                                                                                                                                                                                                                                |
| `billingContactId`                 | String  | ID of the contact to bill.                                                                                                                                                                                                                                                                                                                                                                                        |
| `billingCompanyId`                 | String  | ID of the billing company.                                                                                                                                                                                                                                                                                                                                                                                        |
| `dealId`                           | String  | ID of the associated deal.                                                                                                                                                                                                                                                                                                                                                                                        |
| `ownerId`                          | String  | ID of the contract owner.                                                                                                                                                                                                                                                                                                                                                                                         |
| `billingAddress`                   | Object  | Billing address. See [address format](#address-format) below.                                                                                                                                                                                                                                                                                                                                                     |
| `netPaymentTerms`                  | Integer | Number of days the buyer has to pay each invoice.                                                                                                                                                                                                                                                                                                                                                                 |
| `locale`                           | String  | IETF locale tag (e.g., `"en-US"`).                                                                                                                                                                                                                                                                                                                                                                                |
| `automatedTaxesEnabled`            | Boolean | Whether automated sales tax is enabled for the contract (must be [enabled in your account](https://knowledge.hubspot.com/payments/set-up-automated-tax-and-tax-rates)). Defaults to `false`. When `true`:<ul><li>`taxRateGroupId` cannot be set on line items</li><li>You must include the `billingAddress` fields `address`, `state`, `zip`, and `countryCode`. See [address format](#address-format).</li></ul> |
| `addressTypesToCollect`            | Array   | Address types to collect at checkout.                                                                                                                                                                                                                                                                                                                                                                             |
| `allowedPaymentMethods`            | Array   | Accepted payment methods.                                                                                                                                                                                                                                                                                                                                                                                         |
| `poNumber`                         | String  | Purchase order number.                                                                                                                                                                                                                                                                                                                                                                                            |
| `sellerCompanyName`                | String  | Seller's company name.                                                                                                                                                                                                                                                                                                                                                                                            |
| `sellerCompanyDomain`              | String  | Seller's company website domain (e.g., `"example.com"`).                                                                                                                                                                                                                                                                                                                                                          |
| `sellerCompanyAddress`             | Object  | Seller's company address. See [address format](#address-format).                                                                                                                                                                                                                                                                                                                                                  |
| `sellerEmail`                      | String  | Seller's email address.                                                                                                                                                                                                                                                                                                                                                                                           |
| `sellerFirstName`                  | String  | Seller's first name.                                                                                                                                                                                                                                                                                                                                                                                              |
| `sellerLastName`                   | String  | Seller's last name.                                                                                                                                                                                                                                                                                                                                                                                               |
| `sellerPhone`                      | String  | Seller's phone number.                                                                                                                                                                                                                                                                                                                                                                                            |
| `billingStartDateOverride`         | String  | Date when billing schedule entries begin for the contract's recurring line items, in `YYYY-MM-DD` format.                                                                                                                                                                                                                                                                                                         |
| `externalPaymentMethodReferenceId` | String  | Reference ID of a payment method managed outside of HubSpot (e.g., a Stripe payment method ID).                                                                                                                                                                                                                                                                                                                   |
| `customProperties`                 | Object  | Custom CRM property values as a string-to-string map.                                                                                                                                                                                                                                                                                                                                                             |

The response returns the full updated contract object.

### Terminate a contract

To terminate an active contract, make a `POST` request to `/commerce/contracts/2027-03-beta/contracts/{contractId}/terminate`.

In the request body, you can include a `terminationDate` to set a future termination date. This will schedule the termination and update the contract's total contract value (TCV) to reflect the shortened term. If omitted, the contract terminates as of the current date.

```json theme={null}
{
  "terminationDate": "2026-12-31"
}
```

The response returns the contract object with the `terminationDate` property set to reflect the date of termination.

## Contract changes

A contract change lets you propose updates to a contract's line items. Rather than editing line items directly, you describe what should change. You can use contract changes to add or remove services, adjust pricing mid-contract, or update quantities.

There are two workflows for contract changes based on the `type` field:

| Type     | Description                                                                                                                                                                                                                                           |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DIRECT` | Line item modifications are specified in the API request body. With `autoAccept: true`, the change is applied immediately. With `autoAccept: false` (default), the change sits at `DRAFT` until accepted via the [accept endpoint](#accept-a-change). |
| `QUOTE`  | A HubSpot quote is generated for the buyer to review and sign. The change is accepted when the buyer signs the quote, or canceled when the quote is voided. Accept and cancel actions happen through the quote lifecycle, not through this API.       |

Changes move through the following statuses:

| Status     | Description                                                                                                     |
| ---------- | --------------------------------------------------------------------------------------------------------------- |
| `DRAFT`    | Created but not yet submitted. Line item changes can be modified at this stage.                                 |
| `PROPOSED` | Submitted for review (for `QUOTE` changes).                                                                     |
| `ACCEPTED` | Approved and applied to the contract. `DIRECT` changes with `autoAccept: true` skip to this status immediately. |
| `CANCELED` | Voided before acceptance.                                                                                       |
| `FAILED`   | A processing error occurred during acceptance.                                                                  |
| `EXPIRED`  | Not accepted before the expiration date.                                                                        |

### Create a change

To create a contract change, make a `POST` request to `/commerce/contracts/2027-03-beta/changes`.

The `type` field is required and determines the change workflow. Use `"DIRECT"` to specify line item modifications in the request, or `"QUOTE"` to initiate a quote-backed approval flow.

<Tabs>
  <Tab title="DIRECT">
    ```json theme={null}
    {
      "contractId": "123456789",
      "type": "DIRECT",
      "prorating": true,
      "autoAccept": false,
      "effectiveDate": "2026-10-01",
      "name": "Q4 seat expansion",
      "lineItemChanges": [
        {
          "action": "UPDATE",
          "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6",
          "lineItemUpdate": {
            "quantity": "5"
          }
        }
      ]
    }
    ```

    | Property                                | Type    | Description                                                                          |
    | --------------------------------------- | ------- | ------------------------------------------------------------------------------------ |
    | `type` <RequiredIndicator />            | String  | Must be `"DIRECT"`.                                                                  |
    | `prorating` <RequiredIndicator />       | Boolean | Whether to prorate the change based on the effective date.                           |
    | `lineItemChanges` <RequiredIndicator /> | Array   | Line item modifications to apply. See [line item changes](#line-item-changes) below. |
    | `contractId`                            | String  | ID of the contract to apply this change to.                                          |
    | `autoAccept`                            | Boolean | When `true`, the change is applied immediately. Defaults to `false`.                 |
    | `effectiveDate`                         | String  | Date the change takes effect, in `YYYY-MM-DD` format.                                |
    | `name`                                  | String  | A name for this change.                                                              |

    The response returns the change:

    ```json theme={null}
    {
      "id": "234567890",
      "contractId": "123456789",
      "type": "DIRECT",
      "status": "DRAFT",
      "prorating": true,
      "effectiveDate": "2026-10-01",
      "name": "Q4 seat expansion",
      "createdAt": "2026-09-15T14:00:00.000Z",
      "updatedAt": "2026-09-15T14:00:00.000Z",
      "lineItemChanges": [
        {
          "action": "UPDATE",
          "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6",
          "lineItemUpdate": {
            "quantity": "5"
          }
        }
      ],
      "deltaLineItems": [
        {
          "id": "24584111229",
          "name": "Platform license",
          "quantity": 5,
          "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6"
        }
      ],
      "proposedLineItems": [
        {
          "id": "24584111229",
          "name": "Platform license",
          "quantity": 5,
          "price": "1200.00",
          "amount": "6000.00",
          "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6"
        }
      ]
    }
    ```
  </Tab>

  <Tab title="QUOTE">
    When creating a change quote, you must associate it with a deal. In the request body, you can either:

    * Associate it with an existing deal by including `dealId`.
    * Generate a new deal by including both `dealPipeline` and `dealStage`.

    Unlike `DIRECT` changes, change quotes don't support updating line items directly when creating the change. Instead, you'll use the [quotes API](/docs/api-reference/latest/crm/objects/quotes/guide) to handle any line item updates.

    ```json theme={null}
    {
      "contractId": "420538663347",
      "type": "QUOTE",
      "prorating": false,
      "quoteTemplateId": "987654321",
      "dealId": "29451866158",
      "name": "Q4 upgrade"
    }
    ```

    | Property                                | Type    | Description                                                                                                                                     |
    | --------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
    | `type` <RequiredIndicator />            | String  | Must be `"QUOTE"`.                                                                                                                              |
    | `prorating` <RequiredIndicator />       | Boolean | Whether to prorate the change based on the effective date.                                                                                      |
    | `quoteTemplateId` <RequiredIndicator /> | String  | ID of the change quote template to use.                                                                                                         |
    | `contractId`                            | String  | ID of the contract to apply this change to.                                                                                                     |
    | `dealId`                                | String  | ID of an existing deal to associate with the change quote. This field is required unless you are providing both `dealPipeline` and `dealStage`. |
    | `dealPipeline`                          | String  | The ID of the pipeline for the new associated deal. Required for generating a new deal for the quote (must also include `dealStage`).           |
    | `dealStage`                             | String  | The ID of the pipeline stage for the new associated deal. Required for generating a new deal for the quote (must also include `dealPipeline`).  |
    | `sellerEmail`                           | String  | Email address of the seller on the change quote.                                                                                                |
    | `effectiveDate`                         | String  | Date the change takes effect, in `YYYY-MM-DD` format.                                                                                           |
    | `name`                                  | String  | A name for this change.                                                                                                                         |

    The response returns the change, as shown below. You can separately retrieve the resulting quote via the [quotes API](/docs/api-reference/latest/crm/objects/quotes/guide) using the returned `quoteId` value.

    ```json theme={null}
    {
      "location": null,
      "createdResourceId": "16677927",
      "entity": {
        "id": "16677927",
        "contractId": "420538663347",
        "type": "QUOTE",
        "status": "DRAFT",
        "createdAt": "2026-07-24T20:08:49.124Z",
        "updatedAt": "2026-07-24T20:08:49.124Z",
        "name": "Q4 upgrade",
        "quoteId": "11688277651",
        "effectiveDate": "2026-07-25",
        "prorating": false,
        "lineItemChanges": []
      }
    }
    ```
  </Tab>
</Tabs>

#### Line item changes

For `DIRECT` changes, each entry in `lineItemChanges` represents a modification to a single line item:

| Property                       | Type   | Description                                                                                                                                                                                           |
| ------------------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `action` <RequiredIndicator /> | String | The type of modification. Allowed values: `"ADD"`, `"UPDATE"`, `"REMOVE"`.                                                                                                                            |
| `lineItemAdd`                  | Object | Line item to create. Required for `ADD` actions. See [line item fields](#line-items) for the full set of supported fields. In responses, `ADD` actions populate `lineItemAdd` (not `lineItemUpdate`). |
| `lineItemUpdate`               | Object | Fields to modify on the existing line item. Required for `UPDATE` actions. Uses patch semantics: absent fields are unchanged, empty string clears a field, a non-empty value sets the field.          |
| `rampKey`                      | String | The `rampKey` of the line item to update or remove. Required for `"UPDATE"` and `"REMOVE"`.                                                                                                           |

### Retrieve changes for a contract

To retrieve all changes for a contract, make a `GET` request to `/commerce/contracts/2027-03-beta/contracts/{contractId}/changes`.

The response returns a `changes` array containing all changes associated with the contract.

```json theme={null}
{
  "changes": [
    {
      "id": "234567890",
      "contractId": "123456789",
      "type": "DIRECT",
      "status": "ACCEPTED",
      "prorating": true,
      "effectiveDate": "2026-10-01",
      "name": "Q4 seat expansion",
      "createdAt": "2026-09-15T14:00:00.000Z",
      "updatedAt": "2026-10-01T00:00:00.000Z",
      "lineItemChanges": [
        {
          "action": "UPDATE",
          "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6",
          "lineItemUpdate": {
            "quantity": "5"
          }
        }
      ]
    }
  ]
}
```

### Retrieve a change

To retrieve an individual change by ID, make a `GET` request to `/commerce/contracts/2027-03-beta/changes/{changeId}`.

The response returns the full change object.

### Update a change

To update a change, make a `PATCH` request to `/commerce/contracts/2027-03-beta/changes/{changeId}`.

<Note>A change can only be updated while it has `DRAFT` status.</Note>

In the request body, include the fields you want to modify.

| Property          | Type    | Description                                                                              |
| ----------------- | ------- | ---------------------------------------------------------------------------------------- |
| `prorating`       | Boolean | Whether to prorate the change based on the effective date.                               |
| `effectiveDate`   | String  | Date the change takes effect, in `YYYY-MM-DD` format.                                    |
| `lineItemChanges` | Array   | Replaces the current line item change list. See [line item changes](#line-item-changes). |
| `name`            | String  | A name for the change. Set to `null` to clear.                                           |

```json theme={null}
{
  "prorating": true,
  "effectiveDate": "2026-11-01",
  "lineItemChanges": [
    {
      "action": "UPDATE",
      "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6",
      "lineItemUpdate": {
        "quantity": "10"
      }
    }
  ]
}
```

The response returns the updated change.

### Accept a change

To accept a `DIRECT` change, make a `POST` request to `/commerce/contracts/2027-03-beta/changes/{changeId}/accept`. No request body is required. Accepting a change applies the line item modifications to the contract and transitions the change to `ACCEPTED` status.

<Note>This endpoint only works for `DIRECT` changes. `QUOTE` changes are accepted when the buyer signs the associated quote.</Note>

The response returns the updated change.

### Cancel a change

To cancel a `DIRECT` change, make a `POST` request to `/commerce/contracts/2027-03-beta/changes/{changeId}/cancel`. No request body is required.

<Note>This endpoint only works for `DIRECT` changes. `QUOTE` changes are canceled by voiding the associated quote.</Note>

Canceling a change transitions it to `CANCELED` status without applying any modifications to the contract.

The response returns the updated change.

### Preview a change

To preview the effects of a `DIRECT` change without creating it, make a `POST` request to `/commerce/contracts/2027-03-beta/changes/preview`.

The request body uses the same schema as creating a `DIRECT` change. The endpoint does not persist the change or affect the contract.

The response returns only the projected line item state:

```json theme={null}
{
  "deltaLineItems": [
    {
      "id": "24584111229",
      "name": "Platform license",
      "quantity": 5,
      "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6"
    }
  ],
  "proposedLineItems": [
    {
      "id": "24584111229",
      "name": "Platform license",
      "quantity": 5,
      "price": "1200.00",
      "amount": "6000.00",
      "rampKey": "20b25cb9-a4da-4b62-81b8-2821cc45f2a6"
    }
  ]
}
```

| Property            | Type  | Description                                                                                      |
| ------------------- | ----- | ------------------------------------------------------------------------------------------------ |
| `deltaLineItems`    | Array | The modifications that would be applied to the contract's line items when the change is enacted. |
| `proposedLineItems` | Array | The resulting state of the contract's line items if the change were to be applied.               |

## Renewal quotes

A renewal quote lets you initiate the renewal process for a contract that is approaching its end date. When a renewal quote is accepted by the buyer, a new contract is created and automatically associated with the previous one.

### Create a renewal quote

To create a renewal quote, make a `POST` request to `/commerce/contracts/2027-03-beta/contracts/{contractId}/renewal-quotes`.

When creating a renewal quote, you must associate it with a deal. In the request body, you can either:

* Associate it with an existing deal by including `dealId`.
* Generate a new deal by including both `dealPipeline` and `dealStage`.

The renewal quote is pre-populated with the contract's active recurring line items as of the end date.

```json theme={null}
{
  "quoteTemplateId": "987654321",
  "dealId": "29451866158",
  "name": "2027 Annual Renewal"
}
```

| Property                                | Type   | Description                                                                                                                                                             |
| --------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quoteTemplateId` <RequiredIndicator /> | String | ID of the quote template to use for the renewal quote.                                                                                                                  |
| `dealId`                                | String | ID of an existing deal to associate with the renewal quote. This field is required unless you are providing both `dealPipeline` and `dealStage` to generate a new deal. |
| `dealPipeline`                          | String | The ID of the pipeline when generating a new associated deal. Required for generating a new deal for the quote (must also include `dealStage`).                         |
| `dealStage`                             | String | The ID of the pipeline stage when generating a new associated deal. Required for generating a new deal for the quote (must also include `dealPipeline`).                |
| `name`                                  | String | A name for the renewal quote.                                                                                                                                           |

The response returns the newly created quote, including its line items and metadata.

## Contract properties

### Contract status

The `status` field reflects the contract's current state, and is determined by the `contractEffectiveDate` date and end date:

| Status       | Description                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DRAFT`      | Created in the HubSpot UI but not yet finalized, or created via the API with a future `contractEffectiveDate` (scheduled to become active on that date).                                                                                                                                                                                                                                                                    |
| `ACTIVE`     | Contract is currently in effect.                                                                                                                                                                                                                                                                                                                                                                                            |
| `COMPLETED`  | The contract's billing period has ended. A contract's end date is automatically calculated from the latest `hs_recurring_billing_end_date` across its recurring line items, and cannot be set directly. Contracts with evergreen line items (`recurringBillingTerms: "AUTOMATICALLY_RENEW"`) have no calculated end date and will not naturally reach this status, but must instead be [terminated](#terminate-a-contract). |
| `TERMINATED` | Contract has been manually [terminated](#terminate-a-contract).                                                                                                                                                                                                                                                                                                                                                             |

### Address format

The `billingAddress` and `sellerCompanyAddress` properties use the same structure:

```json theme={null}
"billingAddress": {
  "address": "123 Fake Street",
  "address2": null,
  "city": "Somerville",
  "country": "United States",
  "countryCode": "US",
  "state": "MA",
  "zip": "02145"
}
```

| Property      | Type   | Description                                                                                                                                                                                                                   |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address`     | String | Street line 1 (e.g., `"123 Fake Street"`). Required when `automatedTaxesEnabled` is `true`.                                                                                                                                   |
| `address2`    | String | Street line 2 (e.g., `"Unit 12"`)                                                                                                                                                                                             |
| `city`        | String | City (e.g., `"Portland"`)                                                                                                                                                                                                     |
| `state`       | String | State or province (e.g., `"ME"`). Required when `automatedTaxesEnabled` is `true`.                                                                                                                                            |
| `zip`         | String | Postal code (e.g., `"04101"`). Required when `automatedTaxesEnabled` is `true`.                                                                                                                                               |
| `country`     | String | Country name (e.g., `"United States"`).                                                                                                                                                                                       |
| `countryCode` | String | Two-letter ISO 3166-1 alpha-2 country code (e.g., `"US"`). You can provide `country`, `countryCode`, or both. If both are provided, they must be consistent with each other. Required when `automatedTaxesEnabled` is `true`. |

### Line items

#### Modes

The `lineItems` array accepts a `mode` field that determines how each line item is created:

| Mode           | Required fields               | Description                                                                                                 |
| -------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `CUSTOM`       | `name`, `quantity`, `pricing` | Creates a line item from scratch.                                                                           |
| `FROM_PRODUCT` | `productId`                   | Copies a product from your HubSpot product library. Product defaults are used for any fields not specified. |
| `CLONE`        | `sourceLineItemId`            | Copies an existing line item. Cloned values are used for any fields not specified.                          |

<Tabs>
  <Tab title="CUSTOM">
    ```json theme={null}
    "lineItems": [
      {
        "mode": "CUSTOM",
        "name": "Platform license",
        "quantity": 1,
        "pricing": {
          "pricingModel": "FLAT",
          "prices": [
            {
              "currencyCode": "USD",
              "price": "1200.00"
            }
          ]
        },
        "recurringBillingFrequency": "ANNUALLY",
        "recurringBillingTerms": "AUTOMATICALLY_RENEW"
      }
    ]
    ```
  </Tab>

  <Tab title="FROM_PRODUCT">
    ```json theme={null}
    "lineItems": [
      {
        "mode": "FROM_PRODUCT",
        "productId": "15686964654",
        "quantity": 1
      }
    ]
    ```
  </Tab>

  <Tab title="CLONE">
    ```json theme={null}
    "lineItems": [
      {
        "mode": "CLONE",
        "sourceLineItemId": "24574616090",
        "quantity": 1
      }
    ]
    ```
  </Tab>
</Tabs>

#### Recurring billing

To configure recurring billing for line items, use the fields below, which map directly to the corresponding CRM line item property. [Learn more about recurring billing](/docs/api-reference/latest/crm/objects/line-items/guide#recurring-billing).

| Field                              | Type    | Description                                                                                                                                                                                                                                                                                                             |
| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recurringBillingTerms`            | String  | Whether the line item is evergreen or fixed-term. Allowed values: <ul><li>`AUTOMATICALLY_RENEW`: billing recurs indefinitely.</li><li>`FIXED`: billing ends after a set period. Use with `recurringBillingPeriod` or `recurringBillingNumberOfPayments`.</li></ul><br />Maps to `hs_recurring_billing_terms`.           |
| `recurringBillingFrequency`        | String  | How often billing occurs. Allowed values: <ul><li>`ANNUALLY`</li><li>`BIWEEKLY`</li><li>`MONTHLY`</li><li>`QUARTERLY`</li><li>`WEEKLY`</li><li>`PER_SIX_MONTHS`</li><li>`PER_TWO_YEARS`</li><li>`PER_THREE_YEARS`</li><li>`PER_FOUR_YEARS`</li><li>`PER_FIVE_YEARS`</li></ul><br />Maps to `recurringbillingfrequency`. |
| `recurringBillingPeriod`           | String  | Total duration of a fixed-term billing period as an ISO 8601 duration string (e.g., `"P8M"` for 8 months). Use with `recurringBillingTerms: "FIXED"`.<br /><br />Maps to `hs_recurring_billing_period`.                                                                                                                 |
| `recurringBillingNumberOfPayments` | Integer | Number of billing payments for a fixed-term line item. Use as an alternative to `recurringBillingPeriod`.<br /><br />Maps to `hs_recurring_billing_number_of_payments`.                                                                                                                                                 |

For example, the line item below would bill monthly for 8 months:

```json theme={null}
{
  "recurringBillingFrequency": "MONTHLY",
  "recurringBillingTerms": "FIXED",
  "recurringBillingPeriod": "P8M"
}
```

#### Taxes

To configure taxes for a line item, you can set the following fields:

| Field            | Type   | Description                                                                                                                                                                                                                                                                                                            |
| ---------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `taxCategory`    | String | Intended for use with [automated sales tax](https://knowledge.hubspot.com/payments/set-up-automated-tax-and-tax-rates). The ID of the tax category, which you can find in your account's [line item property settings](https://knowledge.hubspot.com/properties/create-and-edit-properties#edit-an-existing-property). |
| `taxRateGroupId` | String | Intended for manually setting sales tax when automated sales tax isn't enabled. The ID of the tax rate group that determines the tax rate applied to this line item, which you can retrieve via the [tax rates API](/docs/api-reference/latest/account/settings/tax-rates/get-tax-rates).                                   |

The following example shows how to manually specify a tax rate for a line item using `taxRateGroupId`:

```json highlight={10} theme={null}
"lineItems": [
      {
        "mode": "CUSTOM",
        "name": "Test line item",
        "quantity": 1,
        "pricing": {
          "pricingModel": "FLAT",
          "prices": [{ "currencyCode": "USD", "price": "100.00" }]
        },
        "taxRateGroupId": "2147636425"
      }
    ]
```

The `taxAmount` field is returned in line item responses and is automatically calculated based on the line item's tax configuration.

#### Pricing models

The `pricing` object supports four pricing models. All tiered models (`VOLUME`, `GRADUATED`, `STAIRSTEP`) share the same `prices` array structure: `maxQuantity` defines the upper bound of each tier, and the last tier is always unbounded.

<Tabs>
  <Tab title="Flat">
    In the `FLAT` pricing model, a single fixed price per unit is charged, regardless of quantity. `prices` contains a single entry per currency.

    ```json theme={null}
    {
      "mode": "CUSTOM",
      "name": "Support Package",
      "quantity": 1,
      "pricing": {
        "pricingModel": "FLAT",
        "prices": [{ "currencyCode": "USD", "price": "500.00" }]
      },
      "recurringBillingPeriod": "P12M",
      "recurringBillingFrequency": "MONTHLY"
    }
    ```
  </Tab>

  <Tab title="Volume">
    In the `VOLUME` pricing model, all units are billed at the **per-unit rate** of whichever tier the total quantity falls into. The `price` field is a per-unit rate, multiplied by the total quantity.

    **Example:** 15 seats → tier 2 rate applies to all 15 → 15 × $8.00 = $120.00

    ```json theme={null}
    {
      "mode": "CUSTOM",
      "name": "User Seats",
      "quantity": 15,
      "pricing": {
        "pricingModel": "VOLUME",
        "prices": [
          { "currencyCode": "USD", "price": "10.00", "maxQuantity": 10 },
          { "currencyCode": "USD", "price": "8.00",  "maxQuantity": 20 },
          { "currencyCode": "USD", "price": "6.00" }
        ]
      },
      "recurringBillingPeriod": "P12M",
      "recurringBillingFrequency": "MONTHLY"
    }
    ```
  </Tab>

  <Tab title="Graduated">
    In the `GRADUATED` pricing model, each unit is billed at the rate of the tier it falls within, applied incrementally across tiers. The `price` field is a per-unit rate for that tier's range.

    **Example:** 25 seats → (10 × $10.00) + (10 × $8.00) + (5 × $6.00) = $210.00

    ```json theme={null}
    {
      "mode": "CUSTOM",
      "name": "API Calls",
      "quantity": 25,
      "pricing": {
        "pricingModel": "GRADUATED",
        "prices": [
          { "currencyCode": "USD", "price": "10.00", "maxQuantity": 10 },
          { "currencyCode": "USD", "price": "8.00",  "maxQuantity": 20 },
          { "currencyCode": "USD", "price": "6.00" }
        ]
      },
      "recurringBillingPeriod": "P12M",
      "recurringBillingFrequency": "MONTHLY"
    }
    ```
  </Tab>

  <Tab title="Stairstep">
    In the `STAIRSTEP` pricing model, a flat fee is charged based on whichever tier the total quantity falls into, with no per-unit math. The `price` field is the total flat fee for that tier, not a per-unit rate.

    **Example:** 15 seats → tier 2 applies → flat fee of \$120.00 (quantity is ignored in the calculation)

    ```json theme={null}
    {
      "mode": "CUSTOM",
      "name": "Storage Tier",
      "quantity": 15,
      "pricing": {
        "pricingModel": "STAIRSTEP",
        "prices": [
          { "currencyCode": "USD", "price": "80.00",  "maxQuantity": 10 },
          { "currencyCode": "USD", "price": "120.00", "maxQuantity": 20 },
          { "currencyCode": "USD", "price": "150.00" }
        ]
      },
      "recurringBillingPeriod": "P12M",
      "recurringBillingFrequency": "MONTHLY"
    }
    ```
  </Tab>
</Tabs>

**Key rules for tiered pricing**

* Tiers must be ordered low to high by `maxQuantity`.
* `maxQuantity` must be a positive integer (e.g., `10`).
* The last tier must always be unbounded (omit `maxQuantity`).
* The `price` field means different things depending on the model:
  * `VOLUME`, `GRADUATED`: per-unit rate, multiplied by quantity.
  * `STAIRSTEP`: total flat fee for the tier (quantity is not factored in).
* For multi-currency line items, include one full set of tiers per currency code within the same `prices` array.
