HLAI Experts

Guide · Email

Sending a transactional email from HighLevel without another email service

You can send a one-off email, such as a confirmation, straight from GoHighLevel (GHL) by calling POST /conversations/messages with type Email and the contactId of an existing contact. It goes out through whichever email provider that sub-account is set to use, so check that before you write code. Look the contact up rather than upserting one just to send.

Rob EasonPublished

What the send endpoint gives you

This is the conversations API's send-message route. Set type to Email and it sends an email to the contact you name. The token needs the conversations/message.write scope.

  • contactId is required. The email goes to a contact that already exists in the sub-account.
  • subject and html are separate fields. Put the subject line in one and the body markup in the other.
  • emailTo lets you pick another email address that belongs to the same contact, when the main one isn't right for this message.

Which service actually sends it

HighLevel decides the sending service in an order. A default provider set on the sub-account comes first, ahead of anything configured at the agency. When no provider is configured, LeadConnector Email is the documented fallback.

HighLevel's article on that order dates from 2023, so don't build on it alone. Open the sub-account's email settings and see what it's actually set to use. That tells you which service and sending domain your transactional mail will go out on.

Setting up a sending domain on LC Email

On a shared sending domain, the from address your contact sees can be rewritten. If you want mail to show your own domain, set up a dedicated one.

  1. In the sub-account, go to Settings > Email Services.
  2. Open Dedicated Domain and IP and click Add Domain.
  3. Add the DNS records HighLevel gives you and complete the verification.
  4. If you send different kinds of email, HighLevel lets you assign a dedicated domain to each email category separately.
A sending domain decides where mail comes from. A Reply-To decides where answers go. Set both on purpose.

Building the request

Once you know the provider and the domain, the call itself is short.

  1. Find the contact and take its contactId.
  2. Set type to Email.
  3. Put the subject line in subject and the full body markup in html.
  4. Set emailTo only if the message should go to one of the contact's other addresses.
  5. Send with a token that has conversations/message.write.
  6. Save the ids that come back in the response.

Send to a contact that already exists

It's tempting to upsert the contact in the same step, so the send never fails for want of a record. We don't. HighLevel's upsert can create a new contact whenever it doesn't find a match, so a typo or a second address turns one person into two records, and the email goes to the new one.

Our rule is to look the contact up first and send only to a contact that exists. If the lookup finds nobody, don't send; handle that case on purpose. That's our practice, not a HighLevel restriction: the API allows upsert, and some setups will want it. Just don't let it run as a side effect of sending.

Keep both ids from the response

The send response returns a messageId and an emailMessageId as separate values. They identify different things, and later calls can ask for one or the other. Store both against your own record of the send, so you can find the message again without searching for it.

Rather have it set up for you?

Starting from a 30-minute 1:1 with Rob, we set up your sending domain, build the email call into your app and test it on a real contact record.

Book a 1:1 with Rob

Questions

Questions about sending email from HighLevel

Can I send transactional email from HighLevel without a separate email service?
Yes. Call POST /conversations/messages with type Email for an existing contact, and HighLevel sends it through the sub-account's configured provider. With no provider configured, LeadConnector Email is the documented fallback.
Does the contact need to exist in HighLevel before I send?
Yes. contactId is a required field on the send request. Look the contact up first and use its id.
Which email provider sends an email from the HighLevel API?
A default provider on the sub-account takes priority over agency configuration, and LeadConnector Email is the fallback when none is set. HighLevel's article on this order is dated, so check the sub-account's email settings to be sure.
Why does my email show a different sending address?
Mail on a shared sending domain can display a rewritten from address. Set up a dedicated domain under Settings, Email Services, Dedicated Domain and IP, and verify its DNS records.
Should I upsert the contact before sending?
We don't. Upsert can create a new contact when it finds no match, which can split one person into two records. We look the contact up and send only if it exists.
Rob Eason

Who you talk to

Rob Eason

Rob runs HLAI Experts and takes the 1:1 calls himself.

He is a HighLevel Certified Admin with the second-most reviews in HighLevel's Certified Admin Directory worldwide, all of them 5 out of 5.

He won HighLevel's Top New Subaccounts via AI Employee award in its 2025 Summer of AI Awards and taught HighLevel's official masterclass on its AI Employee.

Before HighLevel, he co-owned a 60-employee financial services firm and sold his share.

On the call he looks at your account, not a script.

5/5 across 83 reviews in HighLevel's Certified Admin Directory