Custom fields

Definitions belong to the workspace and values belong to individual contacts. Read GET /fields or GET /fields/{id} with contacts:read. Creating with POST /fields and saving with POST /fields/{id}/save requires segments:write; saving also requires If-Match.

Create a definition

Include Idempotency-Key and a body such as:

{"key": "loyalty_points", "label": "Points", "type": "number"}

Types are text, number, boolean, date, datetime, single_select and multi_select. Selection types require 1–30 options with {id, label} and unique IDs. Other types omit options, including empty arrays.

The key is unique within the workspace. Key, type and existing option IDs remain stable during edits; labels can change and options can be added. Changing a label does not change stored values.

Save a value

Profile custom is keyed by definition ID, not its key or label. This fragment can be part of a contact PATCH with the current revision:

{
  "custom": {
    "FIELD_ID": {"type": "number", "value": 120}
  }
}

Dates use YYYY-MM-DD; datetime uses UTC with Z and at most microsecond precision. Single selection stores an option ID and multiple selection stores an array of IDs. false, 0 and [] are present values; null in a patch removes the value.

POST /contacts/{id}/custom-fields accepts {fieldId, value} with contacts:write and the contact revision. It also accepts {definition: {key, label, type, options?}, value} to create the definition and value atomically; this variant additionally requires segments:write. Failed validation leaves no orphan definition.

Use the data

Values support personalization and audience rules. The server checks workspace, type and options before saving; creating a definition does not assign values to other contacts. Manage definitions in Settings → Custom fields.