# Custom Fields

Custom fields add organization-specific values to elements, tasks, and publications. The API
separates reusable custom-field definitions from the values stored on individual resources.

Use this page for v2 custom-field concepts. Use the [API reference](/api) for exact request
schemas, response schemas, status codes, and field-level validation.

## Definition Families

Custom-field definitions are scoped by resource family:

| Family | Definition endpoints | Value locations |
|--------|----------------------|-----------------|
| Element custom fields | `/api/v2/custom-fields` | root element writes and `PATCH /api/v2/elements/{id}/custom-fields` |
| Task custom fields | `/api/v2/task-custom-fields` | task writes and `PATCH /api/v2/elements/{id}/tasks/{taskId}/custom-fields` |
| Publication custom fields | `/api/v2/publication-custom-fields` | publication writes |

Definition list endpoints use the shared pagination model. See
[Querying Lists](/docs/guides/api-conventions/querying-lists) before implementing list traversal.

## Selection Options

Selection choices are managed under plural `options` paths:

```text
GET    /api/v2/custom-fields/{id}/options/{optionId}
GET    /api/v2/custom-fields/{id}/options/external-id/{externalId}
POST   /api/v2/custom-fields/{id}/options
PUT    /api/v2/custom-fields/{id}/options/{optionId}
PUT    /api/v2/custom-fields/{id}/options/external-id/{externalId}
PATCH  /api/v2/custom-fields/{id}/options/{optionId}
PATCH  /api/v2/custom-fields/{id}/options/external-id/{externalId}
DELETE /api/v2/custom-fields/{id}/options/{optionId}
DELETE /api/v2/custom-fields/{id}/options/external-id/{externalId}
```

The same option pattern exists under `/api/v2/task-custom-fields` and
`/api/v2/publication-custom-fields`.

Important rules:

- option create returns <Badge variant="default">201 Created</Badge>.
- option delete returns <Badge variant="default">204 No Content</Badge>.
- `PUT` replaces option fields.
- `PATCH` is presence-aware.
- `externalId: null` clears the external ID where the field is documented as clearable.
- `name: null` is invalid.

## Value Shape

Element, task, and publication values use a shared shape:

```json
{
  "customFields": [
    {
      "id": 701,
      "value": "Updated summary"
    },
    {
      "id": 702,
      "selectedOptionIds": [7701]
    }
  ]
}
```

Send the value field that matches the custom-field type:

| Value kind | Field |
|------------|-------|
| Text | `value` |
| Single selection | `selectedOptionIds` with one ID |
| Multiple selection | `selectedOptionIds` |
| Date | `date` in `yyyy-MM-dd` format |
| Number | `number` |

The API validates the custom-field definition, selected option IDs, scope, and type-specific rules.

## Value Write Semantics

For custom-field patch subresources:

- `customFields` is required.
- `customFields: null` is invalid.
- each entry requires `id`.
- omitted custom-field IDs remain unchanged.
- text fields can be cleared by sending `value: ""` or `value: null`.
- date and number fields are cleared by sending the entry without a `date` or `number` value.
- selection fields are cleared by sending `selectedOptionIds: []`.
- single-selection fields accept at most one selected option.
- selected option IDs must belong to the addressed custom-field definition.
- Slack and date-time custom-field rows are intentionally hidden from definition reads and are
  treated as unavailable if addressed in value writes. Public clients should rely only on `TEXT`,
  `SINGLE_SELECTION`, `MULTIPLE_SELECTION`, `DATE`, and `NUMBER`.

The clearing rules above apply only when the field definition allows empty values. Selection and
date definitions can opt out with `allowEmptyValue: false` — covered next.

### Empty-Value Fallback Defaults

:::caution{title="Empty values may store a default instead of clearing"}

Selection and date definitions expose an `allowEmptyValue` flag in definition read responses. When
`allowEmptyValue` is `false`, an addressed entry with an empty value stores a default instead of
clearing the field:

- selection fields select the field's first option (lowest `position`, then lowest option ID).
- date fields store the current date resolved in the requesting user's time zone (UTC when the
  user has no resolvable time zone).

:::

Additional rules:

- the fallback applies only to entries present in the payload; omitted fields keep patch
  semantics.
- when a full replacement endpoint treats `customFields` as replacement state, it removes omitted
  active, writable current-organization values for that resource scope; foreign-organization,
  inactive, Slack, and date-time values outside the public write model are preserved.
- a substituted value behaves like an explicitly sent value; a date fallback that matches the
  stored date is a no-op.
- a selection field without options cannot fall back and keeps clearing semantics.
- fields with `allowEmptyValue: true` keep the clearing semantics listed above.

Root `PUT` is different from custom-field patch subresources: when root element replacement includes
`customFields`, the list is treated as replacement state for the current organization's active,
writable element custom fields only.

## Scope Rules

Custom-field IDs are scoped by organization and placement:

- element custom-field IDs are valid for element values only.
- task custom-field IDs are valid for task values only.
- publication custom-field IDs are valid for publication values only.
- task custom fields can be limited to task formats.
- publication custom fields can be limited to platforms.

When an element is shared across organizations, v2 preserves foreign-organization custom-field
values while patching the current organization's values. A current-organization client cannot write
foreign-organization custom-field IDs.

## Related Migration Notes

For v1 field mappings and client-impacting changes, see
[Custom-Field Migration](/docs/migration-from-v1/custom-fields).
