Custom Fields V2 Setup
Manage custom fields with the V2 API for enhanced field types, object-key scoping, and folder organization. This guide walks you through creating, reading, updating, and deleting custom fields across contacts, opportunities, and custom objects.
Prerequisites
Before working with Custom Fields V2, confirm you have:
- A GoHighLevel sub-account with access to custom field management
- Your
locationIdfrom Settings > Business Profile - Knowledge of which object you want to add fields to (e.g.,
contact,opportunity, or a custom object key) - A Private Integration Token (PIT) with the
custom-fieldsscope - A REST client such as Postman, Insomnia, or
curl
Set Up Authentication
Custom Fields V2 endpoints require a PIT with the custom-fields scope. This is separate from the custom-objects scope used for schemas and records.
- Go to Settings > Integrations > Private Integrations
- Create or edit an integration and enable the
custom-fieldsscope with read and write permissions - Click Save and copy the generated token
export GHL_TOKEN="your-private-integration-token"
export LOCATION_ID="your-location-id"
Base URL: https://services.leadconnectorhq.com. Include these headers:
Authorization: Bearer $GHL_TOKEN
Content-Type: application/json
Version: 2021-07-28
Make Your First Call
Create a custom field by sending a POST to /custom-fields:
curl -X POST "https://services.leadconnectorhq.com/custom-fields" \
-H "Authorization: Bearer $GHL_TOKEN" \
-H "Content-Type: application/json" \
-H "Version: 2021-07-28" \
-d '{
"locationId": "'"$LOCATION_ID"'",
"objectKey": "contact",
"name": "Preferred Language",
"dataType": "TEXT",
"placeholder": "e.g., English, Spanish",
"folderId": "optional-folder-id"
}'
The objectKey parameter scopes the field to a specific object. Use contact for contact fields, opportunity for deal fields, or any custom object key. Supported dataType values include TEXT, NUMERICAL, PHONE, EMAIL, DATE, SINGLE_OPTIONS, MULTIPLE_OPTIONS, FILE_UPLOAD, and TEXTAREA.
Read a field with GET /custom-fields/{fieldId}. Update with PUT /custom-fields/{fieldId}. Delete with DELETE /custom-fields/{fieldId}. List all fields for an object with GET /custom-fields/object/{objectKey}.
Handle the Response
A successful POST /custom-fields returns the new field definition:
{
"customField": {
"id": "cf_abc123",
"locationId": "your-location-id",
"objectKey": "contact",
"name": "Preferred Language",
"fieldKey": "contact.preferred_language",
"dataType": "TEXT",
"placeholder": "e.g., English, Spanish",
"folderId": null
}
}
The fieldKey is auto-generated from the object key and field name. Use this key when setting values on records. The id is needed for update and delete operations.
Common errors: 400 means a required parameter like name or dataType is missing. 401 indicates an invalid token or missing custom-fields scope. 409 means a field with that name already exists on the target object. 404 on object-scoped queries means the objectKey is invalid.
Test Your Setup
Verify your custom fields integration end to end:
- Create a test field on the
contactobject withPOST /custom-fields - Read it back with
GET /custom-fields/{fieldId}and verify the definition - List by object with
GET /custom-fields/object/contactand confirm your field appears - Update the field with
PUT /custom-fields/{fieldId}, changing theplaceholdervalue - Delete the test field with
DELETE /custom-fields/{fieldId}and verify it no longer appears in the object listing
If the field does not appear on contact records in the GHL UI, confirm the objectKey matches and allow a few seconds for the UI to sync.
Next Steps
Read the full Custom Fields V2 guide for advanced patterns including dropdown option management and field ordering. Set up Field Folders to organize your fields into logical groups, or explore Object Schema CRUD to define entirely new objects with built-in field definitions.