Skip to main content
PATCH

Authorizations

Authorization
string
header
required

Your secret API key as a Bearer token: Authorization: Bearer vxn_sk_.... Keys are created and scoped in the dashboard - see Authentication.

Headers

Idempotency-Key
string

Recommended on PATCH and DELETE for safe retries.

Path Parameters

id
string
required

Custom field identifier (cf_ prefix).

Pattern: ^cf_[A-Za-z0-9]+$

Body

application/json

Lifecycle-gated PATCH. While the field is IN USE (usage_count > 0): key renames, field_type changes, and option-value removals are BLOCKED (409 custom_field_in_use). Always editable: label, description, position, required, and ADDING options.

label

Customer-facing label - shown on the signup form, referenced on wallet passes, and used in the dashboard. Plain string or per-language object (the platform localization pattern, same as Card.name). This is the DEFAULT - each card's form_builder can override the label per card.

Required string length: 1 - 50
description
string | null

Always editable.

Maximum string length: 500
position
integer

Always editable.

options
object[]

Adding options is always allowed; removing a value that customers already stored is blocked while in use.

key
string

Rename - BLOCKED while usage_count > 0.

Pattern: ^[a-z][a-z0-9_]{1,49}$
field_type
enum<string>

Field type - see the type table on the Custom Field object. Immutable while in use.

Available options:
text,
textarea,
number,
currency,
date,
boolean,
select,
multiselect
Example:

"select"

Response

Updated custom field (full object).

A reusable custom field DEFINITION - the single vocabulary used across the whole platform: the signup form (via each card's form_builder), the customer record (Customer.custom.<key>), wallet pass slots ({{custom.<key>}} in Card.pass_fields), and notification templates. Define once, reference everywhere.

The definition owns IDENTITY (key, type, options, granularity) and DEFAULTS (label translations, required, position); each card's form owns USAGE (which fields, per-card required/order/label overrides). Limits: 50 definitions per organization (409 custom_field_limit_reached), 20 fields per card form.

id
string
required

Opaque, stable, immutable. cf_ prefix.

Pattern: ^cf_[A-Za-z0-9]+$
Example:

"cf_01HW9R9Z4EF7N8MTX1RVCFLD01"

object
string
required

Always "custom_field".

Allowed value: "custom_field"
key
string
required

Stable machine identifier, unique within the organization (2-50 chars, lowercase snake). Used in {{custom.<key>}} templates and Customer custom.<key> payloads. Renames are blocked while the field is in use (usage_count > 0) to prevent keys diverging across cards.

Pattern: ^[a-z][a-z0-9_]{1,49}$
Example:

"department"

label
required

Customer-facing label - shown on the signup form, referenced on wallet passes, and used in the dashboard. Plain string or per-language object (the platform localization pattern, same as Card.name). This is the DEFAULT - each card's form_builder can override the label per card.

Required string length: 1 - 200
field_type
enum<string>
required

What kind of data the field holds - drives form input, validation, and typed pass/notification rendering:

Immutable while the field is used by any card (409 custom_field_in_use).

Available options:
text,
textarea,
number,
currency,
date,
boolean,
select,
multiselect
Example:

"select"

created_at
integer
required

Unix seconds.

Example:

1750000000

description
string | null

Internal helper text for the dashboard.

Maximum string length: 500
Example:

"Clinic department the patient is assigned to."

position
integer

DEFAULT form position when added to a card; each card's form_builder ordering overrides.

Example:

2

options
object[]

Choices for select / multiselect (required for those types). Each option is {value, label} - labels are always editable (display only); values are immutable once any customer has stored them and removing a used value is blocked (409 custom_field_in_use). Adding options is always allowed.

Example:
date_granularity
enum<string>

DATE type only - controls the stored format: date → YYYY-MM-DD, monthYear → YYYY-MM, year → YYYY. Forced to date for non-date types.

Available options:
year,
monthYear,
date
Example:

"date"

usage_count
integer

Read-only. Number of cards referencing this field. Renames + type changes + deletes are blocked while > 0.

Example:

3

cards_using
string[]

Read-only. The referencing card ids.

Example:
updated_at
integer

Unix seconds.

Example:

1750000000

number_format
enum<string> | null

number fields only: integer rejects fractional input; decimal (default) allows it. Null on other types.

Available options:
integer,
decimal,
null