Skip to content

Custom Fields, Values & Tags

Custom fields, custom values, and tags let you extend and label the data in your SMBcrm account without changing your data model. Custom fields attach structured data, like a referral source or preferred contact method, to records such as contacts, opportunities, and custom objects. Custom values are reusable snippets you can drop into templates and messages. Tags are simple labels you can filter and automate on.

Base URL: https://services.smbcrm.com · Version header: v3 · Scopes: locations/customFields.readonly, locations/customFields.write, locations/customValues.readonly, locations/customValues.write, locations/tags.readonly, locations/tags.write. See Scopes.

Custom values, tags, and contact and opportunity custom fields take your account/location ID as a path segment, as described in Base URL & Headers. The custom object field endpoints vary: some take locationId as a query parameter, some as a body field, and looking up or deleting a field by ID doesn’t need it at all. Each endpoint below shows where it goes.

Custom fields on contacts and opportunities live under your location ID. Set model to contact or opportunity to choose which kind of record a field belongs to.

GET/locations/{locationId}/customFields

List custom fields for contacts, opportunities, or both.

scope locations/customFields.readonlyauth Location token or PIT

Add the optional model query parameter to filter the list: contact, opportunity, or all.

Terminal window
curl "https://services.smbcrm.com/locations/<location_id>/customFields?model=contact" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"customFields": [
{
"id": "<field_id>",
"name": "Referral Source",
"fieldKey": "contact.referral_source",
"placeholder": "Where did they hear about us?",
"dataType": "TEXT",
"position": 0,
"locationId": "<location_id>",
"model": "contact"
},
{
"id": "<field_id_2>",
"name": "Preferred Contact Method",
"fieldKey": "contact.preferred_contact_method",
"dataType": "SINGLE_OPTIONS",
"position": 1,
"picklistOptions": ["Email", "Phone", "SMS"],
"picklistImageOptions": [],
"isAllowedCustomOption": false,
"locationId": "<location_id>",
"model": "contact"
}
]
}

Each field also returns the settings that apply to its type. Choice fields return picklistOptions, picklistImageOptions, and isAllowedCustomOption. File fields return isMultiFileAllowed and maxFileLimit. Fields with validation or display settings return urlValidation, dateTimeValidation, userFieldConfig, or optionDisplayType, described under Data types and settings.

GET/locations/{locationId}/customFields/{id}

Get one custom field by ID or field key.

scope locations/customFields.readonlyauth Location token or PIT

id can be the field’s ID or its field key, such as contact.referral_source.

Terminal window
curl https://services.smbcrm.com/locations/<location_id>/customFields/<field_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"customField": {
"id": "<field_id>",
"name": "Referral Source",
"fieldKey": "contact.referral_source",
"placeholder": "Where did they hear about us?",
"dataType": "TEXT",
"position": 0,
"locationId": "<location_id>",
"model": "contact"
}
}
POST/locations/{locationId}/customFields

Create a custom field for contacts or opportunities.

scope locations/customFields.writeauth Location token or PIT

name and dataType are required. All other properties are optional.

Property Type Description
name string Display name of the field. Required.
dataType string One of the data types. Required.
model string contact or opportunity.
placeholder string Placeholder text shown in the field.
position number Position of the field in the list. Defaults to 0.
acceptedFormat array of strings File extensions a FILE_UPLOAD field accepts, such as .pdf, .docx, and .jpeg.
isMultipleFile boolean Whether a FILE_UPLOAD field takes more than one file.
maxNumberOfFiles number Maximum number of files for a FILE_UPLOAD field.
textBoxListOptions array Entries for a TEXTBOX_LIST field, each as { label, prefillValue }.
urlValidation object URL rules. Required when dataType is URL.
dateTimeValidation object Date and time rules. Required for TIME and DATE_TIME, optional for DATE.
userFieldConfig object User field settings. Required when dataType is USER.
optionDisplayType string How RADIO and CHECKBOX options render. Defaults to TEXT_ONLY.
Terminal window
curl -X POST https://services.smbcrm.com/locations/<location_id>/customFields \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"name": "Referral Source",
"dataType": "TEXT",
"model": "contact",
"placeholder": "Where did they hear about us?"
}'
201 Created
{
"customField": {
"id": "<field_id>",
"name": "Referral Source",
"fieldKey": "contact.referral_source",
"placeholder": "Where did they hear about us?",
"dataType": "TEXT",
"position": 0,
"locationId": "<location_id>",
"model": "contact"
}
}
PUT/locations/{locationId}/customFields/{id}

Update a custom field (body: name).

scope locations/customFields.writeauth Location token or PIT

