Skip to main content
This document covers gohighlevel_create_note and the custom_fields support added to the GoHighLevel contact and opportunity write tools.

Authentication

GoHighLevel tools use the existing GoHighLevel connector. Both values are resolved from the integration row and injected from the connector:
  • private_token — GoHighLevel Private Integration Token
  • location_id — sub-account location id (only needed by tools whose endpoint requires it)

gohighlevel_create_note

Adds a timeline note to a GoHighLevel contact via POST /contacts/{contactId}/notes. This is a mutating tool. GoHighLevel scopes notes to the contact — there is no opportunity-scoped note endpoint, so you always pass a contact id. To make a note attributable to one opportunity, also pass opportunity_id. The tool sends it as a relations entry (objectKey: "opportunity"). Without it, a contact holding two opportunities shows the same undifferentiated note on both — so supply it whenever the note is about a particular opportunity. relations is absent from GoHighLevel’s published v2 note schema but is the real mechanism: notes read back from a live location carry relations: [{"objectKey": "opportunity", "recordId": "..."}] (verified 2026-08-03). The tool reports the link GoHighLevel actually recorded, not the one requested — opportunity_linked is false and the summary says “not confirmed” if the relation is missing from the response, so a future API change surfaces instead of passing as a clean success.

Inputs

Required:
  • contact_id: Id of the contact to annotate. Look it up with gohighlevel_search_contacts, or take it from an opportunity.
  • body: Note text. Plain text; newlines are preserved. Whitespace-only bodies are rejected rather than creating an empty timeline entry.
Optional:
  • user_id: GoHighLevel user id to attribute the note to.
  • opportunity_id: Opportunity to link the note to. Omitted entirely from the request when absent, rather than sent as an empty array.

Output

Structured content includes note_id and the full note object. When opportunity_id was supplied it also carries opportunity_linked (bool) and linked_opportunity_id, read back from the created note’s relations. The markdown summary truncates the body at 120 characters (counted in runes); the full text stays in the structured payload.

Notes

  • There is no idempotency. Calling twice creates two notes. Prefer one note per distinct event.

custom_fields on contact and opportunity writes

gohighlevel_create_contact, gohighlevel_update_contact, gohighlevel_create_opportunity and gohighlevel_update_opportunity all accept an optional custom_fields array:
Each entry needs either id or key, plus a value passed as a string (a numeric or boolean field takes its value in string form, e.g. "42" or "true" — the input schema declares value as string). Fields you omit are not included in the write; whether GoHighLevel merges or replaces the resource’s other custom fields on update has not been verified live — confirm before relying on a partial custom_fields update to preserve values you didn’t send. An entry with neither id nor key, or with no value, is rejected with an error naming the offending index — a silently skipped field would look like a successful write that never landed. Validation runs before any HTTP call, so malformed input doesn’t cost a round trip or a partial write. gohighlevel_create_contact and gohighlevel_update_contact also expose the address fields the API already supported: address1, city, state, postal_code, country. The field_value wire key is verified against a live location (2026-08-03): a contact written with customFields: [{id, field_value}] echoed back fieldValue and read back value carrying the written value. GoHighLevel is asymmetric here — it accepts field_value on write and returns value on read. Note that opportunities read back a different, typed shape (fieldValueString / fieldValueNumber / fieldValueDate / fieldValueArray), and the test location defines no opportunity-scoped custom fields, so custom_fields on the opportunity tools is still unverified — confirm before relying on it there.