Skip to main content

CustomFields API

Tenant-defined fields attached to contacts and conversations Base path: /api/v1/custom-fields Endpoint count: 9

title: “Errors worth branching on” description: “Per-endpoint failure templates matching the envelope — what actually fires, what to retry, what to surface to the operator.”

Errors worth branching on

These five failures cover the custom-field create (POST /api/v1/custom-fields), which every form-builder save flows through. Each block below is a full { error, meta } envelope as the API returns it, and the matrix at the bottom answers retry vs surface for the same five classes. For the platform-wide decision table these branches plug into, see the error handling guide.

401 — Unauthorized

A 401 on this page is the bearer key failing before the route ran — it never means the resource is wrong. Rotate the key or re-mint the scoped token; retrying the same request changes nothing.

403 — Forbidden

A 403 means the key authenticated but the operation is gated by scope — check the key’s scopes on the developer page; a 403 is never a data-not-found shape.

422 — Schema

A 422 means the payload did not match the request schema — branch on error.details.field and resend with an allowed name (letters/digits/hyphens/underscores) instead of blind-retrying the same body.

429 — Rate

The Retry-After header and error.details.retry_after are both set on every 429 — resend the SAME request after the lower of the two.

409 — Conflict

Retry with PATCH against the existing field — do not rename-and-forget.

60-second retry matrix


List custom field definitions

GET /api/v1/custom-fields
List every custom-field definition configured for the current tenant, in display order. Populates the Settings › Custom Fields table and the field pickers in the segment builder and contact detail. Returns an empty list for a freshly-provisioned tenant.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Get a custom field definition

GET /api/v1/custom-fields/{id}
Fetch a single custom-field definition by id, including its type, options, default value, validators (regex / min_len / max_len / enum_values) and required/searchable flags. Returns 404 if no definition with that id exists for the tenant.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Scan dependents (segments / campaigns / flows / contacts)

GET /api/v1/custom-fields/{id}/dependencies
Scan every surface that references this custom field — contacts holding a value, plus segments, campaigns, drip enrollments and flows filtering on it — and return the counts, so the UI can preview the blast radius before a force-delete. Returns zeroed counts when the field is unused; 404 if the definition does not exist.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Schema-explorer payload: definition + usage counts + last-10 PII-redacted sample values

GET /api/v1/custom-fields/{id}/explorer
Return the schema-explorer payload for one field: its definition, usage counts across contacts / segments / campaigns / drip enrollments / flows, and up to ten of the most recent distinct, PII-redacted sample values stored under the field key. Powers the field drill-down panel. Returns 404 if the definition does not exist.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Create a custom field definition

POST /api/v1/custom-fields
Create a custom-field definition for the tenant. The key and type are immutable once set; select / multiselect fields require options, and enum_values / min_len / max_len apply per type. Returns 201 with the created definition and rejects invalid payloads with 422.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Reorder custom field definitions

POST /api/v1/custom-fields/reorder
Persist a new top-to-bottom display order for the tenant’s custom-field definitions from a list of definition ids. Unknown ids are ignored and omitted ids keep their current order; duplicate ids are rejected with 422. Returns the refreshed, reordered definition list.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.
string[]
required
Custom-field definition ids in the desired top-to-bottom display order (1–500 ids). Unknown ids are ignored and any definitions omitted from the list keep their current order.

Set a custom-field value on a contact

PUT /api/v1/custom-fields/values
Set a single custom-field value on one contact, validated against the field definition, and persist it to the contact’s custom_attributes. Invalidates the contact-detail cache so the next read reflects the write. Returns the contact id, key and an ok flag.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.
string
required
Id of the contact whose custom-field value is being set (1–128 characters).
string
required
Machine key of the custom-field definition to write, in snake_case (up to 40 characters).
string | number | boolean | string[] | null
required
Value to store for this field. Its JSON type must match the field’s declared type — a string for text / select, a number for number, a boolean for boolean, an ISO-8601 string for date, or an array of strings for multiselect.

Update a custom field definition

PATCH /api/v1/custom-fields/{id}
Update a custom-field definition’s editable attributes (name, description, options, default value, required / searchable flags and validators). The key and type stay frozen so stored values are never orphaned; passing null clears a validator or the default. Returns 404 if the definition does not exist.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.

Delete a custom field definition

DELETE /api/v1/custom-fields/{id}
Delete a custom-field definition and strip its key from every contact. Without force=true, a field still referenced by any segment, campaign, drip enrollment or flow returns 409 with the full dependency snapshot; with force=true, dependents are flagged broken and the field is removed. Returns 204 on success.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.
Response: 204 No Content