name is required. You can also send placeholder, position, model, acceptedFormat, isMultipleFile, maxNumberOfFiles, textBoxListOptions, urlValidation, dateTimeValidation, userFieldConfig, and optionDisplayType. You can’t change a field’s dataType after you create it. A urlValidation or dateTimeValidation object you send replaces the existing rules, and multiSelect in userFieldConfig can’t change.

Terminal window
curl -X PUT https://services.smbcrm.com/locations/<location_id>/customFields/<field_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"name": "Referral Source",
"placeholder": "How did they find us?"
}'
200 OK
{
"customField": {
"id": "<field_id>",
"name": "Referral Source",
"fieldKey": "contact.referral_source",
"placeholder": "How did they find us?",
"dataType": "TEXT",
"position": 0,
"locationId": "<location_id>",
"model": "contact"
}
}
DELETE/locations/{locationId}/customFields/{id}

Delete a custom field.

scope locations/customFields.writeauth Location token or PIT
Terminal window
curl -X DELETE https://services.smbcrm.com/locations/<location_id>/customFields/<field_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{ "succeded": true }

The response uses the API’s own spelling, succeded, not succeeded.

dataType is one of TEXT, LARGE_TEXT, NUMERICAL, PHONE, MONETORY (the API’s own spelling), CHECKBOX, SINGLE_OPTIONS, MULTIPLE_OPTIONS, FLOAT, DATE, TEXTBOX_LIST, FILE_UPLOAD, SIGNATURE, or RADIO. The types URL, USER, TIME, DATE_TIME, and RICH_TEXT are Labs-only for now.

Required when dataType is URL. On update, the object you send replaces the existing rules.

Property Type Description
mode string allow_all accepts any URL, allow_only accepts only the allowedDomains, and block accepts anything except the blockedDomains.
allowedDomains array of strings Domains accepted when mode is allow_only.
blockedDomains array of strings Domains rejected when mode is block.

Required for TIME and DATE_TIME fields, and optional for DATE. On update, the object you send replaces the existing rules.

Property Type Description
mode string any allows any value, future_only requires a future value, past_only requires a past value, and range requires a value between rangeMin and rangeMax.
bufferDays number With future_only: the minimum number of days from today before a date can be selected.
rollingDays number With future_only: a rolling window in days from today, so 30 means the next 30 days. Can’t be combined with bufferDays.
rangeMin string An ISO date or datetime string. Required when mode is range.
rangeMax string An ISO date or datetime string. Required when mode is range.
daysAllowed array of numbers Days of the week that can be selected, from 0 (Sunday) to 6 (Saturday). Works with future_only, past_only, and range.
inputType string For DATE_TIME fields: date_only, time_only, or date_and_time.
{
"dateTimeValidation": {
"mode": "future_only",
"bufferDays": 2,
"daysAllowed": [1, 2, 3, 4, 5]
}
}

Required when dataType is USER. It has one property, multiSelect (boolean), which sets whether the field is single-select or multi-select. You can’t change multiSelect after you create the field.

Sets how options render on RADIO and CHECKBOX fields: TEXT_ONLY, TEXT_WITH_ICON, or TEXT_WITH_IMAGE. New fields default to TEXT_ONLY.

POST/locations/{locationId}/customFields/upload

Upload files for a FILE_UPLOAD custom field.

scope locations/customFields.writeauth Location token or PIT

Send the request as multipart/form-data with these form parts.

Part Description
id The ID of the contact, opportunity, or custom field the files belong to.
maxFiles The maximum number of files, as a string.

Send each file as its own part, named after the file.

Terminal window
curl -X POST https://services.smbcrm.com/locations/<location_id>/customFields/upload \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-F "id=<contact_id>" \
-F "maxFiles=2" \
-F "report.csv=@report.csv"

uploadedFiles maps each file name to its URL, and meta lists the details of each upload.

200 OK
{
"uploadedFiles": {
"report.csv": "<file_url>"
},
"meta": [
{
"fieldname": "report.csv",
"originalname": "report.csv",
"encoding": "7bit",
"mimetype": "text/csv",
"size": 2061,
"url": "<file_url>"
}
]
}

The /custom-fields/ endpoints manage fields on custom objects and on Company (Business) records. For contact and opportunity fields, use the endpoints above. Fields can sit in folders, and you create and manage those folders with the folder endpoints below. See Custom Objects for the object schemas and records these fields belong to.

GET/custom-fields/object-key/{objectKey}

List the custom fields and folders defined for an object.

scope locations/customFields.readonlyauth Location token or PIT

