First-party app
HeyReach

HeyReach

Run HeyReach LinkedIn outreach from a workflow: campaigns, lead lists, leads, senders, inbox and blacklist.

stable MarketingSocial MediaCustomer Relationship Management

About

HeyReach ships in the w6w first-party pack. It declares 30 actions, 3 health checks, and the host runs its code in a sandbox that never sees the credential.

App id
io.w6w.heyreach
Version
0.1.0
Author
w6w
Licence
MIT
Categories
Marketing · Social Media · Customer Relationship Management

Overview

HeyReach is a LinkedIn outreach and automation platform for sales teams, and this app exposes the half of it a workflow can act on: the leads, lists and campaigns that outreach runs on.

Leads are looked up by profile URL, tagged, and pushed in bulk into either a lead list or directly into a campaign paired with the sending LinkedIn account — which is HeyReach’s own unit of work, since a lead is always worked by a specific sender. Campaigns can be listed, read, created as drafts, started, paused, resumed, and their sequence read back, so a workflow can drive outreach state rather than only inspect it.

Around that, the app covers the supporting surfaces a scaling operation needs: the connected LinkedIn sender accounts and their live connection status, the lead and company lists those campaigns draw from, inbox conversations and message sending, workspace-wide statistics per day and per campaign, webhook registration for reacting to replies and connections instead of polling, and the blacklist that keeps leads out of every campaign.

Authorization is HeyReach’s own single X-API-KEY header, and the app ships a health check that reads the API’s own auth answer rather than trusting an HTTP status alone.

Build with HeyReach

Three routes to the same 30 actions. The Workflow tab is generated from HeyReach's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.

Add Leads to Blacklist

blacklist-add-leads

Blacklist up to 100 leads by LinkedIn member id, profile URL, email or full name, so no campaign in this workspace contacts them (POST /api/public/blacklist/AddLeads).

Get Blacklisted Leads

blacklist-get-leads

List the blacklisted leads in this workspace, newest first, filtered by search text or how the entry resolved (POST /api/public/blacklist/GetLeads).

Add Leads to Campaign

campaign-add-leads

Add leads to a campaign, each paired with the LinkedIn account that will work it (POST /api/public/campaign/AddLeadsToCampaignV2).

Create Campaign

campaign-create

Create a campaign in DRAFT status, optionally with its schedule and sequence (POST /api/public/campaign/Create). Start it separately with Start Campaign.

Get Campaign

campaign-get

Fetch one campaign with its status, progress statistics, sender accounts and exclusion rules (GET /api/public/campaign/GetById).

Get Leads from Campaign

campaign-get-leads

List the leads queued in a campaign, with their per-lead campaign, connection and message status (POST /api/public/campaign/GetLeadsFromCampaign).

Get Campaign Sequence

campaign-get-sequence

Read a campaign's sequence node object — the exact shape the campaign runs (GET /api/public/campaign/GetCampaignSequence).

List Campaigns

campaign-list

List campaigns with their status, progress and sender accounts, filtered by keyword, status or account (POST /api/public/campaign/GetAll).

Pause Campaign

campaign-pause

Pause a running campaign (POST /api/public/campaign/Pause).

Resume Campaign

campaign-resume

Resume a paused campaign (POST /api/public/campaign/Resume).

Start Campaign

campaign-start

Activate a DRAFT campaign so its sequence begins running (POST /api/public/campaign/StartCampaign).

Check API Key

check-api-key

Verify the connection's HeyReach API key (GET /api/public/auth/CheckApiKey). Returns `connected: false` when HeyReach rejects the key, and throws when the API itself fails.

Get Conversations

inbox-get-conversations

List LinkedIn conversations, cursor-paged, filtered by sender, campaign, lead, tag or read state (POST /api/public/inbox/GetConversationsV3).

Send Message

inbox-send-message

Send a message into an existing LinkedIn conversation (POST /api/public/inbox/SendMessage).

Add Tags to Lead

lead-add-tags

Add tags to a lead by profile URL or LinkedIn id, optionally creating tags that do not exist yet (POST /api/public/lead/AddTags).

Get Lead

lead-get

Fetch the LinkedIn profile details HeyReach holds for a lead, by profile URL (POST /api/public/lead/GetLead).

Get Tags for Lead

lead-get-tags

Read the tags on a lead. HeyReach's document publishes no response schema for this operation, so the body is returned verbatim (POST /api/public/lead/GetTags).

Get LinkedIn Account

linkedin-account-get

Fetch one sender LinkedIn account by id, including its per-action limits (GET /api/public/li_account/GetById).

List LinkedIn Accounts

linkedin-account-list

List the workspace's sender LinkedIn accounts, with their active flag and auth validity (POST /api/public/li_account/GetAll).

Get LinkedIn Account Status

linkedin-account-status

Read one sender account's live connection status, failure reason, and Sales Navigator / Recruiter authentication (GET /api/public/li_account/GetAccountStatus/{accountId}).

