Custom fields
Custom fields are the extra fields your account adds to its records, such as a region or an account manager. These routes list, create, change, archive and restore the definitions: each field's id (the key of a record's custom_fields map), its name, its type and where it appears. The dashboard's Settings > Custom Fields manages the same fields under the same rules. Every route on this page needs custom fields enabled on the account (enable_custom_fields); otherwise it answers 403 feature_disabled.
| Operation | Scope |
|---|---|
GET /custom_fields |
read |
GET /custom_fields/:id |
read |
POST /custom_fields |
read_write |
PATCH /custom_fields/:id |
read_write |
POST /custom_fields/:id/archive |
read_write |
POST /custom_fields/:id/unarchive |
read_write |
Fields are archived, never deleted, through the API: there is no DELETE route. An archived field keeps its values and can be restored.
The custom field entity
{
"id": 12,
"name": "Region",
"field_type": "string",
"applies_to": ["parties"],
"show_on_triage_queue": false,
"archived": false,
"created_at": "2026-05-02T09:00:00Z",
"updated_at": "2026-09-30T09:00:00Z"
}
field_typeis the field's type, one of the API names in Field types.applies_tolists where the field appears:partiesfor a field on parties, or an empty list.- A field on projects lists
projectstoo:parties,projects, or both (in that order). show_on_triage_queueis true when the field is shown on the triage queue in the dashboard.archivedis true for an archived field. An archived field is not served in any record'scustom_fields, and a write naming it is 422validation_failednamingcustom_fields. Its values are kept, and come back if the field is restored.- A field type that has settings of its own (for example, a list of choices) adds them as new members of this entity. Existing members never change meaning.
Field types
| Type | API name | Settings of its own |
|---|---|---|
| String | string |
None. |
| Integer | integer |
None. |
| User | user |
None. |
What each type serves in a record's custom_fields entry, what a write takes and which values it accepts are in Custom field types on the Parties page.
GET /custom_fields
The account's active custom fields in the collection envelope (see Pagination), ordered by id.
Filters:
applies_to:parties, only the fields that appear on parties.applies_to=projectslists only the fields that appear on projects.include_archived:truealso lists archived fields. By default only active fields are listed.
GET /custom_fields/:id
One field, archived or not. A field id of another account is 404 not_found.
Rules
The dashboard and the API apply the same rules:
- Names are unique among your account's active fields, ignoring case and spaces around the name:
Region,regionandREGIONare the same name. An archived field's name is free for a new field. A name already in use is 422validation_failednamingname. - At most 50 active fields per account. Archived fields do not count. A create (or an unarchive) past 50 is 422
validation_failedwith the messageAn account can have at most 50 active custom fields; archive one first. - A field's type is fixed once the field has a value on any record. Before that it can change. Changing it afterwards is 409
conflictwith the messagefield_type cannot be changed once the field has values(to change the type, archive the field and create a new one; reuse its name only when nothing reads the field by name, see the next rule). - Fields are matched by id, but names matter too. Renaming or archiving a field changes nothing in a record's
custom_fieldskeys. Spreadsheets, and your own code if it looks a field up by name, stop finding a field you rename or archive. Some HoundDog integrations and one-off tasks also read fields by name, and they treat an archived field differently: they keep reading and writing it, so values keep landing in a field that is hidden everywhere else. Never create a new field with the name of a field an integration reads, archived or not: the integration may then read either of the two. Check with whoever relies on a field before you rename or archive it, and before you reuse its name.
POST /custom_fields
Creates a field and answers 201 with the custom field entity. Accepts Idempotency-Key (see Idempotency keys): a repeat answers with the field the first request created.
{
"name": "Crew size",
"field_type": "integer",
"applies_to": ["parties"],
"show_on_triage_queue": false
}
name(required): the field's name, unique among your active fields (see Rules). Spaces around it are removed.field_type(required): the type's API name, one of the names in Field types.applies_to: where the field appears,["parties"]when omitted.[](ornull) is allowed: the field appears nowhere until you change it.projectsmakes the field appear on projects as well. Addingprojectson an account without projects is 403feature_disablednamingapplies_to.show_on_triage_queue: show the field on the triage queue,falsewhen omitted. Turning it on without the triage queue enabled is 403feature_disablednamingshow_on_triage_queue.
Errors: 400 validation_failed for a missing name or field_type, or a field_type or applies_to value that is not listed; 422 validation_failed for the name and the 50-field rules.
PATCH /custom_fields/:id
Changes a field (active or archived) and answers with the custom field entity. Only the members you send change; the entity a GET serves can be sent back as read, and changes nothing (no event is recorded either).
name,applies_to,show_on_triage_queue: as on the create. A name in use by another active field is 422 namingname. Removingparties(orprojects) fromapplies_tohides the field's values on those records without deleting them; adding it back shows them again.field_type: changes only while the field has no value on any record; otherwise 409conflict(see Rules). Sending the type the field already has is not a change.archived: accepted only with the value served. Use the archive and unarchive routes to change it; any other value is 422 namingarchived.id,created_atandupdated_atare ignored.
POST /custom_fields/:id/archive
Archives the field and answers with the custom field entity (archived is true). An archived field:
- is not served in any record's
custom_fields, and a write naming it is 422validation_failednamingcustom_fields; - is hidden from the dashboard's forms, record pages, search, exports, spreadsheet imports and the triage queue;
- keeps its values, which come back when it is restored;
- if it is a User-type field, no longer assigns records to users ("Assigned to Me", the user's page and assignment notifications ignore it until it is restored).
Archiving does not move the updated_at of the records holding the field's values, so updated_since does not return them; follow it through the Custom Field Definition Archived event (see Events). Archiving an archived field changes nothing and answers 200. Accepts Idempotency-Key.
POST /custom_fields/:id/unarchive
Restores an archived field and answers with the custom field entity (archived is false); its values are served again. Refused with 422 validation_failed when an active field now has its name (naming name: rename one of them first) or when your account already has 50 active fields. Like archiving, it does not move the holders' updated_at (follow it through Custom Field Definition Restored). Unarchiving an active field changes nothing and answers 200. Accepts Idempotency-Key.
Events
Every change to a field definition, from the dashboard or the API, records an account event (see Events), and webhook subscriptions can subscribe to each type:
| Type | When |
|---|---|
Custom Field Definition Created |
A field was created |
Custom Field Definition Updated |
A field's name, type, applies_to or show_on_triage_queue changed; details.changes lists each with its old and new value |
Custom Field Definition Archived, Custom Field Definition Restored |
A field was archived or restored |
Custom Field Definition Deleted |
Support staff permanently deleted a field and its values (never through the API); details.values_removed is the number of values removed |
A record's custom field value changing is a different event (see Events).