locationId is a required query parameter. The response has two arrays: fields holds the object’s fields and folders holds its folders. Each folder includes id, locationId, name, and objectKey.

Terminal window
curl "https://services.smbcrm.com/custom-fields/object-key/custom_objects.pet?locationId=<location_id>" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"fields": [
{
"id": "<field_id>",
"locationId": "<location_id>",
"name": "Name",
"fieldKey": "custom_object.pet.name",
"dataType": "TEXT",
"objectKey": "custom_object.pet",
"parentId": "<folder_id>",
"showInForms": true,
"dateAdded": "2026-10-08T15:04:00.000Z",
"dateUpdated": "2026-10-08T15:04:00.000Z"
},
{
"id": "<field_id_2>",
"locationId": "<location_id>",
"name": "Temperament",
"fieldKey": "custom_object.pet.temperament",
"dataType": "SINGLE_OPTIONS",
"objectKey": "custom_object.pet",
"parentId": "<folder_id>",
"showInForms": true,
"options": [
{ "key": "calm", "label": "Calm" },
{ "key": "playful", "label": "Playful" },
{ "key": "shy", "label": "Shy" }
],
"dateAdded": "2026-10-08T15:04:00.000Z",
"dateUpdated": "2026-10-08T15:04:00.000Z"
}
],
"folders": [
{
"id": "<folder_id>",
"locationId": "<location_id>",
"name": "Pet details",
"objectKey": "custom_object.pet"
}
]
}
GET/custom-fields/{id}

Get one custom field or folder by ID.

scope locations/customFields.readonlyauth Location token or PIT
Terminal window
curl https://services.smbcrm.com/custom-fields/<field_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"field": {
"id": "<field_id>",
"locationId": "<location_id>",
"name": "Name",
"fieldKey": "custom_object.pet.name",
"dataType": "TEXT",
"objectKey": "custom_object.pet",
"parentId": "<folder_id>",
"showInForms": true,
"dateAdded": "2026-10-08T15:04:00.000Z",
"dateUpdated": "2026-10-08T15:04:00.000Z"
}
}
POST/custom-fields/

Create a custom field (body: locationId, dataType, fieldKey, objectKey, parentId, showInForms).

scope locations/customFields.writeauth Location token or PIT

Send locationId, dataType, fieldKey, objectKey, parentId, and showInForms. All six are required. parentId is the ID of the folder the field goes in. Folder IDs come from the folders array when you list an object’s fields, or from creating a folder.

dataType is one of TEXT, LARGE_TEXT, NUMERICAL, PHONE, MONETORY (the API’s own spelling), CHECKBOX, SINGLE_OPTIONS, MULTIPLE_OPTIONS, DATE, TEXTBOX_LIST, FILE_UPLOAD, RADIO, or EMAIL.

Property Type Description
name string Display name of the field.
description string Description of the field.
placeholder string Placeholder text shown in the field.
options array Choices for SINGLE_OPTIONS, MULTIPLE_OPTIONS, RADIO, CHECKBOX, and TEXTBOX_LIST fields. Each option is { key, label }, and key and label are both required. Other data types don’t use it.
options[].url string Optional. Valid only on RADIO options.
allowCustomOption boolean For RADIO fields: lets users enter a value that isn’t one of the predefined options. A custom value entered on one record doesn’t become an option on other records.
acceptedFormats string For FILE_UPLOAD fields: one of .pdf, .docx, .doc, .jpg, .jpeg, .png, .gif, .csv, .xlsx, .xls, or all.
maxFileLimit number For FILE_UPLOAD fields: the maximum number of files.
Terminal window
curl -X POST https://services.smbcrm.com/custom-fields/ \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"locationId": "<location_id>",
"name": "Temperament",
"dataType": "SINGLE_OPTIONS",
"fieldKey": "custom_object.pet.temperament",
"objectKey": "custom_object.pet",
"parentId": "<folder_id>",
"showInForms": true,
"options": [
{ "key": "calm", "label": "Calm" },
{ "key": "playful", "label": "Playful" },
{ "key": "shy", "label": "Shy" }
]
}'

To create a file field, send acceptedFormats and maxFileLimit instead of options:

