Custom field definitions API
The endpoints under /api/custom-fields/ manage the schema for custom fields — the field definitions admins create in the settings UI. The actual values you store on individual records use each entity's regular endpoint (see Custom fields feature).
Permissions
- List / read — any authenticated user (the frontend needs definitions to render detail-page forms).
- Create / update / delete — admin role only.
List definitions
GET /api/custom-fields/?target_model=Lead&active_only=true
Authorization: Bearer <token>
{
"definitions": [
{
"id": 17,
"target_model": "Lead",
"key": "industry",
"label": "Industry",
"field_type": "dropdown",
"options": [
{ "value": "saas", "label": "SaaS" },
{ "value": "manufacturing", "label": "Manufacturing" }
],
"is_required": false,
"is_filterable": true,
"is_active": true,
"display_order": 0
}
]
}
Query parameters:
target_model— filter by entity name (Lead,Account,Contact,Opportunity,Task,Case,Invoice,Estimate,RecurringInvoice).active_only=true— exclude soft-deleted definitions.
Create
POST /api/custom-fields/
{
"target_model": "Lead",
"key": "industry",
"label": "Industry",
"field_type": "dropdown",
"options": [
{ "value": "saas", "label": "SaaS" },
{ "value": "manufacturing", "label": "Manufacturing" }
],
"is_required": false,
"is_filterable": true,
"display_order": 0,
"is_active": true
}
Constraints:
keymust match^[a-z][a-z0-9_]*$and be unique per(org, target_model).optionsis required only whenfield_typeisdropdown.target_modelmust be one of the nine supported entities.
Update
PUT /api/custom-fields/<id>/
{ "label": "Industry Vertical", "options": [ … ] }
Immutable fields: key and field_type cannot change after creation. The API returns 400 if either is in the body.
Delete (soft)
DELETE /api/custom-fields/<id>/
Sets is_active=false. Existing values on records are preserved; new writes for the deactivated key are rejected as unknown. Reactivate with PATCH { "is_active": true }.
Errors
{
"error": true,
"errors": {
"key": "must match ^[a-z][a-z0-9_]*$",
"options": "Dropdown fields require a non-empty list of {value, label} pairs"
}
}
See Errors for the full error response shape.