Add Leads to List

list-add-leads

Add up to 100 leads to a lead list, creating or updating each one (POST /api/public/list/AddLeadsToListV2).

Create List

list-create

Create an empty lead or company list (POST /api/public/list/CreateEmptyList).

Get List

list-get

Fetch one lead or company list by id, with its lead count and the campaigns that use it (GET /api/public/list/GetById).

List Lists

list-get-all

List lead and company lists, filtered by keyword, type or the campaigns that use them (POST /api/public/list/GetAll).

Get Leads in List

list-get-leads

Read the leads in a lead list, filtered by keyword, profile URL or LinkedIn id and by when they were added (POST /api/public/list/GetLeadsFromList).

Get Overall Stats by Campaign

stats-get-by-campaign

Read outreach statistics for a date window broken down per campaign, per day and aggregated (POST /api/public/stats/GetOverallStatsByCampaign).

Get Overall Stats

stats-get-overall

Read outreach statistics for a date window, per day and aggregated, optionally scoped to particular senders or campaigns (POST /api/public/stats/GetOverallStats).

Create Webhook

webhook-create

Register a webhook for one HeyReach event type, optionally limited to specific campaigns (POST /api/public/webhooks/CreateWebhook).

Delete Webhook

webhook-delete

Delete a webhook by id (DELETE /api/public/webhooks/DeleteWebhook).

List Webhooks

webhook-list

List the workspace's webhooks with their event type, target URL and campaigns (POST /api/public/webhooks/GetAllWebhooks).

A workflow step names the app and the action, and the editor fills in the connection when you pick one. This is the Step shape from the workflow spec, carrying HeyReach's real ids.

{
  "manifestVersion": "2",
  "name": "heyreach-example",
  "steps": [
    {
      "id": "blacklist-add-leads",
      "uses": {
        "app": "io.w6w.heyreach",
        "action": "blacklist-add-leads",
        "connection": "conn_YOUR_CONNECTION_ID"
      },
      "with": {
        "leads": "<leads>"
      }
    }
  ]
}

Here are some of the things you can do

  • Add Leads to Blacklist

    perform
    blacklist-add-leads
  • Get Blacklisted Leads

    search
    blacklist-get-leads
  • Add Leads to Campaign

    perform
    campaign-add-leads
  • Create Campaign

    perform
    campaign-create
  • Get Campaign

    read
    campaign-get

+25 more actions available

Every app-specific value here is a blank you have to fill in. An app action is reached through the connection that authenticates it, so the address is a connection id, not the app id — and connections belong to your account, so a public page cannot know yours. Create one for HeyReach, then fill in the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the parameters that action declares. The call itself is real — the shape is transcribed from the studio's own snippet builder, which prints the same kind of blanks — but nothing in it is specific to HeyReach. The Workflow tab is where this app's real ids are.

Install
npm install @w6w/sdk
yarn add @w6w/sdk
pnpm add @w6w/sdk
deno add npm:@w6w/sdk
Code
import { W6wClient, isActionRun } from "@w6w/sdk";

// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();

const envelope = await client.run({
  urn: "conn_YOUR_CONNECTION_ID",
  action: "blacklist-add-leads",
  payload: {
    leads: "<value>",
  },
});

if (isActionRun(envelope)) console.log(envelope.value);
Install the CLI
npm install -g @w6w/cli
CLI
w6w run conn_YOUR_CONNECTION_ID --action blacklist-add-leads --payload '{"leads":"<value>"}'

Give an AI agent HeyReach — without giving it HeyReach's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.

One tool call
{
  "name": "w6w_invoke",
  "arguments": {
    "ref": "app:io.w6w.heyreach#blacklist-add-leads",
    "input": {
      "leads": "<leads>"
    }
  }
}

Every tool names its target with a single ref. The app: form above doesn't name a connection at all — the host resolves which of the caller's HeyReach connections to sign with, and refuses rather than guesses when the answer is ambiguous.

What the agent gets

Credentials it can't read

The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.

A tool surface scoped to the caller

Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.

A durable workflow in one call

Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.

Health-aware discovery

HeyReach's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.

The MCP surface is part of the hosted platform. HeyReach itself is MIT, and the runtime that executes it is source-available (FSL).

Request MCP access

Health checks

HeyReach declares its own checks, so its health is a property of the app rather than something the host guesses at.

service

HeyReach API reachable

Calls GET /api/public/auth/CheckApiKey with this connection's key and reads the API's own auth answer. A 401 carrying `Missing API key`/`Invalid API key` is proof HeyReach is reachable — the credential itself is the derived auth:api-key check's verdict.

service

HeyReach platform status

No machine-readable status surface: status.heyreach.io is real but UptimeRobot-hosted, and its only JSON routes are keyed by a token scraped from the page itself.

quota

API rate-limit headroom

Not exposed: HeyReach's document declares a 429 on every operation but no rate-limit header and no quota endpoint.