Terminal window
curl -X POST https://services.smbcrm.com/custom-fields/ \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"locationId": "<location_id>",
"name": "Vaccination Records",
"dataType": "FILE_UPLOAD",
"fieldKey": "custom_object.pet.vaccination_records",
"objectKey": "custom_object.pet",
"parentId": "<folder_id>",
"showInForms": true,
"acceptedFormats": ".pdf",
"maxFileLimit": 2
}'
201 Created
{
"field": {
"id": "<field_id>",
"locationId": "<location_id>",
"name": "Temperament",
"fieldKey": "custom_object.pet.temperament",
"dataType": "SINGLE_OPTIONS",
"objectKey": "custom_object.pet",
"parentId": "<folder_id>",
"showInForms": true,
"options": [
{ "key": "calm", "label": "Calm" },
{ "key": "playful", "label": "Playful" },
{ "key": "shy", "label": "Shy" }
],
"dateAdded": "2026-10-08T15:04:00.000Z",
"dateUpdated": "2026-10-08T15:04:00.000Z"
}
}
PUT/custom-fields/{id}

Update a custom field (body: locationId, showInForms).

scope locations/customFields.writeauth Location token or PIT

locationId and showInForms are required. You can also send name, description, placeholder, options, acceptedFormats, and maxFileLimit. dataType, fieldKey, objectKey, and parentId can’t be changed after creation.

Sending options replaces the whole array, so include every existing option along with any new ones. You can’t remove options through an update. Each option needs a key and a label.

Terminal window
curl -X PUT https://services.smbcrm.com/custom-fields/<field_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"locationId": "<location_id>",
"name": "Temperament",
"showInForms": true,
"options": [
{ "key": "calm", "label": "Calm" },
{ "key": "playful", "label": "Playful" },
{ "key": "shy", "label": "Shy" },
{ "key": "anxious", "label": "Anxious" }
]
}'
200 OK
{
"field": {
"id": "<field_id>",
"locationId": "<location_id>",
"name": "Temperament",
"fieldKey": "custom_object.pet.temperament",
"dataType": "SINGLE_OPTIONS",
"objectKey": "custom_object.pet",
"parentId": "<folder_id>",
"showInForms": true,
"options": [
{ "key": "calm", "label": "Calm" },
{ "key": "playful", "label": "Playful" },
{ "key": "shy", "label": "Shy" },
{ "key": "anxious", "label": "Anxious" }
],
"dateAdded": "2026-10-08T15:04:00.000Z",
"dateUpdated": "2026-10-08T16:20:00.000Z"
}
}
DELETE/custom-fields/{id}

Delete a custom field.

scope locations/customFields.writeauth Location token or PIT
Terminal window
curl -X DELETE https://services.smbcrm.com/custom-fields/<field_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{ "succeded": true, "id": "<field_id>", "key": "custom_object.pet.temperament" }

The response uses the API’s own spelling, succeded, not succeeded.

Folders group an object’s fields in your custom field settings. A field’s parentId is the ID of its folder.

POST/custom-fields/folder

Create a folder for an object's custom fields (body: objectKey, name, locationId).

scope locations/customFields.writeauth Location token or PIT

objectKey, name, and locationId are all required.

Terminal window
curl -X POST https://services.smbcrm.com/custom-fields/folder \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"objectKey": "custom_object.pet",
"name": "Pet details",
"locationId": "<location_id>"
}'
201 Created
{
"id": "<folder_id>",
"objectKey": "custom_object.pet",
"locationId": "<location_id>",
"name": "Pet details"
}
PUT/custom-fields/folder/{id}

Rename a folder (body: name, locationId).

scope locations/customFields.writeauth Location token or PIT

name and locationId are both required.

Terminal window
curl -X PUT https://services.smbcrm.com/custom-fields/folder/<folder_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"name": "Pet profile",
"locationId": "<location_id>"
}'
200 OK
{
"id": "<folder_id>",
"objectKey": "custom_object.pet",
"locationId": "<location_id>",
"name": "Pet profile"
}
DELETE/custom-fields/folder/{id}

Delete a folder.

scope locations/customFields.writeauth Location token or PIT

locationId is a required query parameter.

Terminal window
curl -X DELETE "https://services.smbcrm.com/custom-fields/folder/<folder_id>?locationId=<location_id>" \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{ "succeded": true, "id": "<folder_id>", "key": "<folder_key>" }

The response uses the API’s own spelling, succeded, not succeeded.

Custom values are named snippets you define once in your account and reuse by name across templates and messages. Typical examples are a business phone number, a support email address, or a shipping cutoff time. Each custom value’s fieldKey is its merge tag, in the form {{ custom_values.business_phone }}.

GET/locations/{locationId}/customValues

List custom values.

scope locations/customValues.readonlyauth Location token or PIT
Terminal window
curl https://services.smbcrm.com/locations/<location_id>/customValues \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"customValues": [
{
"id": "<value_id>",
"name": "Business Phone",
"fieldKey": "{{ custom_values.business_phone }}",
"value": "+15125550100",
"locationId": "<location_id>"
},
{
"id": "<value_id_2>",
"name": "Support Email",
"fieldKey": "{{ custom_values.support_email }}",
"value": "support@example.com",
"locationId": "<location_id>"
}
]
}
GET/locations/{locationId}/customValues/{id}

