> ## 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.

# Properties schemas (BETA)

> Read and manage the metadata for CRM properties using the schemas API.

> [accordion] Scope requirements

Use the properties schemas API to create, read, and manage property metadata for CRM objects. With this API, property details available in other CRM APIs, such as options, validation rules, and access settings, are available in one place.

> [!TIP]
>
> This API is used for creating and managing properties and their metadata (i.e., labels, options). To update property values for records (e.g., set a contact's job title), use the [object APIs](https://developers.hubspot.com/docs/api-reference/latest/crm/using-object-apis.md).

> [!WARNING]
>
> This functionality is currently in beta. By participating in this beta, you agree to HubSpot's [Developer Terms](https://legal.hubspot.com/developer-terms) and [Developer Beta Terms](https://legal.hubspot.com/developerbetaterms). Note that the functionality is still under active development and is subject to change based on testing and feedback.

## Create properties

To create a custom property, make a `POST` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties`.

For example, your request body may look similar to:

```json theme={null}
{
  "name": "favorite_food",
  "label": "Favorite food",
  "type": "ENUMERATION",
  "fieldType": "SELECT",
  "groupName": "contactinformation",
  "description": "The contact's favorite food.",
  "options": [
    {
      "label": "Pizza",
      "value": "pizza",
      "displayOrder": 1
    },
    {
      "label": "Tacos",
      "value": "tacos",
      "displayOrder": 2
    }
  ]
}
```

You can set the following fields in the request body:

| Field | Type | Description |
| - | - | - |
| `name` required | String | The internal name of the property. |
| `label` required | String | The name of the property as it appears in HubSpot. |
| `type` required | String | The underlying value type of the property. |
| `fieldType` required | String | How the property is displayed in HubSpot and on forms. |
| `groupName` required | String | The name of the property group the property belongs to. |
| `options` | Array | The selectable [options](#options) for enumeration properties. Defaults to an empty array. |
| `optionDecorators` | Object | The visual presentation settings for enumeration options, including their decoration style and assigned colors. |
| `accessAllowlist` | Array | Entries that restrict which users or teams can view or edit the property. Defaults to an empty array. |
| `validationRules` | Array | Rules enforced on the property's value. Defaults to an empty array. |
| `dataSensitivity` | String | The [data sensitivity](https://knowledge.hubspot.com/account-security/store-sensitive-data) classification: `NONE`, `STANDARD`, or `HIGH`. |
| `defaultValue` | String | The value applied when a record is created without a value for the property. |
| `description` | String | A description of what the property represents. |
| `formField` | Boolean | Whether the property is available in forms. |
| `hasUniqueValue` | Boolean | Whether values must be unique across all records of the object type. |
| `dataEntryInstructions` | String | Guidance text shown to users when they enter a value. |
| `calculationFormula` | String | For calculation properties, the formula used to compute the value. Requires a `fieldType` of `CALCULATION_EQUATION`. Learn how to [create calculation properties](#create-calculation-properties). |
| `rollupConfig` | Object | For rollup properties, how the value is aggregated from associated records. Requires a `fieldType` of `CALCULATION_ROLLUP`. Learn how to [create rollup properties](#create-rollup-properties). |
| `syncConfig` | Object | For sync properties, how the value is synced from an associated record. Learn how to [create sync properties](#create-sync-properties). |

The response includes the newly created property, with the default fields and any other fields you set in the request. A `400` error is returned for invalid input, such as a duplicate `name`, invalid option values, or an incompatible `type` and `fieldType` pairing.

### Create a batch of properties

To create up to 100 properties in one request, make a `POST` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/batch/create`. In the request body, include an `inputs` array.

For example, to create two properties, your request would look similar to:

```json theme={null}
{
  "inputs": [
    {
      "name": "favorite_food",
      "label": "Favorite food",
      "type": "STRING",
      "fieldType": "TEXT",
      "groupName": "contactinformation"
    },
    {
      "name": "favorite_color",
      "label": "Favorite color",
      "type": "STRING",
      "fieldType": "TEXT",
      "groupName": "contactinformation"
    }
  ]
}
```

The response includes one result for each input, in the same order as your request. Each result includes the default fields and any other fields you set for that input. A failure on one input does not prevent the others from being created. If some inputs fail, the response returns a `207` status code with the details for each failed item. An empty `inputs` array returns a `400` error.

### Create calculation properties

Calculation properties compute their value from other properties on the same record. To create a calculation property, set the `fieldType` to `CALCULATION_EQUATION` and include your formula in the `calculationFormula`field.

For example, to create a deal property that calculates a probability-weighted amount, your request body would look similar to:

```json theme={null}
{
  "name": "weighted_amount",
  "label": "Sales Weighted amount",
  "type": "NUMBER",
  "fieldType": "CALCULATION_EQUATION",
  "groupName": "dealinformation",
  "calculationFormula": "amount * hs_deal_stage_probability"
}
```

Reference properties in your formula by their internal names. Learn more about the available operators and functions in the [calculation formula reference](#calculation-formula-reference). A `400` error is returned if the formula can't be parsed or references a property that doesn't exist.

### Create rollup properties

Rollup properties aggregate values from the records associated with the current record. To create a rollup property, set the `fieldType` to `CALCULATION_ROLLUP` and include a `rollupConfig` object.

For example, to create a contact property that sums the amount of all associated closed won deals, your request body would look similar to:

```json theme={null}
{
  "name": "total_closed_won_amount",
  "label": "Total closed won amount",
  "type": "NUMBER",
  "fieldType": "CALCULATION_ROLLUP",
  "groupName": "contactinformation",
  "rollupConfig": {
    "associatedRecordType": "0-3",
    "associatedRecordProperty": "amount",
    "associationSpec": {
      "category": "HUBSPOT_DEFINED",
      "typeId": "3"
    },
    "rollupType": "SUM",
    "conditionalFormula": "dealstage == \"closedwon\""
  }
}
```

In `rollupConfig`, `associatedRecordType`, `associatedRecordProperty`, `associationSpec`, and `rollupType` are required. `conditionalFormula` is optional and filters which associated records are included, using the same [formula syntax](#calculation-formula-reference) as calculation properties. When omitted, all associated records are included. Learn more about the [`rollupConfig` fields](#rollup-configuration).

The `MIN`, `MAX`, `AVG`, and `SUM` rollup types only work with number properties. A `400` error is returned if `rollupConfig` is included without a `fieldType` of `CALCULATION_ROLLUP`, or if the `associationSpec` doesn't exist between the two object types.

### Create sync properties

Sync properties copy a value from an associated record onto the current record. To create a sync property, include a `syncConfig` object and set `type` and `fieldType` to values to match the value being synced.

For example, to create a contact property that syncs the amount of the contact's most recently created deal, your request body would look similar to:

```json theme={null}
{
  "name": "latest_deal_amount",
  "label": "Latest deal amount",
  "type": "NUMBER",
  "fieldType": "NUMBER",
  "groupName": "contactinformation",
  "syncConfig": {
    "associatedRecordType": "0-3",
    "associatedRecordProperty": "amount",
    "associationSpec": {
      "category": "HUBSPOT_DEFINED",
      "typeId": "3"
    },
    "syncPreference": "MOST_RECENTLY_CREATED"
  }
}
```

In `syncConfig`, all fields are required. `syncPreference` determines which associated record the value is synced from: `FIRST_CREATED`, `MOST_RECENTLY_CREATED`, or `SYNC_VALUE` (the only record of a one-to-one association). Learn more about the [`syncConfig` fields](#sync-configuration).

## Retrieve properties

### Retrieve a single property

To retrieve a property, make a `GET` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/{propertyName}`.

For example, a `GET` request to `/crm/schemas/2027-03-beta/objects/0-1/properties/favorite_food?fields=label&fields=options` would return a response similar to the following:

```json theme={null}
{
  "category": "USER_DEFINED",
  "name": "favorite_food",
  "type": "ENUMERATION",
  "fieldType": "SELECT",
  "label": "Favorite food",
  "options": [
    {
      "label": "Pizza",
      "value": "pizza",
      "displayOrder": 1
    },
    {
      "label": "Tacos",
      "value": "tacos",
      "displayOrder": 2
    }
  ],
  "createdAt": "2027-03-01T12:00:00.000Z",
  "updatedAt": "2027-03-01T12:00:00.000Z",
  "archived": false
}
```

The response includes the requested property with the following default fields: `category`, `name`, `type`, `fieldType`, `createdAt`, `updatedAt`, and `archived`. To return additional fields, include the `fields` query parameters in your request. Learn more about the [supported fields](#property-fields-reference). A `404` error is returned if the property doesn't exist for the object.

### Retrieve all properties for an object

To retrieve a paginated list of properties for an object, make a `GET` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties`.

The following query parameters are available:

| Parameter | Description |
| - | - |
| `archived` | Whether to include archived properties or active ones. Defaults to `false`, which returns only active properties. Set the value to `true` to return only archived properties. |
| `after` | A pagination cursor returned in a previous response. Pass this value to retrieve the next page of results. |
| `limit` | The maximum number of properties to return per page. Defaults to 25, with a maximum of 100. |
| `fields` | The additional fields to return for each property. Learn more about the [supported fields](#property-fields-reference). |

The response includes a page of properties, along with a cursor for the next page when more results exist.

### Retrieve a batch of properties

To retrieve multiple properties by name, make a `POST` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/batch/read`.

For example, your request body may look similar to:

```json theme={null}
{
  "inputs": [
    {"name": "favorite_food"},
    {"name": "favorite_color"},
    {"name": "favorite_movie"}
  ]
}
```

The response includes one result for each requested property with the following default fields: `category`, `name`, `type`, `fieldType`, `createdAt`, `updatedAt`, and `archived`. To return additional fields, include the `fields` query parameters in your request. Learn more about the [supported fields](#property-fields-reference).

Any name that doesn't match a property returns a not-found error for that item, and the request returns a `207` status code. An empty `inputs` array returns a `400` error.

### Retrieve options for an option source

Some enumeration properties derive their options dynamically instead of storing static options on the property. For these properties, the `optionsSource` field is set. The supported values are `OWNER` (for properties that reference owners), `PERSONA`, and `CALL_DISPOSITION`.

To retrieve the options for an option source, make a `GET` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/option-sources/{optionSource}`. For example, a request to `/crm/schemas/2027-03-beta/objects/0-1/properties/option-sources/OWNER` returns all the options for an owner-referencing contact property.

The following query parameters are available:

| Parameter | Description |
| - | - |
| `after` | A pagination cursor returned in a previous response. Pass this value to retrieve the next page of results. |
| `limit` | The maximum number of options to return per page. Defaults to 25, maximum 100. Must be a positive number. |

The response includes a page of options, along with a cursor for the next page when more results exist. A `400` error is returned for an invalid `limit` or `after` value, and a `404` error is returned if the option source doesn't exist.

## Update properties

To update a property, make a `PATCH` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/{propertyName}`. In the request body, include only the fields that you want to update. Omitted fields are left unchanged.

For example, the following request body updates a property's label and description:

```json theme={null}
{
  "label": "Favorite meal",
  "description": "The contact's favorite meal."
}
```

To change a rollup or sync property's configuration, include an updated `rollupConfig` or `syncConfig` object. The object replaces the existing configuration rather than appending it, so you should include every field you want to keep.

When you update a field that holds an array (e.g., `options` or `validationRules`), the array you send replaces the existing value rather than appending to it. For example, the following request body replaces any existing validation rules on the property with a single `MAX_LENGTH` rule:

```json theme={null}
{
  "validationRules": [
    {
      "ruleType": "MAX_LENGTH",
      "ruleArguments": ["100"]
    }
  ]
}
```

The response includes the property after the update, with the default fields and any other fields you changed in the request. A `404` error is returned if the property doesn't exist, and a `400` error is returned for an invalid update, such as an incompatible `type` and `fieldType` change or a change to a field that cannot be modified for that property.

### Update a batch of properties

To update up to 100 properties in one request, make a `POST` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/batch/update`. In the request body, include an `inputs` array, where each item names the property it applies to along with the fields to change.

For example, to change one property's label and another property's description, your request body would look similar to:

```json theme={null}
{
  "inputs": [
    {
      "name": "favorite_food",
      "label": "Favorite meal"
    },
    {
      "name": "favorite_color",
      "description": "The contact's favorite color."
    }
  ]
}
```

The response includes one result for each input, in the same order as your request. Each result includes the default fields and any other fields you changed for that input. If some inputs fail, the response returns a `207` status code.

## Archive and restore properties

You can archive a property, with the option to restore it later. The `archived` field on a property reflects its current state, and you can change it with a [`PATCH` request](#update-properties).

* To archive up to 100 properties in one request, make a `POST` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/batch/archive`.
* To restore up to 100 archived properties, make a `POST` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/batch/restore`.

In both cases, include an `inputs` array of objects, each containing the internal property name in its `name` field.

For example, your request body would look similar to:

```json theme={null}
{
  "inputs": [
    {"name": "favorite_food"},
    {"name": "favorite_color"}
  ]
}
```

A successful batch archive request returns `204` with no response body. A successful batch restore request returns `200` with the restored properties in the results array.

If any inputs fail, the response returns `207` with per-item errors. For restore requests, successfully restored properties are included in results. Archive responses do not include successful items in results.

An item fails with a `404` error if the property does not exist, or a `400` error if it's already in the target state (i.e., already restored or archived).

## Delete properties

Once you've archived a property, you can permanently delete it.

> [!WARNING]
>
> **Please note:** deleting a property is permanent and cannot be undone.

To delete a single property, make a `DELETE` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/{propertyName}`. A successful request returns no content. A `404` error is returned if the property doesn't exist, and a `400` error is returned if the property hasn't been archived.

### Delete a batch of properties

To delete up to 100 properties in one request, make a `POST` request to `/crm/schemas/2027-03-beta/objects/{objectTypeId}/properties/batch/purge`. In the request body, include an `inputs` array of objects, each containing the internal property name in its `name` field.

For example, your request body may look similar to:

```json theme={null}
{
  "inputs": [
    {"name": "favorite_food"},
    {"name": "favorite_color"}
  ]
}
```

A successful request returns a `204` with no body. If some inputs fail, the response returns a `207` status code with per-item errors.

## Property fields reference

The following tables describe the fields included in property responses.

| Field | Type | Description |
| - | - | - |
| `category` | String | Who defined the property: `HUBSPOT_DEFINED`, `INTEGRATION_DEFINED`, or `USER_DEFINED`. |
| `name` | String | The internal name of the property. |
| `label` | String | The display name shown in HubSpot. |
| `type` | String | The underlying value type of the property. |
| `fieldType` | String | How the property is displayed in HubSpot and on forms. |
| `description` | String | A description of what the property represents. |
| `options` | Array | For enumeration properties, the selectable options. |
| `optionDecorators` | Object | The visual presentation settings for enumeration options, including their decoration style and assigned colors. |
| `optionsSource` | String | Set when an enumeration property has dynamically derived options. `OWNER`, `PERSONA`, and `CALL_DISPOSITION` are supported values. |
| `calculated` | Boolean | Whether the property's value is computed automatically instead of entered directly. |
| `calculationFormula` | String | The [formula](#calculation-formula-reference) used to compute the value for calculation properties. Not returned if the property's formula can't be represented in this syntax. |
| `rollupConfig` | Object | For rollup properties, how the value is computed. |
| `syncConfig` | Object | For synced properties, how the value is synced from associated records. |
| `groupName` | String | The name of the property group the property belongs to. |
| `hidden` | Boolean | Whether the property is hidden from users in forms and the HubSpot UI. The property remains usable via API. |
| `readOnlyValue` | Boolean | Whether users can set the property's value, or whether it's system-managed. |
| `readOnlyDefinition` | Boolean | Whether the property's definition can be edited, or is locked. |
| `readOnlyOptions` | Boolean | For enumeration properties, whether the set of options can be modified. |
| `hasUniqueValue` | Boolean | Whether values must be unique across all records of the object type. |
| `archivable` | Boolean | Whether the property can be archived. |
| `archived` | Boolean | Whether the property is currently archived. |
| `currencyPropertyName` | String | For number properties that represent a monetary amount, the name of the property that holds the currency code. |
| `dataEntryInstructions` | String | Guidance text shown to users when they enter a value. |
| `accessAllowlist` | Array | Entries that restrict which users or teams can view or edit the property. |
| `dataSensitivity` | String | The data sensitivity classification: `NONE`, `STANDARD`, or `HIGH`. |
| `sensitiveDataCategories` | Array | The categories of sensitive data the property may contain, either `HIPAA` or an empty array (\[]). |
| `defaultValue` | String | The value applied when a record is created without a value for the property. |
| `formField` | Boolean | Whether the property is available in forms. |
| `validationRules` | Array | Rules enforced on the property's value. |
| `dateDisplayFormat` | String | For date properties, how the value is displayed: `ABSOLUTE`, `ABSOLUTE_WITH_RELATIVE`, `TIME_SINCE`, or `TIME_UNTIL`. |
| `numberDisplayFormat` | String | For number properties, how the value is displayed: `UNFORMATTED`, `FORMATTED`, `CURRENCY`, `PERCENTAGE`, `DURATION`, or `PROBABILITY`. |
| `createdAt` | String | The timestamp of when the property was created. |
| `updatedAt` | String | The timestamp of when the property was last updated. |
| `createdByUserId` | String | The ID of the user who created the property. |
| `updatedByUserId` | String | The ID of the user who last updated the property. |

### Property type and fieldType values

When creating properties, both `type` and `fieldType` are required. The `type` value determines the underlying value type of the property, and the `fieldType` value determines how the property appears in HubSpot and on forms. A property's `type` and `fieldType` combination must be compatible.

> [!NOTE]
>
> **Please note:** unlike the [properties API](https://developers.hubspot.com/docs/api-reference/latest/crm/properties/guide.md), the properties schemas API uses uppercase values (e.g., `STRING` instead of `string`, and `TEXT` instead of `text`). `URL` and `EMAIL` are also separate `fieldType` values, rather than `text` with a `textDisplayHint`.

The following table lists the available `type` values and the `fieldType` values supported for each.

| `type` | Supported `fieldType` values |
| - | - |
| `BOOL` | `BOOLEANCHECKBOX`, `CALCULATION_EQUATION` |
| `CURRENCY_NUMBER` | `NUMBER` |
| `DATE` | `DATE` |
| `DATETIME` | `DATE` |
| `ENUMERATION` | `BOOLEANCHECKBOX`, `CHECKBOX`, `RADIO`, `SELECT`, `CALCULATION_EQUATION` |
| `JSON` | `TEXT` |
| `NUMBER` | `NUMBER`, `CALCULATION_EQUATION`, `CALCULATION_READ_TIME`, `CALCULATION_ROLLUP`, `CALCULATION_SCORE` |
| `OBJECT_COORDINATES` | `TEXT` |
| `PHONE_NUMBER` | `PHONE_NUMBER` |
| `STRING` | `TEXT`, `TEXTAREA`, `EMAIL`, `URL`, `HTML`, `FILE`, `CALCULATION_EQUATION` |
| `TIME_RANGE` | `TEXT` |

### Options

Each item in the `options` array includes the following fields:

| Field | Type | Description |
| - | - | - |
| `label` | String | The display label for the option. |
| `value` | String | The internal value stored when the option is selected. |
| `displayOrder` | Number | The position of the option when sorted by display order. |
| `hidden` | Boolean | Whether the option is hidden from end users in forms and meetings. The option still appears in the CRM and HubSpot UI. |
| `description` | String | A description of what the option represents. |

### Option decorators and colors

The `optionDecorators` object sets up the visual presentation settings for enumeration options, including their decoration style and assigned colors.

| Field | Type | Description |
| - | - | - |
| `optionDecoratorStyle` | String | The visual style used to decorate enumeration options. Options are `LABEL_ONLY` (default), `LABEL_WITH_BADGE` (label is wrapped in a colored badge), or `LABEL_WITH_COLOR` (label is next to a colored dot). |
| `optionColors` | Array | The colors assigned to individual enumeration options. Each item contains `optionName` and `color`. |

Each item in the `optionColors` array includes the following fields:

| Field | Type | Description |
| - | - | - |
| `optionName` | String | The option value that the color applies to. |
| `color` | String | The color used to decorate the option in the UI. Available values are `BLACK`, `BLUE`, `BLUE_LIGHT`, `GRAY`, `GREEN`, `GREEN_LIGHT`, `ORANGE`, `ORANGE_LIGHT`, `PINK`, `PINK_LIGHT`, `PURPLE`, `PURPLE_LIGHT`, `RED`, `RED_LIGHT`, `TEAL`, `TEAL_LIGHT`, `YELLOW`, and `YELLOW_LIGHT`. |

### Rollup configuration

The `rollupConfig` object is present for rollup properties and includes the following fields:

| Field | Type | Description |
| - | - | - |
| `associatedRecordType` | String | The object type ID of the associated records being aggregated. |
| `associatedRecordProperty` | String | The property on the associated records whose values are aggregated. |
| `associationSpec` | Object | The association between the property's records and the associated records. Includes `category` (`HUBSPOT_DEFINED`, `USER_DEFINED`, or `INTEGRATOR_DEFINED`) and `typeId`. |
| `rollupType` | String | The aggregation applied: `MIN`, `MAX`, `AVG`, `COUNT`, `SUM`, `EARLIEST_DATE`, or `LATEST_DATE`. |
| `conditionalFormula` | String | An optional formula that filters which associated records are included in the aggregation. |

### Sync configuration

The `syncConfig` object is present for sync properties and includes the following fields:

| Field | Type | Description |
| - | - | - |
| `associatedRecordType` | String | The object type ID of the associated records the value is synced from. |
| `associatedRecordProperty` | String | The property on the associated records that the value is synced from. |
| `associationSpec` | Object | The association between the property's records and the associated records. Includes `category` (`HUBSPOT_DEFINED`, `USER_DEFINED`, or `INTEGRATOR_DEFINED`) and `typeId`. When creating a sync property, the `typeId` value must match the direction of source object to target object. The target object is the object for which you're creating the property (e.g., creating a contact property (target) from a deal property (source), the `typeId` is `3` (deal to contact)). Refer to this [list of default association type ID values](https://developers.hubspot.com/docs/api-reference/latest/crm/associations/associate-records/guide.md#association-type-id-values). |
| `syncPreference` | String | Which record to sync from: `FIRST_CREATED`, `MOST_RECENTLY_CREATED`, or `SYNC_VALUE` (the only record of a one-to-one association). |

### Calculation formula reference

The `calculationFormula` field, and the `conditionalFormula` field in `rollupConfig`, use the same formula syntax.

> [!NOTE]
>
> **Please note:** this syntax differs from the formulas in the [properties API](https://developers.hubspot.com/docs/api-reference/latest/crm/properties/guide.md#create-calculation-properties). For example, conditionals are written as `if(condition, value_if_true, value_if_false)` instead of `if ... then ... endif`, and `is_known` replaces `is_present`.

#### Values and properties

| Element | Syntax | Example |
| - | - | - |
| String | Text wrapped in single or double quotes. | `"closedwon"`, `'closedwon'` |
| Number | A whole or decimal number. | `1000`, `1.5` |
| Boolean | `true` or `false`. | `true` |
| Empty value | `null`. | `null` |
| Property | The property's internal name. You don't need to specify the property's type. | `amount` |

#### Operators

| Operator | Type | Description | Example |
| - | - | - | - |
| `+` | Arithmetic | Adds two values. | `amount + bonus` |
| `-` | Arithmetic | Subtracts one value from another. | `amount - discount` |
| `*` | Arithmetic | Multiplies two values. | `amount * hs_deal_stage_probability` |
| `/` | Arithmetic | Divides one value by another. | `amount * (1 - discount_rate)` |
| `<` | Comparison | Less than. | `amount < 1000` |
| `>` | Comparison | Greater than. | `amount > 1000` |
| `<=` | Comparison | Less than or equal to. | `amount <= 1000` |
| `>=` | Comparison | Greater than or equal to. | `amount >= 1000` |
| `=`, `==` | Equality | Equal to. | `dealstage == "closedwon"` |
| `!=` | Equality | Not equal to. | `dealstage != "closedlost"` |
| `and`, `AND`, `&&` | Logical | True if both conditions are true. Mixed case (e.g., `And`) is not accepted. | `amount > 1000 AND dealstage == "closedwon"` |
| `or`, `OR`, `\|\|` | Logical | True if either condition is true. Mixed case is not accepted. | `dealstage == "closedwon" OR dealstage == "closedlost"` |
| `not`, `!` | Logical | Negates a condition. `!` is the unary form. | `not is_known(close_date)` |

Use parentheses to control the order of arithmetic operations: `amount * (1 - discount_rate)`.

#### Functions

Function names are case-sensitive.

| Function | Returns | Description | Example |
| - | - | - | - |
| `abs(number)` | Number | Returns the absolute value of `number`. | `abs(-100)` |
| `add_time(base, amount, unit)` | Number | Adds `amount` of time to `base`. `unit` must be `"second"`, `"minute"`, `"hour"`, `"day"`, `"week"`, `"month"`, or `"year"`. | `add_time(createdate, 30, "day")` |
| `coalesce(value1, value2, ...)` | Matches the arguments | Returns the first argument that has a value. Accepts 2 to 100 arguments. | `coalesce(firstname, lastname)` |
| `concatenate(string1, string2, ...)` | String | Joins two or more strings together. Accepts up to 100 strings. | `concatenate(firstname, " ", lastname)` |
| `contains(text, substring)` | Boolean | Returns `true` if `text` contains `substring`. Case-sensitive. | `contains(dealname, "enterprise")` |
| `currency_decimal_places(currency)` | Number | Returns the number of decimal places used by `currency`. | `currency_decimal_places("USD")` |
| `dated_exchange_rate(currency, date)` | Number | Returns the exchange rate for `currency` on the given `date`. | `dated_exchange_rate("EUR", closedate)` |
| `euler()` | Number | Returns Euler's number (e ≈ 2.71828). | `euler()` |
| `exchange_rate(currency)` | Number | Returns the current exchange rate for `currency`. | `exchange_rate("EUR")` |
| `if(condition, value_if_true[, value_if_false])` | Matches the arguments | Returns `value_if_true` if `condition` is true. Returns `value_if_false` if false; if omitted, returns `null`. | `if(amount > 1000, "large", "small")` |
| `ifs(condition1, value1, ...)` | Matches the arguments | Evaluates each condition in order and returns the value for the first true condition. Accepts up to 100 condition/value pairs. | `ifs(amount > 5000, "high", amount > 1000, "medium", amount > 0, "low")` |
| `is_known(property)` | Boolean | Returns `true` if `property` has a value. | `is_known(closedate)` |
| `last_updated(property)` | String | Returns the timestamp in milliseconds of when `property` was last updated. | `last_updated(amount)` |
| `lowercase(text)` | String | Converts `text` to lowercase. | `lowercase(dealname)` |
| `max(number1, number2)` | Number | Returns the larger of two numbers. | `max(amount, 500)` |
| `min(number1, number2)` | Number | Returns the smaller of two numbers. | `min(amount, 500)` |
| `month(date)` | Number | Returns the month of `date` as a number (1–12). | `month(closedate)` |
| `number_to_string(number)` | String | Converts `number` to a string. | `number_to_string(amount)` |
| `pipeline_probability(pipeline)` | Number | Returns the win probability of a pipeline stage. | `pipeline_probability(hs_pipeline_stage)` |
| `power(base, exponent)` | Number | Raises `base` to the power of `exponent`. | `power(2, 10)` |
| `round_down(number, decimal_places)` | Number | Rounds `number` down to `decimal_places` decimal places. | `round_down(4.353, 1)` |
| `round_nearest(number, decimal_places)` | Number | Rounds `number` to the nearest value at `decimal_places` decimal places. | `round_nearest(4.32, 1)` |
| `round_up(number, decimal_places)` | Number | Rounds `number` up to `decimal_places` decimal places. | `round_up(4.353, 1)` |
| `sqrt(number)` | Number | Returns the square root of `number`. | `sqrt(144)` |
| `starts_with(text, substring)` | Boolean | Returns `true` if `text` begins with `substring`. Case-sensitive. | `starts_with(dealname, "Enterprise")` |
| `string_length(text)` | Number | Returns the number of characters in `text`. | `string_length(dealname)` |
| `string_to_number(string)` | Number | Converts `string` to a number. | `string_to_number(revenue_string)` |
| `subtract_time(base, amount, unit)` | Number | Subtracts `amount` of time from `base`. `unit` must be `"second"`, `"minute"`, `"hour"`, `"day"`, `"week"`, `"month"`, or `"year"`. | `subtract_time(closedate, 30, "day")` |
| `time_between(date1, date2)` | Number | Returns the length of time between `date1` and `date2`. | `time_between(createdate, closedate)` |
| `time_between_exclude_weekends(date1, date2)` | Number | Returns the length of time between `date1` and `date2`, excluding weekends. | `time_between_exclude_weekends(createdate, closedate)` |
| `uppercase(text)` | String | Converts `text` to uppercase. | `uppercase(dealname)` |
| `year(date)` | Number | Returns the year of `date` as a number. | `year(closedate)` |

#### Example formulas

To return a value based on a condition:

```json theme={null}
"calculationFormula": "if(amount > 1000, \"big\", \"small\")"
```

To use a fallback when a property is empty:

```json theme={null}
"calculationFormula": "coalesce(discount_amount, 0)"
```

To combine a conditional with other functions:

```json theme={null}
"calculationFormula": "if(is_known(close_date), round_up(amount * hs_deal_stage_probability), 0)"
```

#### Formula behavior

* A `400` error is returned if a formula can't be parsed, references a property that doesn't exist, or passes invalid arguments to a function.
* You can't clear `calculationFormula` with a `PATCH` request. Calculation properties require a formula, so send a new formula to change it.
* Some calculation properties, such as those created in HubSpot with functions that aren't listed above, don't return a `calculationFormula`. The `calculated` field is still `true`.

### Access allowlist

Each item in the `accessAllowlist` array includes the following fields:

| Field | Type | Description |
| - | - | - |
| `accessType` | String | The type of access: `VIEW` or `EDIT`. |
| `entityType` | String | The type of entity the entry applies to: `ALL`, `TEAM`, `USER`, or `ADMIN`. |
| `entityId` | String | The ID of the team or user the entry applies to. Not applicable when `entityType` is `ALL` or `ADMIN`. |

### Validation rules

Each item in the `validationRules` array includes the following fields:

| Field | Type | Description |
| - | - | - |
| `ruleType` | String | The kind of validation applied. Options are listed in the table below. |
| `ruleArguments` | Array | The arguments for the rule, such as the maximum length or a regular expression pattern. |
| `shouldApplyNormalization` | Boolean | Whether to normalize the value before the rule is applied. |

The following table lists the available `ruleType` values, the property `type` (and `fieldType`) each supports, and the `ruleArguments` each requires.

| `ruleType` | Supported `type` (and `fieldType`) | Description and arguments |
| - | - | - |
| `AFTER_DATETIME_DURATION` | `DATETIME` | Require a duration after the current date and time. Argument: an ISO-8601 period, such as `["P1Y"]`. |
| `AFTER_DURATION` | `DATE` | Require a duration after the current date. Argument: an ISO-8601 period, such as `["P7D"]`. |
| `ALPHANUMERIC` | `STRING` (`TEXT` and `TEXTAREA`) | Restrict values to certain alphanumeric characters. Argument: one of `ALPHANUMERIC`, `ALPHA_ONLY`, or `NUMERIC_ONLY`. |
| `BEFORE_DATETIME_DURATION` | `DATETIME` | Require a duration before the current date and time. Argument: an ISO-8601 period, such as `["P1M"]`. |
| `BEFORE_DURATION` | `DATE` | Require a duration before the current date. Argument: an ISO-8601 period, such as `["P30D"]`. |
| `DAYS_OF_WEEK` | `DATE`, `DATETIME` | Restrict values to specific days. Argument: one to seven days by name, such as `["MONDAY", "WEDNESDAY", "FRIDAY"]`. |
| `DECIMAL` | `NUMBER` | Restrict the number of decimal places in values. Argument: an integer from 0 to 20, such as `["2"]`. |
| `DOMAIN` | `STRING` (`TEXT`) | Validate domain formatting. No arguments. |
| `EMAIL` | `STRING` (`TEXT` and `EMAIL`) | Validate email address formatting. No arguments. |
| `EMAIL_ALLOWED_DOMAINS` | `STRING` (`TEXT` and `EMAIL`) | Restrict values to specific email domains. Argument: one to 20 domain strings, such as `["company.com", "partner.com"]`. |
| `EMAIL_BLOCKED_DOMAINS` | `STRING` (`TEXT` and `EMAIL`) | Block specific email domains. Argument: one to 20 domain strings, such as `["competitor.com"]`. |
| `END_DATE` | `DATE` | Set a maximum date. Argument: a Unix timestamp in milliseconds, such as `["1640995200000"]`. |
| `END_DATETIME` | `DATETIME` | Set a maximum date and time. Argument: a Unix timestamp in milliseconds, such as `["1640995200000"]`. |
| `FORMAT` | `STRING` (`TEXT` and `TEXTAREA`) | Require specific text case formatting. Argument: one of `CAPITALIZATION`, `UPPER`, or `LOWER`. |
| `MAX_LENGTH` | `STRING` (`TEXT`, `TEXTAREA`, and `PHONE_NUMBER`) | Set a maximum character length. Argument: an integer from 1 to 10000, such as `["100"]`. |
| `MAX_NUMBER` | `NUMBER` | Set a maximum numeric value. Argument: a numeric value, such as `["1000"]`. |
| `MIN_LENGTH` | `STRING` (`TEXT`, `TEXTAREA`, and `PHONE_NUMBER`) | Set a minimum character length. Argument: an integer greater than 1, such as `["5"]`. |
| `MIN_NUMBER` | `NUMBER` | Set a minimum numeric value. Argument: a numeric value, such as `["0"]`. |
| `PHONE_NUMBER_WITH_EXPLICIT_COUNTRY_CODE` | `STRING` (`PHONE_NUMBER`) | Validate phone number formatting, with an option to validate by country code. Argument: none, or a lowercase two-letter country code, such as `["us"]`. |
| `REGEX` | `STRING` (`TEXT` and `TEXTAREA`) | Validate values with a custom regular expression. Arguments: a regex pattern (RE2 syntax) and an error message, such as `["^[A-Z]+$", "Must be uppercase"]`. |
| `SPECIAL_CHARACTERS` | `STRING` (`TEXT` and `TEXTAREA`) | Restrict special characters. Argument: `NOT_ALLOWED`. |
| `START_DATE` | `DATE` | Set a minimum date. Argument: a Unix timestamp in milliseconds, such as `["1640995200000"]`. |
| `START_DATETIME` | `DATETIME` | Set a minimum date and time. Argument: a Unix timestamp in milliseconds, such as `["1640995200000"]`. |
| `URL` | `STRING` (`TEXT` and `URL`) | Validate URL formatting. No arguments. |
| `URL_ALLOWED_DOMAINS` | `STRING` (`TEXT` and `URL`) | Restrict values to specific domains. Argument: one to 20 domain strings, such as `["hubspot.com", "example.com"]`. |
| `URL_BLOCKED_DOMAINS` | `STRING` (`TEXT` and `URL`) | Block specific domains. Argument: one to 20 domain strings, such as `["competitor.com"]`. |
| `WHITESPACE` | `STRING` (`TEXT` and `TEXTAREA`) | Restrict whitespace in values. Arguments for this rule are not documented. |
