Custom fields
Org-defined typed fields on positions — field types, settings UI, and how values appear on position forms.
Custom fields let each organization capture structured metadata on positions (candidates and applications are supported in the API schema for future surfaces). The feature is gated behind the custom_fields per-tenant grant.
Settings → Custom Fields (/dashboard/settings/custom-fields) appears only when trpc.customFields.capabilities returns enabled: true.
Feature gate behavior
| Layer | Check |
|---|---|
| Platform kill switch | platform_integration_settings.enabled for slug custom_fields |
| Per-tenant grant | org_feature_grants.granted = true for your org |
| UI | Tab hidden without grant; API mutations throw PRECONDITION_FAILED |
Definition management and value writes require the grant. Value reads stay open so existing data renders gracefully if a grant is later revoked.
Field types
Each definition has a fieldType (immutable after creation) and a type-specific config bag:
| Type | API value | Config options | Stored value |
|---|---|---|---|
| Text | TEXT | maxLength (default 1,000) | string |
| Long text | TEXTAREA | maxLength (default 20,000) | string |
| Number | NUMBER | min, max | number |
| Currency | CURRENCY | min, max, currency (ISO 4217, 3 chars) | number |
| Date | DATE | — | ISO date string |
| Single select | SELECT | options[] with value + label | option value string |
| Multi select | MULTI_SELECT | options[] | string array |
| Yes / No | BOOLEAN | — | boolean |
| Team member | USER | — | user ID string |
Select types require at least one option (max 100). Options have separate internal value and display label.
Definition metadata
| Property | Description |
|---|---|
label | Human-readable name shown on forms |
description | Optional help text |
required | Whether the field must be filled on create/edit |
sortOrder | Display order on position forms |
entityType | Currently POSITION in the settings UI |
archivedAt | Soft-archive — hidden from new forms, values retained |
Field type is immutable after creation. To change type, archive the old definition and create a new one. Existing values remain tied to the archived definition.
Settings page workflow
- Create field — choose type, label, required flag, and type-specific config (options, min/max, etc.).
- Reorder — arrow buttons adjust
sortOrderamong active definitions. - Edit — update label, description, required, and config (not type).
- Archive / restore — archive hides from position forms; restore brings it back.
The UI mirrors the assessment question editor pattern: conditional config panels per field type.
Position forms
When custom fields are enabled, position create and edit surfaces render a Custom fields section:
- Fields appear in
sortOrder - Required fields block save until filled
- Validation errors are field-labelled (e.g.
"Department code": must be ≤ 100 characters) - USER fields resolve to a team member picker
Values persist in custom_field_values keyed by (definitionId, entityId) — positions use the position ID as entityId.
Not retroactively required
Adding a new required field does not invalidate existing positions missing a value. Required enforcement applies on the next edit save. This prevents mass breakage when admins add fields mid-flight.
API namespace
All procedures live under trpc.customFields:
| Procedure | Access | Purpose |
|---|---|---|
capabilities | Protected org | Gate probe for UI |
listDefinitions | Protected org | Active + archived definitions |
createDefinition | Org admin | New field |
updateDefinition | Org admin | Label, config, required |
archiveDefinition | Org admin | Soft delete |
restoreDefinition | Org admin | Un-archive |
reorderDefinitions | Org admin | Sort order batch update |
getValuesForEntity | Protected org | Read values for a position |
setValuesForEntity | Org admin (grant) | Write values |
Relationship to job governance
Custom fields are the foundation for:
- Job templates — template snapshots include custom field defaults
- Intake forms — hiring managers fill governed fields before requisition approval
- Approval conditions — conditional approval steps can reference field values (via governance
buildTargetFields)
Enable custom_fields before or alongside job_governance for the full template + intake workflow.
Audit trail
Definition create/update/archive actions log to the org activity feed via logActivity with actions like custom_field.created.
Troubleshooting
| Issue | Resolution |
|---|---|
| Tab not visible | Request custom_fields grant from platform admin |
| Cannot save position values | Confirm grant active; check validation messages |
| Wrong options on select | Edit definition options — existing values outside new options fail validation on next save |
| Need different type | Archive + recreate definition |
Related docs
- Job governance — templates and intake forms
- Platform feature flags — enable
custom_fields - First position — using fields when creating roles

