Skip to main content
Everything on this page applies to every published endpoint. The endpoint pages assume you know it.

Base URL and authentication

Paths in the reference already include the /api prefix. Every request carries an API key as a bearer token:
Keys, scopes and the InsufficientScope error are covered in Authentication. Requests authenticated with an API key do not use CSRF tokens. CSRF protection applies to browser dashboard sessions only.

Response envelope

Success:
The payload key is data on most endpoints and a named field on some, such as agents, voices or contacts. The endpoint page shows which. Failure:
Every error answers in this shape: Some errors add fields of their own, such as requiredScope on InsufficientScope, or workflowId and stepId on a TFU Live workflow refusal. Some endpoints also repeat the code in a top-level code field, kept for integrations built before error always held one. The reference lists these on each endpoint. Requests made with an API key or through an OAuth app, MCP included, always get message in English. People using the dashboard get it in their own language. error never changes with the language.

If you read a sentence from error

Five modules used to put a sentence in error: Native Calendar, Native Contacts, Contacts, TFU Live, and the power dialer operations under Campaigns. They now put a code there, like every other module, and the sentence is in message. If your integration shows error to people, show message instead. If it matches the words, match the code. Contacts and the power dialer also sent the code in a separate code field. Read it from error now: code is no longer sent there. TFU Live still sends code, with the same value as error. See the Changelog.

Which id to use

Most resources have more than one identifier. They are not interchangeable. A contact’s contactId is the GoHighLevel contact id on a sub-account with a CRM, and the native contact id, which starts with nct_, on one that keeps its contacts here. It can be absent altogether, so key on the phone number and treat the id as optional. See Agencies, projects and sub-accounts for the three project identifiers in detail.

Phone numbers

Numbers travel in E.164 with a leading +, for example +14155550100. In a URL path the + must be percent-encoded as %2B:

Dates and times

  • Date filters (dateFromUTC, dateToUTC) accept a UTC timestamp with Z or an offset, or a plain YYYY-MM-DD. A plain date covers that whole day.
  • A plain date is a UTC day unless you also send tz, an IANA zone name such as America/Los_Angeles or Asia/Kolkata. With it, the day runs from midnight in that zone to the next midnight there, so a day when the clocks change is 23 or 25 hours long. GET /api/call-history and GET /api/contacts take tz, and the window on their response gives the UTC instants the filter used.
  • tz changes plain dates only. A timestamp is the exact moment it names, with or without tz.
  • A missing or unknown tz is not an error: plain dates stay UTC days. So does a bare offset such as +05:30, because an offset does not follow daylight saving. Send the zone name.
  • A timestamp without a zone is rejected with 400 rather than read as server time.
  • Timestamps in responses are ISO 8601 in UTC, for example 2026-09-05T14:03:22.000Z.
  • Analytics windows are inclusive calendar days. See Metrics and how they are calculated.

Pagination and sorting

Paged list endpoints take page (from 1) and limit, and return a pagination object with page, limit, total and totalPages. Sorting is not uniform, and the reference shows which form each endpoint takes:
  • Calls: sort as field.direction, for example dateTime.desc.
  • Contacts: sortBy and sortOrder (asc or desc).

Idempotency

Most operations are not idempotent. Repeating a create after a timeout can create twice. Read the current state back before retrying a write. These operations accept an Idempotency-Key header. Send a unique value per logical request and a retry with the same key returns the original result:

Concurrency tokens

Documents that are edited while they run carry a version. Send it back on every write. If someone saved in between, the write is refused with 409 and you reload instead of overwriting them.

Legacy aliases

Some responses carry an older spelling beside the canonical field. Same value. Build on the canonical name. Deprecated routes carry a Deprecation response header (RFC 9745) and are marked in the reference. Removals are announced in the Changelog.

Status codes

Error codes

The codes shared across published endpoints, grouped by what to do about them. Each endpoint’s page lists the codes specific to it. A few codes have two spellings, an older one kept so existing integrations keep working, and the reference shows which one each endpoint returns. If you handle one, handle both. Integration states are explained in GoHighLevel resources.

Billing access

AccessSubscriptionRequired can block reads as well as writes. Changing API key scopes does not resolve it. Effective software access is separate from the provider’s subscription status and the wallet’s recorded balance. An approved billing exemption does not change resource ownership, user roles or API key scopes. It also does not cancel an existing provider subscription or erase billing history.

Rate limits

Limits are per minute and the defaults are below. The headers on every response are authoritative, so build on them rather than on this table. Every response carries the standard draft rate-limit headers: When a limit is exceeded the API returns 429 with TooManyRequests and the standard envelope. Wait RateLimit-Reset seconds and retry. Spread bulk work across the window rather than bursting at the top of the minute.