HeyReach alternative
The HeyReach alternative that books the call
Keep what works. Add live signals, lists that refill themselves and replies drafted for you.
Why teams switch
Why people leave HeyReach.
You still write every reply
On HeyReach's self-serve plans the replies are yours. AI replies come with their done-for-you service.
Your lists go stale
You build a list once. Gelee keeps adding new people who match, every day.
Sending isn't the hard part
HeyReach is great at sending from lots of accounts. Gelee also finds who to send to, and when.
What you get
Everything, on every plan.
Side by side
Gelee vs HeyReach.
| Feature | |||
|---|---|---|---|
| Finding buyers | |||
| Live buying signals (hiring, funding, job changes) | ✓ | Done-for-you only | |
| Evergreen lists that add new matches every day | ✓ | ✕ | |
| Every lead enriched automatically | ✓ | Email finder | |
| ICP filters checked before every send | ✓ | ✕ | |
| Scores every lead before reaching out | ✓ | Done-for-you only | |
| Reaching them | |||
| Routes your best accounts to your best prospects | ✓ | ✕ | |
| Per-account limits for invites, messages, reads, likes and comments | ✓ | ✕ | |
| Smart warm-up and ramp-up | ✓ | ✕ | |
| Post engager campaigns | ✓ | ✕ | |
| Keyword and follower campaigns | ✓ | ✕ | |
| Free InMails to Open Profiles | ✓ | ✕ | |
| Blacklist | ✓ | ✓ | |
| Replies and booking | |||
| AI drafts replies and sends your booking link | ✓ | Done-for-you only | |
| One inbox for every account | ✓ | ✓ | |
| Custom Slack notifications | ✓ | ✕ | |
| Setup and plumbing | |||
| Set up for you by our team | ✓ | Done-for-you only | |
| CRM integrations | ✓ | ✓ | |
| Public API and webhooks | ✓ | ✓ | |
| MCP for Claude and ChatGPT | ✓ | ✓ | |
How to switch
9 steps. We do them with you.
Export what you have in HeyReach
Export each campaign's leads to CSV from HeyReach, or pull them with
POST /api/public/campaign/GetLeadsFromCampaign(it returns each lead's campaign, connection and message status). Keep the LinkedIn profile URL, name, company, title, any custom user fields and tags.Note who has already been contacted and who replied. You will usually leave those people out of Gelee, or put them in a separate follow-up campaign.
Bring your do-not-contact list over first
Do this first. Before a single lead goes in. Pull your HeyReach blacklist with
POST /api/public/blacklist/GetLeadsand GetCompanies (or export it from the app), and add every lead you have already contacted that you do not want contacted again.Then send it over in one call, or add it in the app's Settings. People and whole companies both work, and sending the same list twice won't break anything. Gelee checks it when someone joins a campaign and again right before every message.
curl -X POST "https://www.gelee.ai/api/v1/blacklist" \ -H "Authorization: Bearer gk_your_key" \ -H "Content-Type: application/json" \ -d '{"entries":[ {"value":"https://www.linkedin.com/in/janedoe","type":"account"}, {"value":"Acme Corp","type":"company"} ]}'Connect your LinkedIn seats
Whoever sends the outreach connects their LinkedIn in the Gelee app, under Accounts. It takes a minute.
One rule matters more than the rest: don't let HeyReach and Gelee both run campaigns from the same seat at the same time. Neither tool knows what the other sent, and LinkedIn sees both. Pause that seat's HeyReach campaigns first, then switch it on in Gelee.
Brand new or rested account? Turn on warm-up and it starts slow.
Swap your message variables
Paste your HeyReach messages into Gelee steps and swap the variables. If a variable comes back empty, Gelee drops that sentence instead of sending a blank, so you don't need a fallback on every one.
Anything of your own, like a report link or a finding, becomes a custom field:
{{custom.field_name}}. If a step needs a field that isn't there yet, it waits for it (up to a day). Handy if you write the link onto the lead when they accept.- {FIRST_NAME} →
{{firstName}} - company and position fields →
{{company}},{{role}} - a custom user field →
{{custom.field_name}} - a fallback message →
{{custom.field_name|fallback text}}, or let Gelee drop the sentence
- {FIRST_NAME} →
Rebuild the sequence
A HeyReach sequence is a tree of nodes (connection request, message, InMail, like, follow, view) with a branch for accepted and not accepted. A Gelee campaign is an ordered list of steps that starts with a connection request (outbound) or a message to existing connections (inbound), with a wait before each step. Rebuild the main path: the invite note, then each follow-up message.
Gelee writes the AI lines and replies, so you can keep your copy as written or let Gelee personalise it per lead. A/B variants are per step, and
GET /campaigns/{id}/performanceshows replies and bookings for each.Steps HeyReach sends to Instantly, Smartlead or EmailBison have no Gelee equivalent; send those leads to your email tool from a Gelee webhook instead.
Add your leads
Make the campaign, then add people however's easiest: upload the CSV, push them with the API, or point Zapier or Clay at the campaign's intake URL. All Gelee needs is the LinkedIn URL.
Leave out anyone HeyReach already reached, unless you actually want a second touch. Gelee won't put the same person in two of your campaigns anyway.
Mapping from AddLeadsToCampaignV2: profileUrl → linkedin_url, firstName/lastName → first_name/last_name, companyName → company, position → title, emailAddress → email, customUserFields [{name, value}] → custom_fields {name: value}.
curl -X POST "https://www.gelee.ai/api/v1/campaigns/CAMPAIGN_ID/leads" \ -H "Authorization: Bearer gk_your_key" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: import-batch-1" \ -d '{"leads":[{"linkedin_url":"https://www.linkedin.com/in/janedoe", "first_name":"Jane","company":"Acme","title":"VP Sales", "custom_fields":{"report_link":"https://acme.example/r/5d70"}, "tags":["imported"]}]}'Repoint your integrations
Map each HeyReach webhook to the Gelee event in the table above. The main differences: Gelee's reply event fires on every reply (check timeline.first_reply_at for the first), invite_sent and message_sent must be picked by name, and Gelee adds bookings, needs_human and lead_updated.
In Gelee, add a webhook under Settings, Event Destinations (or
POST /webhooks). Every event comes with the person, the seat that sent and the campaign. Hit Test to get a full sample before anything real flows.Leave the HeyReach one running until you cut over, so your CRM doesn't have a gap.
Port your API code
Swap the base URL and header, then follow the mapping table. Every Gelee answer about a person carries the same block: name, LinkedIn URL, lead id, the seat that sent, the campaign, stage, booking likelihood and grade, timeline, booking and a link to the conversation. You can usually drop the extra lookups HeyReach code makes to stitch those together.
Sends take an Idempotency-Key header, so a retry never messages someone twice. Keys that send need the "Read + write + send messages" permission.
# HeyReach curl -X POST "https://api.heyreach.io/api/public/inbox/SendMessage" \ -H "X-API-KEY: $HEYREACH_KEY" -H "Content-Type: application/json" \ -d '{"conversationId":"2-ODM0…","linkedInAccountId":123,"message":"Hi Jane"}' # Gelee curl -X POST "https://www.gelee.ai/api/v1/inbox/chat_88/messages" \ -H "Authorization: Bearer $GELEE_KEY" -H "Content-Type: application/json" \ -H "Idempotency-Key: msg-5d70-1" \ -d '{"text":"Hi Jane"}'Run both for a bit, then cut over
Don't move everything on day one. Start with a seat or two, run them next to HeyReach for a few weeks, and look at accepts, replies and booked calls. Split by seat, never by person.
Happy? Pause the rest of HeyReach, export one last time, move the remaining seats. Keep that last export. It's your record of who was contacted before.
Let AI do it
Let our AI move it.
The Gelee MCP already knows HeyReach. Connect it to Claude or ChatGPT and ask it to move you over. It checks with you before anything sends.
Set up the MCPQuestions
Good to know.
Does Gelee have a HeyReach-style API?
Yes. Campaigns, leads with custom fields, tags, the inbox, sending, seats, stats, the blacklist and webhooks are all in the Gelee API, and the mapping table on this page lists the Gelee call for each HeyReach one. Gelee also lets you start new conversations and InMails, edit and unsend messages, and work the AI SDR's drafts.
How do HeyReach custom user fields move to Gelee?
Send them as custom_fields when you push each lead (customUserFields [{name, value}] becomes custom_fields {name: value}), or set them later with PATCH /prospects/{id}. Use them in messages as {{custom.name}}.
Is there a Gelee equivalent of HeyReach's EVERY_MESSAGE_REPLY_RECEIVED webhook?
reply_received fires on every reply from someone in your campaigns, and reply_positive and reply_negative split them by sentiment. needs_human fires when the AI SDR hands a reply to a person.
Can I run HeyReach and Gelee at the same time?
Yes. Just don't run both on the same LinkedIn seat at once, and don't let them message the same people. Split by seat and you're fine.
Will I lose my HeyReach conversation history?
No. The conversations live on LinkedIn, so they show up in Gelee once the seat connects. What doesn't come over is the other tool's own notes, tags and stats. Export those before you cancel.
For developers: API calls, webhooks and variables
HeyReach has a public REST API at api.heyreach.io/api/public, authenticated with an X-API-KEY header and limited to 300 requests a minute. It covers campaigns (create, sequence, schedule, senders, start, pause, resume), adding leads with custom fields, lists, the inbox (list conversations, read one, send a message into an existing conversation, mark seen), LinkedIn accounts (including connecting with credentials or cookies), tags, stats, the blacklist, email enrichment, webhooks and organization-level workspace management.
Its webhooks cover connection requests sent and accepted, messages and InMails sent, first replies and every reply, follows, liked posts, profile views, campaign completion and tag changes, and can be limited to specific campaigns.
Their words, our words
| HeyReach | Gelee | Notes |
|---|---|---|
| Campaign | Campaign | Both run a sequence from one or more senders. |
| Lead list | The campaign's leads | Gelee has no separate list object: leads live in campaigns. Push or upload them straight into one. |
| LinkedIn sender account | Seat | One connected LinkedIn account. |
| Custom user fields | Custom fields | Used as {{custom.key}} in messages. |
| Tags | Tags | Plus inbox flags: interested, lost, referral, follow-up. |
| Unibox / inbox | Inbox | Gelee's AI SDR can draft or send replies there. |
| Blacklist (leads and companies) | Blacklist | Profiles and companies, checked before every send. |
| Workspace | Workspace | One Gelee API key belongs to one workspace. |
API calls
| HeyReach | Gelee | Notes |
|---|---|---|
GET auth/CheckApiKey | GET /me | Also returns the workspace name and every seat. |
POST campaign/GetAll, GET campaign/GetById | GET /campaigns, GET /campaigns/{id} | Includes seats, schedule, source, auto top-up and counts. |
POST campaign/Create + UpdateSequence | POST /campaigns (sequence in the body) | Lands as a draft. |
POST campaign/StartCampaign, Resume | POST /campaigns/{id}/launch | |
POST campaign/Pause | POST /campaigns/{id}/pause | |
POST campaign/UpdateSettings, UpdateSchedule, UpdateAccounts | PATCH /campaigns/{id} | name, schedule, seat_ids, filters, search, auto_top_up. |
POST campaign/CreateCampaignFromTemplate | POST /campaigns/{id}/duplicate | |
POST campaign/AddLeadsToCampaignV2 | POST /campaigns/{id}/leads | customUserFields becomes custom_fields; up to 100 a call; safe to retry. |
PATCH campaign/UpdateLeadCustomFields | PATCH /prospects/{id} { custom_fields } | null deletes a field, like HeyReach. |
POST campaign/StopLeadInCampaign | POST /prospects/{id}/pause or /remove | Or POST /inbox/stop with LinkedIn URLs to stop someone everywhere. |
POST campaign/GetLeadsFromCampaign | GET /prospects?campaign_id=… | Every lead, with sender, timeline, booking and score. |
POST campaign/GetCampaignsForLead | GET /prospects?linkedin_url=… | Every campaign row for that person. |
POST lead/GetLead | GET /prospects?linkedin_url=…, GET /people/{id} | |
POST lead/AddTags, ReplaceTags, GetTags | PATCH /prospects/{id} { tags } | { add, remove } or a full list. |
POST inbox/GetConversationsV2, V3 | GET /inbox | Every seat, with the whole story of each person. |
GET inbox/GetChatroom | GET /inbox/{chat_id}/messages | From stored history, paged with a cursor. |
POST inbox/SendMessage | POST /inbox/{chat_id}/messages | Needs a key with the send permission. Takes an Idempotency-Key. |
(no equivalent found in HeyReach's docs) | POST /conversations | Start a new conversation or InMail to someone you have no thread with. |
POST inbox/SetSeenStatus | POST /inbox/{chat_id}/read | |
POST li_account/GetAll, GetById, GetAccountStatus | GET /seats | Status, limits, today's sends, warm-up. |
POST li_account/Connect, ConnectWithCookies | Not available | Seats connect in the app; POST /seats/{id}/reconnect-link sends a reconnect link. |
POST stats/GetOverallStats, GetOverallStatsByCampaign | GET /analytics, /analytics/daily, /campaigns/{id}/performance | |
POST blacklist/AddLeads, AddCompanies | POST /blacklist | Up to 500 entries a call. |
POST blacklist/RemoveLeads, RemoveCompanies | DELETE /blacklist/{id} | |
webhooks/CreateWebhook, GetAllWebhooks, UpdateWebhook, DeleteWebhook | POST, GET, PATCH, DELETE /webhooks | Always signed when made through the API. |
list/* (lead and company lists) | Not available | Push leads straight into a campaign instead. |
enrichment/enrich-email | Not available | |
management/organizations/* (workspaces, users, keys) | POST /team for teammates | No workspace or key creation over the API. |
Webhooks
| HeyReach | Gelee webhook | Notes |
|---|---|---|
| CONNECTION_REQUEST_SENT | invite_sent | Pick it by name; it is not part of "all". |
| CONNECTION_REQUEST_ACCEPTED | connection_accepted | |
| MESSAGE_SENT, INMAIL_SENT | message_sent | message.message_type says INMAIL for InMails. Pick by name. |
| MESSAGE_REPLY_RECEIVED, INMAIL_REPLY_RECEIVED (first reply) | reply_received | Fires on every reply; timeline.first_reply_at tells you if it is the first. |
| EVERY_MESSAGE_REPLY_RECEIVED | reply_received | Also reply_positive and reply_negative, sorted by sentiment. |
| CAMPAIGN_COMPLETED | campaign_completed | |
| LEAD_TAG_UPDATED | lead_updated | Also fires for custom fields, flags, notes, pause and resume. |
| FOLLOW_SENT, LIKED_POST, VIEWED_PROFILE | No webhook | |
| (none) | call_booked, needs_human, lead_accepted, lead_rejected | Bookings, replies the AI handed to a person, and verdicts on pushed leads. |
Message variables
| Value | Gelee variable |
|---|---|
| First name | {{firstName}} |
| Full name | {{fullName}} |
| Company | {{company}} |
| Job title | {{role}} |
| Industry | {{industry}} |
| Your own per-lead field | {{custom.your_field}} |
| A fallback when empty | {{custom.your_field|default text}} |
| Sender's name | {{senderName}} |
Discovery call
Moving from HeyReach? We'll plan it with you.
A quick call. We learn about your market, and if it's a fit we'll move you over.
