GoHighLevel Contacts API
Upsert Contact
/contacts/upsertPOST /contacts/upsert If the setting is configured to check both Email and Phone, the API will attempt to identify an existing contact based on the priority sequence specified in the setting, and will create or update the contact accordingly. If two separate contacts already exist—one with the same email and another with the same phone—and an upsert request includes both the email and phone, the API will update the contact that matches the first field in the configured sequence, and ignore the second field to prevent duplication It takes 51 body fields, requires the contacts.write scope and authenticates with a sub-account (location) token.
Request and authentication
- Method
POST- Full URL
https://services.leadconnectorhq.com/contacts/upsert- Scopes
contacts.write- Token type
- Sub-account (location) token
- Accepted auth
- OAuth Access Token, Private Integration Token
- API version header
Version: 2021-07-28- Schema verified
- 22 June 2026
Notes from the field
- For multi-contact imports, use the `hylo_bulk_upsert_contacts` MCP tool — one call instead of N round-trips.
- Pass `tags` inline here to skip a follow-up add-tags call (saves 1 round-trip per contact).
- Pass `customFields` inline here to skip per-field update-contact-field calls.
This endpoint is safe to fan out in parallel, so a batch of records costs roughly one round trip instead of one per record. Hylo's bulk tools do that server-side and retry HighLevel's 429s with back-off.
Request body
JSON body fields. Nested objects are shown indented under their parent.
| Name | Type | Description |
|---|---|---|
firstName | string | Example: |
lastName | string | Example: |
name | string | Example: |
email | string | Example: |
locationIdrequired | string | Example: |
gender | string | Example: |
phone | string | Example: |
address1 | string | Example: |
city | string | Example: |
state | string | Example: |
postalCode | string | Example: |
website | string | Example: |
timezone | string | Example: |
dnd | boolean | Example: |
dndSettings | object | — |
Call | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
Email | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
SMS | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
WhatsApp | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
GMB | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
FB | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
inboundDndSettings | object | — |
all | object | — |
statusrequired | string | One of: |
message | string | — |
tags | array | This field will overwrite all current tags associated with the contact. To update a tags, it is recommended to use the Add Tag or Remove Tag API instead. Example: |
customFields | array | — |
source | string | Example: |
dateOfBirth | object | The birth date of the contact. Supported formats: YYYY/MM/DD, MM/DD/YYYY, YYYY-MM-DD, MM-DD-YYYY, YYYY.MM.DD, MM.DD.YYYY, YYYY_MM_DD, MM_DD_YYYY Example: |
country | string | Example: |
companyName | string | Example: |
assignedTo | string | User's Id Example: |
createNewIfDuplicateAllowed | boolean | Controls whether to create a new contact or update an existing duplicate. Scenario 1: If this value is true and the location allows duplicate contacts, a new contact will be created immediately without checking for duplicates. Scenario 2: If this value is true but the location does not allow duplicate contacts, this field is ignored and the normal upsert behavior applies: the API will search for an existing duplicate contact, update it if found, or create a new contact if not found. Scenario 3: If this value is false or not provided, the normal upsert behavior applies regardless of the location's duplicate contact setting. Example: |
Response fields
Top-level fields returned on a successful call.
| Name | Type | Description |
|---|---|---|
new | boolean | Example: |
contact | object | — |
id | string | Example: |
name | string | Example: |
locationId | string | Example: |
firstName | string | Example: |
lastName | string | Example: |
email | string | Example: |
emailLowerCase | string | Example: |
timezone | string | Example: |
companyName | string | Example: |
phone | string | Example: |
dnd | boolean | Example: |
dndSettings | object | — |
Call | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
Email | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
SMS | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
WhatsApp | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
GMB | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
FB | object | — |
statusrequired | string | One of: |
message | string | — |
code | string | — |
type | string | Example: |
source | string | Example: |
assignedTo | string | Example: |
address1 | string | Example: |
city | string | Example: |
state | string | Example: |
country | string | Example: |
postalCode | string | Example: |
website | string | Example: |
tags | array | Example: |
dateOfBirth | string | Example: |
dateAdded | string | Example: |
dateUpdated | string | Example: |
traceId | string | — |
Example request
Copy-paste ready. Swap YOUR_TOKEN for your access token or Private Integration Token.
curl -X POST 'https://services.leadconnectorhq.com/contacts/upsert' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Version: 2021-07-28' \
-H 'Content-Type: application/json' \
-d '{
"locationId": "ve9EPM428h8vShlRW1KT"
}'Skip the schema lookup
Hylo gives your AI agent this schema — and the other 52 documented here — without you looking anything up. Ask in plain English; it picks the endpoint, fills the body, and can run the call against your own sub-account.
More contacts endpoints
- Add Followers ContactPOST /contacts/:contactId/followers
- Add Remove Contact From BusinessPOST /contacts/bulk/business
- Add TagsPOST /contacts/:contactId/tags
- Create AssociationPOST /contacts/bulk/tags/update/:type
- Create ContactPOST /contacts/
- Create NotePOST /contacts/:contactId/notes
- All GoHighLevel Contacts endpointsCategory index
- GoHighLevel API referenceEvery category, webhooks, and OAuth scopes