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

# Custom fields

> Workspace-defined fields, on the wire.

Workspaces define their own fields on CRM records. They arrive in a nested
object with stable keys:

```json theme={null}
{
  "object": "contact",
  "id": "cont_...",
  "first_name": "Ana",
  "custom_fields": {
    "annual_revenue": 250000,
    "segment": "enterprise",
    "renewal_date": "2027-03-01",
    "is_key_account": true,
    "notes_from_sales": null
  }
}
```

Two things follow from that shape.

**Keys are readable and stable.** `custom_fields.segment` is the field's key,
not an opaque id, so your code reads the way the workspace talks. The key is
fixed at creation; renaming a field's label in Sailer does not move it.

**Values are typed.** A number field returns a JSON number, a checkbox returns a
boolean, a date returns an ISO-8601 date string. They are not stringified.

## Discovering the fields a workspace uses

Every custom field defined on the entity appears on every record, with `null`
where a record has no value. So reading any one record shows you the complete
set of keys in use.

```bash theme={null}
curl "https://api.chatsailer.com/v1/contacts?limit=1" \
  -H "Authorization: Bearer $SAILER_API_TOKEN" \
  | jq '.data[0].custom_fields | keys'
```

<Note>
  A dedicated field-definition endpoint, exposing each field's type, label, and
  allowed values, is designed but not part of this release. Until then, infer
  type from the values you receive.
</Note>

## Writing them

Send only the keys you want to change. Unlisted fields are left alone:

```bash theme={null}
curl -X PATCH https://api.chatsailer.com/v1/contacts/cont_123 \
  -H "Authorization: Bearer $SAILER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"custom_fields": {"segment": "mid-market"}}'
```

To clear a field, send `null`. Sending an unknown key, or a value of the wrong
type, returns `422` with the offending key in `error.detail`.
