← all tools
Sequencers

HeyReach

LinkedIn outreach at volume, paced so your account survives it.

Cost per callBYOK · vendor billed
Your own keyrequired
CategorySequencers

HeyReach runs LinkedIn sequences: connection requests, messages and follow-ups, throttled to stay inside what LinkedIn tolerates. Your agent builds the list and loads it into a campaign you already created. Replies come back where you can read them.

HeyReach is the LinkedIn half of activation. Pair it with an email sequencer to work both channels at once.

things you can ask for

  • Add these 40 profiles to the LinkedIn campaign, the ones Wiza already enriched
  • What came back in the inbox this week?
  • Pause outreach to this company
  • Run this list on LinkedIn and email at the same time, pairing with Instantly

works well with HeyReach

  • Wiza

    the LinkedIn URLs you enriched are the campaign list

  • Instantly

    pair LinkedIn with email for the same shortlist

  • Apify

    scrape post engagers straight into a campaign list

  • Loxo

    log the LinkedIn conversation on the candidate

Ask for the outcome and your agent composes the run itself. Or start from a skill, a whole pipeline it already knows end to end.

browse all skills →

What your agent reads before it touches HeyReach

Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.

Read the HeyReach docs →
Show the raw playbookwritten for the agent

HOW in lib/heyreach.py. Paths CONFIRMED (Postman docs + community audit, 2026-06-01) — PascalCase actions under /api/public, X-API-KEY. No public OpenAPI (/swagger redirect-loops). Methods: check_api_key, get_all_campaigns, get_campaign, pause_campaign, resume_campaign, add_leads_to_campaign, get_lead, get_conversations, get_overall_stats, get_all_lists, create_empty_list, get_my_network (+ add_leads_to_list V2 analog — verify on pilot). No create-via-API / delete / send-message endpoints exist. Index: reference/docs/heyreach/raw/endpoints.md.

Auth & config

  • Base URL: https://api.heyreach.io/api/public · Auth: header X-API-KEY (env HEYREACH_API_KEY; never hardcode). check_api_key() = safe read-only pilot.

Key rule + approval gate

  • Campaigns must be pre-created in the HeyReach UI. Resolve campaign/list ids first (get_all_campaigns/get_all_lists), then add leads.
  • add_leads_to_campaign drives real LinkedIn outreach — approval-gate (pilot a few, confirm, then batch). Confirm stats after writes.

Operations

Campaigns: get_all_campaigns, get_campaign, add_leads_to_campaign, pause_campaign, resume_campaign. Lists: get_all_lists, create_empty_list, add_leads_to_list. Inbox: get_conversations. Else → generic request().

Handoff

LinkedIn activation layer: sourced/enriched LinkedIn profiles → add to a list or campaign → outreach. Pairs with email sequencers (Instantly/Smartlead) for multichannel.

Field notes (production experience)

Field-shape note: these are vendor-native operational notes. The client returns the raw vendor JSON and uses the method names in this file — read field shapes accordingly (no normalized-wrapper / result.data. prefix).

  • No campaign creation via API - create the campaign in the HeyReach UI first, then reference its campaign_id. Always list_campaigns and resolve the exact target before inserts.
  • Add leads in small chunks; validate response shape before scaling; pull campaign stats after inserts to confirm effect.
  • Lead payloads carry linkedin_url (+ optional first_name/last_name/email).

Callable surface — lib/heyreach.py

Import: from lib.heyreach import HeyReach → instantiate HeyReach() (reads key from env). Base: https://api.heyreach.io/api/public. Generic passthrough: request(method, path, *, params, json).

  • add_leads_to_campaign(campaign_id: int, leads: list[dict], **opts) -> Any — POST /campaign/AddLeadsToCampaignV2 — enroll LinkedIn leads into a (pre-created) campaign.
  • add_leads_to_list(list_id: int, leads: list[dict]) -> Any
  • check_api_key() -> Any — GET /auth/CheckApiKey — validate the key (safe read-only pilot).
  • create_empty_list(name: str, **opts) -> Any
  • get_all_campaigns(offset: int = 0, limit: int = 100, **filters) -> Any — POST /campaign/GetAll — list campaigns (paged via offset/limit).
  • get_all_lists(offset: int = 0, limit: int = 100, **filters) -> Any
  • get_campaign(campaign_id: int) -> Any
  • get_conversations(**filters) -> Any — POST /inbox/GetConversationsV2 — LinkedIn inbox conversations.
  • get_lead(payload: dict) -> Any — POST /lead/GetLead — fetch a lead (by linkedin url / id).
  • get_my_network(sender_id: int, **opts) -> Any — POST /MyNetwork/GetMyNetworkForSender — a sender's LinkedIn network.
  • get_overall_stats(**filters) -> Any — POST /stats/GetOverallStats — account/campaign aggregate stats.
  • pause_campaign(campaign_id: int) -> Any
  • resume_campaign(campaign_id: int) -> Any