Skip to main content

Custom Fields

Custom fields let you store business-specific data on contacts — company name, subscription plan, lead source, contract renewal date, or anything else relevant to your workflow.

Unlike a free-form JSON blob, SendSeven custom fields are schema-defined and typed. You first create a field definition (with a key, a type, and optional validation rules), then set values for that field on individual contacts. This gives you type validation, dropdown options, segmentation support, and personalization variables.

Breaking change

Earlier versions of this guide described setting an arbitrary custom_fields JSON object directly on POST /contacts or PUT /contacts/{id}. That is no longer supported. The custom_fields body field is ignored on contact create/update. Custom field values are now managed through the dedicated endpoints documented below — most importantly POST /api/v1/contacts/{contact_id}/fields/{field_id}.

The Two-Step Model

  1. Define the field once (an admin/settings operation) — POST /api/v1/custom-fields. This returns a field definition with an id.
  2. Set a value per contactPOST /api/v1/contacts/{contact_id}/fields/{field_id}.

You only define a field once; afterwards you set/read its value on as many contacts as you like.

Required Scopes

ScopePurpose
settings:readList / view custom field definitions
settings:updateCreate / update custom field definitions
settings:adminDelete (deactivate) a custom field definition
contacts:readRead custom field values on a contact
contacts:updateSet custom field values on a contact

Field Types

field_typeDescription
textFree-form text
numberNumeric values (integers and decimals)
booleanTrue / false
dateDate only (YYYY-MM-DD)
datetimeDate and time (ISO 8601)
selectSingle selection from options
multiselectMultiple selections from options
emailEmail address
phonePhone number
urlWebsite URL
locationLatitude / longitude
collectionArray of values

select and multiselect require an options array. After a field is created, its key and field_type are immutable to preserve data integrity.


Step 1 — Define a Custom Field

curl -X POST "https://api.sendseven.com/api/v1/custom-fields" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"name": "Company Size",
"key": "company_size",
"field_type": "select",
"description": "Number of employees",
"options": ["1-10", "11-50", "51-200", "201-500", "500+"],
"required": false,
"display_order": 0
}'

Request fields

FieldRequiredNotes
nameyesDisplay name (1–100 chars)
keyyesInternal key, snake_case, must match ^[a-z][a-z0-9_]*$
field_typeyesOne of the types above
descriptionnoHelp text (≤ 500 chars)
optionsfor select/multiselectArray of allowed string values
requirednoDefaults to false
default_valuenoDefault for new contacts
agent_visiblenoVisible to agents (default true)
agent_editablenoEditable by agents (default true)
user_editablenoEditable by the contact via self-service (default false)
display_ordernoLower numbers sort first (default 0)

Response (201 Created) — note the id, which you use to set values:

{
"id": "cf-12345678-abcd-efgh-ijkl-mnopqrstuvwx",
"tenant_id": "tn-12345678-abcd-efgh-ijkl-mnopqrstuvwx",
"name": "Company Size",
"key": "company_size",
"field_type": "select",
"description": "Number of employees",
"options": ["1-10", "11-50", "51-200", "201-500", "500+"],
"required": false,
"default_value": null,
"agent_visible": true,
"agent_editable": true,
"user_editable": false,
"display_order": 0,
"is_active": true,
"created_at": "2026-01-15T10:30:00Z"
}

List, Get, Update, Delete Definitions

# List all definitions (paginated)
curl "https://api.sendseven.com/api/v1/custom-fields?page=1&page_size=20" \
-H "Authorization: Bearer s7_api_..."

# Get one definition
curl "https://api.sendseven.com/api/v1/custom-fields/cf-12345678" \
-H "Authorization: Bearer s7_api_..."

# Update a definition (key and field_type cannot change)
curl -X PUT "https://api.sendseven.com/api/v1/custom-fields/cf-12345678" \
-H "Authorization: Bearer s7_api_..." \
-H "Content-Type: application/json" \
-d '{"options": ["1-10", "11-50", "51-200", "201-1000", "1000+"]}'

# Delete (soft-delete / deactivate) a definition
curl -X DELETE "https://api.sendseven.com/api/v1/custom-fields/cf-12345678" \
-H "Authorization: Bearer s7_api_..."

Deleting a field definition deactivates it (soft delete) so existing data is preserved; inactive fields can no longer be assigned new values.


Step 2 — Set a Field Value on a Contact

Send the value to POST /api/v1/contacts/{contact_id}/fields/{field_id}. The body is a single value whose type must match the field's field_type (and, for select/multiselect, must be one of the defined options).

curl -X POST "https://api.sendseven.com/api/v1/contacts/contact_d4e5f6a7/fields/cf-12345678" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{"value": "51-200"}'

Response

{ "success": true, "message": "Field value updated" }

Setting the value again on the same field overwrites the previous value. A 404 is returned if the contact or the field definition does not exist.


Read Custom Field Values

All values for a contact

curl "https://api.sendseven.com/api/v1/contacts/contact_d4e5f6a7/fields" \
-H "Authorization: Bearer s7_api_..."
{
"contact_id": "contact_d4e5f6a7",
"fields": [
{
"field_id": "cf-12345678",
"field_key": "company_size",
"field_name": "Company Size",
"field_type": "select",
"value": "51-200"
}
]
}

Embedded in the contact

GET /api/v1/contacts/{contact_id} also returns custom field values under a custom_fields object, keyed by field key:

{
"id": "contact_d4e5f6a7",
"name": "Sophie Martin",
"email": "[email protected]",
"custom_fields": {
"company_size": {
"field_definition_id": "cf-12345678",
"name": "Company Size",
"field_type": "select",
"value": "51-200"
}
}
}
info

This embedded custom_fields object is read-only. Writing it back on PUT /contacts/{id} has no effect — use POST /contacts/{id}/fields/{field_id} to change a value.


Python Example

import requests

BASE_URL = "https://api.sendseven.com/api/v1"
HEADERS = {
"Authorization": "Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00",
"Content-Type": "application/json",
}

# 1. Define the field once (settings:update)
field = requests.post(
f"{BASE_URL}/custom-fields",
headers=HEADERS,
json={
"name": "Plan",
"key": "plan",
"field_type": "select",
"options": ["basic", "professional", "scale", "enterprise"],
},
).json()
field_id = field["id"]

# 2. Set the value on a contact (contacts:update)
contact_id = "contact_d4e5f6a7"
requests.post(
f"{BASE_URL}/contacts/{contact_id}/fields/{field_id}",
headers=HEADERS,
json={"value": "enterprise"},
)

# 3. Read all custom field values for the contact (contacts:read)
values = requests.get(
f"{BASE_URL}/contacts/{contact_id}/fields",
headers=HEADERS,
).json()
print(values["fields"])

Common Custom Field Patterns

keyfield_typeUse Case
companytextCRM sync
sourceselectLead tracking
planselectSubscription tier
preferred_languagetextLocalization
external_idtextThird-party system mapping
lifetime_valuenumberRevenue tracking
last_order_datedateE-commerce integration
is_resellerbooleanSegmentation flag

Next Steps