# Custom attributes

> Add typed fields to customers, companies, conversations, messages and custom objects using name suffixes and attribute metadata.

Source: https://developer.kustomer.com/docs/concepts/custom-attributes

Custom attributes are your own fields on Kustomer objects. They live under a `custom` key, and the **suffix** of each name sets its type:

```json
{
  "custom": {
    "loyaltyTierStr": "gold",
    "lifetimeValueNum": 1840.5,
    "lastOrderAt": "2026-10-02T15:04:05Z",
    "marketingOptInBool": true,
    "accountUrl": "https://admin.acme.example/customers/10293",
    "notesTxt": "Prefers email. Allergic to latex."
  }
}
```

## Suffixes

| Suffix | Type                                 | Example name         | Example value                |
| ------ | ------------------------------------ | -------------------- | ---------------------------- |
| `Str`  | Short string, up to 1,024 characters | `loyaltyTierStr`     | `"gold"`                     |
| `Txt`  | Text, shown as a multi-line field    | `notesTxt`           | `"Prefers email."`           |
| `Num`  | Number                               | `lifetimeValueNum`   | `1840.5`                     |
| `At`   | Date and time (ISO 8601)             | `lastOrderAt`        | `"2026-10-02T15:04:05Z"`     |
| `Bool` | Boolean                              | `marketingOptInBool` | `true`                       |
| `Url`  | URL                                  | `accountUrl`         | `"https://..."`              |
| `Id`   | Reference to another object          | `primaryOrderId`     | `"5822a4a5aa5f92110005d69a"` |

Every type also accepts `null` to clear the value. Use camelCase and keep names stable: the system name is what the API, workflows and search use, even if an admin later changes the display name.

_Type a label such as 'Order number' and pick a type suffix (Str, Txt, Num, At, Bool, Url or Id). The label is split into words, camelCased and given the suffix, so 'Order number' with Str becomes orderNumberStr, a short string of up to 1,024 characters. The name then appears in a PATCH /v1/customers/{id} body under custom, in a mock customer card labelled with the default display name 'Order Number' (title-cased, without the suffix), and as customer_custom_orderNumberStr in search and workflow conditions. Mistakes are shown too: a name with no suffix or a spelled-out type such as orderNumberString, or a display name used as the key, fails with 400 bad_request; PascalCase is flagged as not camelCase; sending null clears the value; and Id attributes need metadata with a target before you write values._

## Which objects support them

Customers, companies, conversations, messages, notes, users, KObjects and tracked events. Each object type has its own set of attributes, configured separately.

## Attribute metadata

Metadata tells Kustomer how to present and validate each attribute: its display name, type, allowed values, and whether it's sensitive. Admins can edit it in **Settings › Platform › Klasses**, or you can manage it through the API.

`GET /v1/metadata/{resource}` ([reference](https://developer.kustomer.com/api/core-resources/get-custom-attribute-metadata))

`PUT /v1/metadata/{resource}` ([reference](https://developer.kustomer.com/api/core-resources/update-custom-attribute-metadata))

`resource` is one of `customer`, `company`, `conversation`, `message`, `note`, `user`, `kobject`, `kobject.<klassSlug>`, `event` or `event.<suffix>`.

```bash title="cURL"
curl -X PUT "https://acme.api.kustomerapp.com/v1/metadata/customer" \
  -H "Authorization: Bearer $KUSTOMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "properties": {
      "loyaltyTierStr": {
        "displayName": "Loyalty tier",
        "enumeration": ["bronze", "silver", "gold"]
      },
      "lifetimeValueNum": { "displayName": "Lifetime value" },
      "primaryOrderId": {
        "displayName": "Primary order",
        "target": "kobject.ecomm-order"
      }
    }
  }'
```

### Metadata properties

**properties.\<name>**

A single request can set up to 100 properties.

> **Configure Id attributes before you use them:** An attribute ending in `Id` must have metadata with a `target` before you write values to it. Kustomer validates that each value refers to an existing object of the target type.

> **Inherited sensitivity:** Some standard attributes inherit sensitivity settings: `customer.externalId` follows `customer.externalIds`, and `customer.firstName`, `customer.lastName` and `customer.displayName` follow `customer.name`.

## Using custom attributes elsewhere

- **Search.** Custom attributes are searchable with names like `customer_custom_loyaltyTierStr` or `kobject_custom_ecomm-order_orderStatusStr`. See [Search](https://developer.kustomer.com/docs/concepts/search).
- **Workflows and business rules.** Use them in conditions (for example `customer_custom_loyaltyTierStr` equals `gold`) and set them in actions. See [Conditions and variables](https://developer.kustomer.com/docs/workflows/conditions-and-expressions).
- **Apps.** Declare them in an app definition so they're configured on install. See [Klasses](https://developer.kustomer.com/docs/apps/klasses).
