Custom Fields
Extend any entity with custom data fields
Custom fields let you add structured data to contacts, companies, deals, and activities. Define field schemas (definitions) and set values per entity.
How It Works
- Create a definition — define the field name, type, and which entity it applies to
- Set values — attach field values to specific entities
- Query — filter and retrieve custom field values
Field Types
| Type | Description | Example Value |
|---|---|---|
text | Free-form text | "Enterprise customer" |
number | Numeric value | 42 |
boolean | True/false | true |
date | ISO 8601 date | "2026-01-15" |
select | Single option from a list | "Gold" |
multi_select | Multiple options from a list | ["Gold", "VIP"] |
url | URL | "https://acme.com" |
email | Email address | "admin@acme.com" |
phone | Phone number | "+1-555-0100" |
Entity Types
Custom fields can be defined for:
contact— added to contactscompany— added to companiesdeal— added to dealsactivity— added to activities
Create a Field Definition
curl -X POST https://api.nodestash.io/v1/custom-fields \
-H "Authorization: Bearer $NODESTASH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entity_type": "contact",
"name": "VIP Level",
"slug": "vip_level",
"field_type": "select",
"description": "Customer VIP tier",
"options": ["Platinum", "Gold", "Silver", "Bronze"],
"is_required": false,
"display_order": 0
}'const field = await client.customFields.definitions.create({
entity_type: 'contact',
name: 'VIP Level',
slug: 'vip_level',
field_type: 'select',
description: 'Customer VIP tier',
options: ['Platinum', 'Gold', 'Silver', 'Bronze'],
is_required: false,
display_order: 0,
})Definition Data Model
| Field | Type | Description |
|---|---|---|
id | string | Unique ID with cf_ prefix |
entity_type | string | contact, company, deal, or activity |
name | string | Display name (max 200 chars) |
slug | string | URL-safe identifier (^[a-z][a-z0-9_]*$, max 100 chars) |
field_type | string | One of the field types above |
description | string | null | Field description (max 500 chars) |
is_required | boolean | Whether the field is required |
options | string[] | null | Options for select and multi_select types |
display_order | integer | Display ordering (min 0) |
created_at | string | ISO 8601 timestamp |
updated_at | string | ISO 8601 timestamp |
The slug must be unique per workspace and entity type. It cannot be changed after creation.
Set Field Values
Set custom field values on an entity using the slug as the key:
curl -X PUT https://api.nodestash.io/v1/contacts/ct_abc123/custom-fields \
-H "Authorization: Bearer $NODESTASH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"vip_level": "Gold",
"customer_since": "2024-01-15",
"annual_revenue": 500000
}
}'const values = await client.customFields.values.set('contacts', 'ct_abc123', {
fields: {
vip_level: 'Gold',
customer_since: '2024-01-15',
annual_revenue: 500000,
},
})Setting values is a merge operation — existing field values that aren't included in the request are preserved, not deleted.
Get Field Values
curl https://api.nodestash.io/v1/contacts/ct_abc123/custom-fields \
-H "Authorization: Bearer $NODESTASH_API_KEY"const values = await client.customFields.values.get('contacts', 'ct_abc123')
for (const field of values) {
console.log(`${field.name} (${field.field_type}): ${field.value}`)
}Response:
{
"data": [
{
"id": "cfv_abc123",
"type": "custom_field_value",
"attributes": {
"field_definition_id": "cf_def456",
"slug": "vip_level",
"name": "VIP Level",
"field_type": "select",
"value": "Gold"
}
},
{
"id": "cfv_ghi789",
"type": "custom_field_value",
"attributes": {
"field_definition_id": "cf_jkl012",
"slug": "annual_revenue",
"name": "Annual Revenue",
"field_type": "number",
"value": 500000
}
}
],
"meta": {
"request_id": "req_abc123def456ghi789jkl012"
}
}List Definitions
# All definitions for contacts
curl "https://api.nodestash.io/v1/custom-fields?entity_type=contact" \
-H "Authorization: Bearer $NODESTASH_API_KEY"const { data: definitions } = await client.customFields.definitions.list({
entity_type: 'contact',
})
for (const def of definitions) {
console.log(`${def.name} (${def.field_type}) — ${def.slug}`)
}