Get one custom value.

scope locations/customValues.readonlyauth Location token or PIT
Terminal window
curl https://services.smbcrm.com/locations/<location_id>/customValues/<value_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"customValue": {
"id": "<value_id>",
"name": "Business Phone",
"fieldKey": "{{ custom_values.business_phone }}",
"value": "+15125550100",
"locationId": "<location_id>"
}
}
POST/locations/{locationId}/customValues

Create a custom value (body: name, value).

scope locations/customValues.writeauth Location token or PIT
Terminal window
curl -X POST https://services.smbcrm.com/locations/<location_id>/customValues \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{
"name": "Business Phone",
"value": "+15125550100"
}'
201 Created
{
"customValue": {
"id": "<value_id>",
"name": "Business Phone",
"fieldKey": "{{ custom_values.business_phone }}",
"value": "+15125550100",
"locationId": "<location_id>"
}
}
PUT/locations/{locationId}/customValues/{id}

Update a custom value (body: name, value).

scope locations/customValues.writeauth Location token or PIT

Both name and value are required. This endpoint replaces the whole custom value instead of patching a single field.

Terminal window
curl -X PUT https://services.smbcrm.com/locations/<location_id>/customValues/<value_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{ "name": "Business Phone", "value": "+15125550199" }'
200 OK
{
"customValue": {
"id": "<value_id>",
"name": "Business Phone",
"fieldKey": "{{ custom_values.business_phone }}",
"value": "+15125550199",
"locationId": "<location_id>"
}
}
DELETE/locations/{locationId}/customValues/{id}

Delete a custom value.

scope locations/customValues.writeauth Location token or PIT
Terminal window
curl -X DELETE https://services.smbcrm.com/locations/<location_id>/customValues/<value_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{ "succeded": true }

The response uses the API’s own spelling, succeded, not succeeded.

Tags are short labels you attach to contacts to segment lists and trigger automations. This section manages the tag definitions for your account; to add or remove a tag on a specific contact, use the tag endpoints on the Contacts API instead.

GET/locations/{locationId}/tags

List tags.

scope locations/tags.readonlyauth Location token or PIT
Terminal window
curl https://services.smbcrm.com/locations/<location_id>/tags \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"tags": [
{ "id": "<tag_id>", "name": "website-lead", "locationId": "<location_id>" },
{ "id": "<tag_id_2>", "name": "vip", "locationId": "<location_id>" }
]
}
GET/locations/{locationId}/tags/{tagId}

Get one tag.

scope locations/tags.readonlyauth Location token or PIT
Terminal window
curl https://services.smbcrm.com/locations/<location_id>/tags/<tag_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{
"tag": { "id": "<tag_id>", "name": "website-lead", "locationId": "<location_id>" }
}
POST/locations/{locationId}/tags

Create a tag (body: name).

scope locations/tags.writeauth Location token or PIT

This endpoint returns 200, unlike the custom value and custom field create endpoints, which return 201. Check for any 2xx status in your client.

Terminal window
curl -X POST https://services.smbcrm.com/locations/<location_id>/tags \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{ "name": "webinar-2026" }'
200 OK
{
"tag": { "id": "<tag_id>", "name": "webinar-2026", "locationId": "<location_id>" }
}
PUT/locations/{locationId}/tags/{tagId}

Update a tag (body: name).

scope locations/tags.writeauth Location token or PIT
Terminal window
curl -X PUT https://services.smbcrm.com/locations/<location_id>/tags/<tag_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3" \
-H "Content-Type: application/json" \
-d '{ "name": "webinar-2026-replay" }'
200 OK
{
"tag": { "id": "<tag_id>", "name": "webinar-2026-replay", "locationId": "<location_id>" }
}
DELETE/locations/{locationId}/tags/{tagId}

Delete a tag.

scope locations/tags.writeauth Location token or PIT
Terminal window
curl -X DELETE https://services.smbcrm.com/locations/<location_id>/tags/<tag_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"
200 OK
{ "succeded": true }

The response uses the API’s own spelling, succeded, not succeeded.

  • Contacts: the customFields array you send when creating or updating a contact matches the fields you define here, and contacts carry the tags you define here.
  • Custom Objects: the custom object schemas and records that the custom object fields belong to.
  • Locations: other account-level settings for your SMBcrm location.
  • Scopes: the full list of scopes your token can request.
  • Errors & Troubleshooting: status codes and error response shapes.