Custom field definitions extend the data model of core entities (customers, subscriptions, plans, products) with your own fields. Define the field type, validation rules, and visibility, then set values on individual records.
Supported field types: text, number, boolean, date, enum, entity_ref
Key concepts:
- Entity types - which resources this field applies to (e.g.,
customer,subscription) - Field group - logical grouping for UI display
- Validation - regex patterns, min/max values, required/optional
- Auditable - whether changes to this field are tracked in the audit log
- Deprecation - soft-disable a field before permanent removal
List custom field definitions
Lists custom field definitions in form order, all in one page. Filters use the field.op=value grammar (status, field_type, field_group, key, visibility, write_access, auditable, created_at, updated_at, deprecated_at). entity_type keeps the definitions offered on one entity type (CUSTOMER, PRODUCT, PLAN, SUBSCRIPTION). Archived definitions are left out unless include_archived is set or the status filter names archived.
Required scope: org.read (Read organization profile).
query Parameters
auditableFilter on auditable (boolean). Operators: eq — dot grammar, e.g. auditable.eq=value; a bare auditable=value means eq.
created_atFilter on created_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. created_at.gt=value; a bare created_at=value means eq.
deprecated_atFilter on deprecated_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. deprecated_at.gt=value; a bare deprecated_at=value means eq.
field_groupFilter on field_group (string). Operators: eq, in — dot grammar, e.g. field_group.in=value; a bare field_group=value means eq. A bare comma-separated value is in-sugar: field_group=a,b means field_group.in=a,b.
field_typeFilter on field_type (enum). Operators: eq, in — dot grammar, e.g. field_type.in=value; a bare field_type=value means eq. A bare comma-separated value is in-sugar: field_type=a,b means field_type.in=a,b. Legal values: STRING, NUMBER, BOOLEAN, DATE, DATETIME, ENUM, URL, EMAIL, ENTITY_REF.
keyFilter on key (string). Operators: eq, contains, in — dot grammar, e.g. key.contains=value; a bare key=value means eq. A bare comma-separated value is in-sugar: key=a,b means key.in=a,b.
statusFilter on status (enum). Operators: eq, ne, in — dot grammar, e.g. status.ne=value; a bare status=value means eq. A bare comma-separated value is in-sugar: status=a,b means status.in=a,b. Legal values: draft, scheduled, active, deprecated, archived.
updated_atFilter on updated_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. updated_at.gt=value; a bare updated_at=value means eq.
visibilityFilter on visibility (enum). Operators: eq, in — dot grammar, e.g. visibility.in=value; a bare visibility=value means eq. A bare comma-separated value is in-sugar: visibility=a,b means visibility.in=a,b. Legal values: PUBLIC, INTERNAL.
write_accessFilter on write_access (enum). Operators: eq, in — dot grammar, e.g. write_access.in=value; a bare write_access=value means eq. A bare comma-separated value is in-sugar: write_access=a,b means write_access.in=a,b. Legal values: ALL, ADMIN_ONLY, SYSTEM_ONLY.
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
entity_typeOnly definitions offered on this entity type (CUSTOMER, PRODUCT, PLAN, SUBSCRIPTION).
include_archivedInclude archived definitions. Off by default: this list is what the forms read. A status filter naming archived (status=archived, status.in=…,archived) includes them without it.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List custom field definitions › Responses
OK
Create a custom field definition
Creates an active definition and answers 201 with it; left out, visibility defaults to PUBLIC, write_access to ALL, sort_order to 0, and auditable and show_in_table to false. The key must match ^[a-z][a-z0-9_]{1,63}$, and an ENUM field needs enum_options and an ENTITY_REF field entity_ref_config, or the request is refused with 400. A key already used by a definition in this workspace that is not archived is refused with 409.
Required scope: org.update (Update organization profile).
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Create a custom field definition › Request Body
display_nameentity_typesfield_typeRequests also accept the new spelling: each value in lower case (boolean for BOOLEAN). The listed spelling is deprecated in requests and accepted until 2026-11-30.
keyauditabledefault_valuedescriptionfield_groupshow_in_tablesort_ordervisibilityRequests also accept the new spelling: each value in lower case (internal for INTERNAL). The listed spelling is deprecated in requests and accepted until 2026-11-30.
write_accessRequests also accept the new spelling: each value in lower case (admin_only for ADMIN_ONLY). The listed spelling is deprecated in requests and accepted until 2026-11-30.
Create a custom field definition › Responses
Created
Get a custom field definition
Returns one definition that is not archived. An archived definition answers 404 here; list with include_archived to see it, or restore it with PATCH /custom-fields/{id}.
Required scope: org.read (Read organization profile).
path Parameters
idCustom field definition UUID
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get a custom field definition › Responses
OK
Update a custom field definition
Deprecated: use PATCH /custom-fields/{id} instead. Removed on 2026-11-30.
Merge-patches a definition: a field left out stays as it is. key, field_type and entity_types are fixed at creation. status moves the definition through its lifecycle: archived archives it (it leaves every form, its key is free again, its stored values stay); any other status on an archived definition restores it to that status, refused with 409 when a live definition has taken its key since; deprecated keeps the stored values and refuses new ones. An archived definition takes no other change until a status restores it (409). expected_version refuses an update made against a stale read (409).
Required scope: org.update (Update organization profile).
path Parameters
idCustom field definition UUID
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Update a custom field definition › Request Body
auditabledefault_valuedescriptiondisplay_nameexpected_versionfield_groupshow_in_tablesort_orderstatusMoves the definition through its lifecycle. archived archives it: it leaves every form and its key is free again, and its stored values stay. Any other status on an archived definition restores it to that status, refused with 409 when a live definition has taken its key since. deprecated keeps the stored values but refuses new ones.
visibilityRequests also accept the new spelling: each value in lower case (internal for INTERNAL). The listed spelling is deprecated in requests and accepted until 2026-11-30.
write_accessRequests also accept the new spelling: each value in lower case (admin_only for ADMIN_ONLY). The listed spelling is deprecated in requests and accepted until 2026-11-30.
Update a custom field definition › Responses
OK
Delete a custom field definition
With the header X-Confirm-Purge: true, deletes the definition, archived or not, and every value stored for it; this cannot be undone. Without the header the definition is archived instead, until 2026-11-30; after that date a DELETE without the header is refused with 400. To archive, send PATCH /custom-fields/{id} with {"status": "archived"}. Answers 204.
Required scope: org.update (Update organization profile).
path Parameters
idCustom field definition UUID
Headers
X-Confirm-Purgetrue deletes the definition and every value stored for it. Without it the definition is archived instead, until 2026-11-30; after that date the header is required.
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Delete a custom field definition › Responses
No Content
Update a custom field definition
Merge-patches a definition: a field left out stays as it is. key, field_type and entity_types are fixed at creation. status moves the definition through its lifecycle: archived archives it (it leaves every form, its key is free again, its stored values stay); any other status on an archived definition restores it to that status, refused with 409 when a live definition has taken its key since; deprecated keeps the stored values and refuses new ones. An archived definition takes no other change until a status restores it (409). expected_version refuses an update made against a stale read (409).
Required scope: org.update (Update organization profile).
path Parameters
idCustom field definition UUID
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Update a custom field definition › Request Body
auditabledefault_valuedescriptiondisplay_nameexpected_versionfield_groupshow_in_tablesort_orderstatusMoves the definition through its lifecycle. archived archives it: it leaves every form and its key is free again, and its stored values stay. Any other status on an archived definition restores it to that status, refused with 409 when a live definition has taken its key since. deprecated keeps the stored values but refuses new ones.
visibilityRequests also accept the new spelling: each value in lower case (internal for INTERNAL). The listed spelling is deprecated in requests and accepted until 2026-11-30.
write_accessRequests also accept the new spelling: each value in lower case (admin_only for ADMIN_ONLY). The listed spelling is deprecated in requests and accepted until 2026-11-30.
Update a custom field definition › Responses
OK
Deprecate a custom field definition
Deprecated: use PATCH /custom-fields/{id} instead. Removed on 2026-11-30.
Moves an active definition to deprecated: its stored values stay, new values are refused. Refused (409) when it is already deprecated or archived. Replaced by PATCH /custom-fields/{id} with {"status": "deprecated"}.
Required scope: org.update (Update organization profile).
path Parameters
idCustom field definition UUID
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Deprecate a custom field definition › Responses
OK
Purge a custom field definition
Deprecated: use DELETE /custom-fields/{id} instead. Removed on 2026-11-30.
Deletes the definition and every value stored for it, and answers how many values went. Requires the header X-Confirm-Purge: true. Replaced by DELETE /custom-fields/{id} with the same header.
Required scope: org.update (Update organization profile).
path Parameters
idCustom field definition UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Confirm-PurgeMust be 'true' to confirm purge
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Purge a custom field definition › Responses
OK
Restore an archived custom field definition
Deprecated: use PATCH /custom-fields/{id} instead. Removed on 2026-11-30.
Brings an archived definition back to the forms: deprecated again when it had been deprecated before it was archived, active otherwise. Its stored values were kept and hydrate again. Refused (409) when the definition is not archived, or when a live definition has taken its key since. Replaced by PATCH /custom-fields/{id} with {"status": "active"} (or "deprecated").
Required scope: org.update (Update organization profile).
path Parameters
idCustom field definition UUID
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Restore an archived custom field definition › Responses
OK