Custom fields
The custom field definitions of a workspace: the keys in a contact's `custom_fields`, their labels, types and options.
The custom field definitions of a workspace: the keys in a contact's custom_fields, their labels, types and options.
Every route takes Authorization: Bearer <ACCESS_TOKEN> unless the auth line says otherwise. Ids are numbers. Errors use the shape on the errors page.
| Route | Scope | What it does |
|---|---|---|
GET /v1/custom-fields | contacts.read | A workspace's custom field definitions, in display order. |
POST /v1/custom-fields | contacts.write | Define a custom field for a workspace. |
PATCH /v1/custom-fields/{id} | contacts.write | Change a custom field's label, type, options, required flag or order. |
DELETE /v1/custom-fields/{id} | contacts.write | Remove a custom field definition. |
List custom fields
GET https://api.bluereacher.com/v1/custom-fieldsAuth: Bearer access token. Scope: contacts.read.
A workspace's custom field definitions, in display order.
A definition is the key under which a value sits in a contact's custom_fields ({ "lead_source": "Referral" }), its label, its type and, for select / multi_select, the allowed options. Typed definitions are enforced when a contact is created or updated: a value that is not a valid number, date (YYYY-MM-DD), URL, email, phone or option is refused there. options is null for every type but select and multi_select.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspace_id | query | number | yes | The workspace. |
Request
curl -X GET "https://api.bluereacher.com/v1/custom-fields?workspace_id=7" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Responses
A 200 reply (OK):
{
"success": true,
"data": [
{
"id": 41,
"workspace_id": 7,
"field_key": "lead_source",
"field_label": "Lead Source",
"field_type": "select",
"options": [
"Web",
"Referral",
"Event"
],
"is_required": false,
"sort_order": 1,
"created_at": "2026-11-04T02:20:00.000Z",
"updated_at": "2026-11-04T02:20:00.000Z"
},
{
"id": 42,
"workspace_id": 7,
"field_key": "deal_size",
"field_label": "Deal Size",
"field_type": "number",
"options": null,
"is_required": false,
"sort_order": 2,
"created_at": "2026-11-04T02:21:00.000Z",
"updated_at": "2026-11-04T02:21:00.000Z"
}
]
}| Status | When | Message |
|---|---|---|
| 200 | OK | |
| 400 | No workspace_id | workspace_id is required. |
| 401 | Missing or invalid token | Invalid or expired access token. |
| 403 | Missing scope | Missing scope(s): contacts.read. This integration was granted: … |
| 404 | Workspace does not exist or is not owned by the installer (same response for both) | Workspace not found or not accessible to this token |
Create custom field
POST https://api.bluereacher.com/v1/custom-fieldsAuth: Bearer access token. Scope: contacts.write.
Define a custom field for a workspace.
Leave field_key out to have it made from the label (Lead Source → lead_source); a key you pass is lower-cased and anything but letters, digits and _ becomes _. Keys are unique per workspace: a taken key answers 409 (update it with Update custom field instead). select and multi_select need options. Writing a value under a brand-new key on a contact also creates a text definition for it, so this call is for fields that need a type, options, a label or an order up front.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspace_id | body | number | yes | The workspace. |
field_label | body | string | yes | Shown in the dashboard. Up to 100 characters. |
field_type | body | enum | yes | How values are validated and shown. |
field_key | body | string | no | The key in custom_fields. Letters, digits and _, up to 50 characters. Default: made from the label. |
options | body | array<string> | no | The choices (required for select / multi_select; up to 100, 100 characters each). Ignored for other types. |
is_required | body | boolean | no | Marks the field required in the dashboard. Default false. |
sort_order | body | number | no | Display position, lowest first. Default 0. |
Request
curl -X POST "https://api.bluereacher.com/v1/custom-fields" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"workspace_id": 7,
"field_label": "Lead Source",
"field_type": "select",
"options": [
"Web",
"Referral",
"Event"
],
"sort_order": 1
}'Responses
A 201 reply (Created):
{
"success": true,
"message": "Custom field created",
"data": {
"id": 41,
"workspace_id": 7,
"field_key": "lead_source",
"field_label": "Lead Source",
"field_type": "select",
"options": [
"Web",
"Referral",
"Event"
],
"is_required": false,
"sort_order": 1,
"created_at": "2026-11-04T02:20:00.000Z",
"updated_at": "2026-11-04T02:20:00.000Z"
}
}| Status | When | Message |
|---|---|---|
| 201 | Created | |
| 400 | Missing label or type, bad type, or a select without options | options is required for a select field — an array of choices. |
| 401 | Missing or invalid token | Invalid or expired access token. |
| 403 | Missing scope | Missing scope(s): contacts.write. This integration was granted: … |
| 404 | Workspace does not exist or is not owned by the installer (same response for both) | Workspace not found or not accessible to this token |
| 409 | The key is taken | A custom field with key "lead_source" already exists in this workspace. Update it with PATCH /custom-fields/41. |
Update custom field
PATCH https://api.bluereacher.com/v1/custom-fields/{id}Auth: Bearer access token. Scope: contacts.write.
Change a custom field's label, type, options, required flag or order.
Send only what changes. The key never changes, because the values on contacts sit under it — delete the field and create another to rename a key. Switching to select / multi_select needs options in the same call (or already on the field); switching away clears them. Values already on contacts are not rewritten; they are validated against the new type the next time a contact is updated.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | number | yes | The field id. |
field_label | body | string | no | Up to 100 characters. |
field_type | body | enum | no | The new type. |
options | body | array<string> | no | Replaces the choices of a select / multi_select field. |
is_required | body | boolean | no | true / false. |
sort_order | body | number | no | Display position. |
Request
curl -X PATCH "https://api.bluereacher.com/v1/custom-fields/41" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"field_label": "Source",
"options": [
"Web",
"Referral",
"Event",
"Partner"
]
}'Responses
A 200 reply (OK):
{
"success": true,
"message": "Custom field updated",
"data": {
"id": 41,
"workspace_id": 7,
"field_key": "lead_source",
"field_label": "Source",
"field_type": "select",
"options": [
"Web",
"Referral",
"Event",
"Partner"
],
"is_required": false,
"sort_order": 1,
"created_at": "2026-11-04T02:20:00.000Z",
"updated_at": "2026-11-04T03:05:00.000Z"
}
}| Status | When | Message |
|---|---|---|
| 200 | OK | |
| 400 | Nothing to change, a key change, a bad type, or a select without options | field_key cannot be changed — delete the field and create another. |
| 401 | Missing or invalid token | Invalid or expired access token. |
| 403 | Missing scope | Missing scope(s): contacts.write. This integration was granted: … |
| 404 | Custom field does not exist or is not owned by the installer (same response for both) | Custom field not found or not accessible to this token |
Delete custom field
DELETE https://api.bluereacher.com/v1/custom-fields/{id}Auth: Bearer access token. Scope: contacts.write.
Remove a custom field definition.
Values already stored under the key stay on the contacts; they just stop being validated, shown and offered in filters. Writing the key on a contact again recreates a text definition.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | number | yes | The field id. |
Request
curl -X DELETE "https://api.bluereacher.com/v1/custom-fields/41" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Responses
A 200 reply (OK):
{
"success": true,
"message": "Custom field deleted",
"data": {
"id": 41,
"workspace_id": 7,
"field_key": "lead_source"
}
}| Status | When | Message |
|---|---|---|
| 200 | OK | |
| 401 | Missing or invalid token | Invalid or expired access token. |
| 403 | Missing scope | Missing scope(s): contacts.write. This integration was granted: … |
| 404 | Custom field does not exist or is not owned by the installer (same response for both) | Custom field not found or not accessible to this token |

