Skip to main content

What You Get

  • Contact sync — Import GHL contacts into Tuco with deduplication
  • Owner mapping — Map GHL users to Tuco team members
  • Tag sync — GHL contact tags imported automatically
  • Custom field sync — Map GHL custom fields to Tuco custom fields or tags
  • Campaign conditions — Use GHL tags in campaign branching and stop conditions

Connecting GoHighLevel

  1. Go to Integrations → CRM
  2. Enter your GHL API key and Location ID
  3. Click Test & Connect
  4. A full sync starts automatically
Only one CRM can be connected at a time. Disconnect HubSpot before connecting GHL.

Required API scopes

  • Location access
  • Contacts: search and read
  • Tags: read location tags
  • Users: read (for owner mapping)
  • Custom fields: read (for field mapping)
  • Contact tags: add/remove (for campaign automation)
  • Conversations: create (for activity logging)

Contact Sync

How it works

  • First sync — imports all GHL contacts into a “GHL Import” list
  • Incremental sync — every 15 minutes, syncs recently modified contacts
  • Deduplication — matched by phone number
  • Tags — GHL contact tags are imported into Tuco’s tag system

What syncs

Owner Mapping

Same as HubSpot — map GHL users to Tuco members.
  1. Integrations → CRM → Owner Mapping
  2. Map each GHL user to a Tuco member
  3. Save & Re-sync

Custom Field Mapping

Map GHL custom fields to Tuco tags or custom fields.
  1. Integrations → CRM → Property Mapping
  2. Select a GHL custom field
  3. Choose Tag or Custom Field target
  4. Save & Re-sync

Channel control with tags

Use a GHL contact tag to control which channel a lead’s outbound messages go out on. Tags are read live on every send (workflow action and conversation-provider / CloseBot), so they take effect immediately — no sync, no custom field, no reinstall. The tag name is matched loosely (case-insensitive, ignoring spaces/dashes/underscores), so forcefallback, force-fallback, force_fallback, and Force Fallback all work.
forcefallback only changes the channel, not delivery. The lead must have a fallback configured (Settings → When iMessage isn’t available). With no fallback set up the send returns an error instead of silently delivering over iMessage. Add or remove the tag any time to flip a lead between iMessage-first and SMS-only.

Send iMessages from a GHL workflow

The simplest way to trigger a Tuco iMessage from a GHL workflow is a plain Webhook action pointed at the Send Message API — no Marketplace app or action secret, just your Tuco API key. GHL’s Webhook action already attaches the full contact payload, so the only thing you map is the message.
  1. In your workflow, add a Webhook action — Method POST, URL https://app.tuco.ai/api/messages.
  2. Add a header: Authorization = Bearer tuco_sk_xxxxxxxxxxxxx (your API key).
  3. Under Custom Data, set message (required). Optionally add lineId (pin a sending line) and attachmentUrls.
Tuco reads GHL’s native contact fields to fill in the recipient and contact link automatically (phone → recipient, contact_id → GHL contact, location.id → GHL location, full_name → name, user.email → owner). You don’t map any of those.
Full field-by-field mapping and a copy-paste example are on the Send Message → “Send straight from a GoHighLevel webhook” reference. If the contact has no phone or email the send fails with missing_recipient.
Want Tuco to look up the recipient, pick a line, and run compliance checks for you from only a contact ID? Use the GHL Marketplace Send via Tuco action instead — see your in-app Leads → AI & API tab for both setups.

Send a voice note from GHL

The Marketplace Send via Tuco (Send iMessage) action can deliver a native iMessage voice note — the recognizable play-button bubble, not a file link. You supply a clean audio URL and flip one toggle; Tuco transcodes the audio to the voice-note format for you.

Get an audio URL

You need a public https://… link to an audio file (mp3, m4a, wav, aac, ogg, or caf), ≤ 25 MB and ≤ 5 minutes. The easiest way to get one:
  • In the dashboard, open /uploads (or the Upload audio etc tab on the Leads page), drag in your clip, and hit Copy to copy the link.
  • Or upload it programmatically with POST /api/attachments/upload.
Either way the URL belongs to your workspace, so it passes Tuco’s attachment ownership guard automatically.

Configure the action fields

In your GHL workflow, add the Send via Tuco action and set these fields:
A voice note — like any attachment — is blocked on the first-ever message to a contact. It only lands on a contact you already have a conversation with. Warm the contact up with a plain text message first; the voice note lands on any later step.
_attachment_only_ needs a real attachmentUrl to go with it. If you set the magic word but leave the URL empty, the action returns Used _attachment_only_ but no Attachment URL was provided. To send audio with a caption, put your caption in message instead of the magic word.
Want the audio to send as a file rather than a voice note? Leave voiceNote off (or false). Everything else stays the same.

Check for Replies (Marketplace workflow action)

The Check for Replies action tells your workflow whether a contact has replied on iMessage since your last outbound message — and hands the recent conversation to later steps, so If/Else branches, AI steps, and webhooks can act on what was actually said. The action takes an optional phone field; leave it blank to use the contact’s phone automatically.

Response

Each pastConversation item:
hasReplied and hasEverReplied answer different questions. hasReplied means “replied since your last outbound” — after you (or Tuco’s AI copilot) send a follow-up, it flips back to false. hasEverReplied never flips back: once the contact has replied, it stays true. If your workspace has an auto-responder, branch on hasEverReplied — the auto-reply usually lands within seconds, so hasReplied will already be false by the time your workflow checks. Use hasReplied only for strict wait-for-reply flows, and lastReply / pastConversation for AI context. If a line was later deleted, from/to may be empty for its messages — fromLineId still identifies the line.

Using GHL Data in Campaigns

Stop conditions

  • GHL tag — stop if contact has/doesn’t have a tag (live API call)

Branching

  • GHL has tag — branch based on GHL tags (live API call)
  • GHL property — branch on custom field values
All GHL checks call the live GHL API, not cached data.

Available operators

When comparing GHL property values in stop conditions or branches, all standard operators are supported:

Goal Bot integration

GHL tags and custom fields can be used as advance or exit conditions in Goal Bots. When a Goal Bot checks GHL data, it calls the live API — the same way campaigns do.