Announcing CIMD support for MCP Client registration
Learn more

HeyReach MCP or API, What to Use for Agent Development?

TL;DR

  • HeyReach ships an official MCP server and a public REST API. Both authenticate with a static, non-expiring credential, and neither issues per-user identity or exposes scopes.
  • MCP embeds an MCP Key inside a per-workspace Connection URL. The API uses an X-API-KEY header. A URL-borne secret lands in config files, shell history, and proxy logs by default.
  • HeyReach publishes no tool manifest for its MCP server, and no OpenAPI document is reachable on the public host. Enumeration is a runtime activity on both paths.
  • Both surfaces draw on one rate budget: 300 requests per minute, organization-wide. One noisy agent degrades every other integration on the account.
  • Scalekit's HeyReach connector vaults the key per user, resolves it server-side, and writes a 90-day audit trail. The MCP versus API choice does not change your credential infrastructure.

The decision you are actually making

Your agent needs to read HeyReach campaigns, enroll leads, and watch the LinkedIn inbox for replies. HeyReach ships both an official MCP server and a public REST API, so the obvious question is which one to build against.

For most tools in this series, that question resolves along a clean line: MCP gives you per-user OAuth, the API gives you a service credential. HeyReach does not split that way. Both paths run on the same class of static key. The interesting tradeoffs are somewhere else entirely.

What HeyReach MCP and the HeyReach API actually are

These are two front doors onto the same backend. Understanding how each one is credentialed matters more than understanding what each one is called.

The HeyReach MCP server

HeyReach was among the first LinkedIn outreach platforms to ship an official MCP server, documented on the HeyReach MCP product page. It is a remote server, not a local process.

Each workspace gets its own MCP Connection URL and MCP Key, generated under Integrations and then HeyReach MCP Server. Regenerating the key rewrites the Connection URL. Clients that only speak stdio bridge to it through mcp-remote, per HeyReach's Claude integration guide.

The HeyReach public API

The REST API is documented in the HeyReach API Postman collection. The base path is https://api.heyreach.io/api/public.

Authentication is a single X-API-KEY request header on every call. HeyReach states that API keys never expire, though they can be deleted or deactivated, and that the key maps requests to your organization. You can validate a key with a GET against /auth/CheckApiKey.

What each path exposes, and how you can verify it

Capability comparison usually starts with two published tool lists. For HeyReach, only one side publishes anything, so it is worth being precise about what is verifiable and what is not.

The API is documented; the MCP manifest is not

HeyReach's help center carries six articles covering MCP, the API, and webhooks. None of them enumerates the tools the MCP server exposes. The product page describes outcomes such as pulling live stats and pushing qualified leads into a sequence, not tool names or input schemas.

The API side is better, but not by as much as you would like. The Postman collection documents the endpoints; there is no OpenAPI document served from the public host that an agent planner or codegen step could consume.

The practical consequence for agent builders

You cannot plan a HeyReach agent's tool surface from documentation alone. On the MCP path, the only authoritative enumeration is a live tools/list call against your own Connection URL. Treat anything else as hearsay.

This is a real cost. It means your capability audit is a runtime activity, it has to be repeated after HeyReach ships changes, and it cannot be pinned in a spec file that your CI checks against.

The tool surface you can pin down

If you want a documented, versioned, schema-complete tool list for HeyReach today, the Scalekit HeyReach connector docs publish one. Ten tools, each with typed parameters:

Tool
What it does
heyreach_check_api_key
Validates the connected credential before other calls
heyreach_get_all_campaigns
Lists campaigns with status and campaignAccountIds
heyreach_get_campaign_by_id
Returns one campaign with progress stats and sender accounts
heyreach_get_all_linkedin_accounts
Lists connected LinkedIn sender profiles
heyreach_get_all_lists
Lists lead lists with counts and linked campaigns
heyreach_get_leads_from_list
Paginates leads out of a specific list
heyreach_get_lead
Looks up one lead by LinkedIn profile URL
heyreach_add_leads_to_campaign
Adds up to 100 leads, each bound to a sender account
heyreach_get_conversations
Reads the unified LinkedIn inbox with filters
heyreach_get_overall_stats
Aggregates acceptance and reply rates by campaign and account

Comparing them where it matters for agents

With the enumeration caveat stated, the two paths still differ on properties you can verify from official documentation.

The dimensions that actually separate them

Dimension
HeyReach MCP server
HeyReach public API
Credential
MCP Key embedded in the workspace Connection URL
X-API-KEY request header
Credential lifetime
Rotate by generating a new key, which changes the URL
Never expires; can be deleted or deactivated
Identity boundary
Documented as per workspace
Documented as mapping to your organization
Per-user consent
No
No
Scope controls
None exposed
None exposed
Published manifest
No
Postman collection; no reachable OpenAPI document
Enumeration method
Live tools/list against your endpoint
Read the collection
Rate limit
Not documented separately; calls resolve to the same public API
300 requests per minute, organization-wide
Event subscriptions
No subscription primitive
Webhooks, configured as a separate surface
Headless execution
Yes, the credential is static
Yes
Transport
Remote HTTP; stdio clients bridge via mcp-remote
HTTPS REST

Where the gap bites

Two rows carry most of the weight. The first is event subscriptions. MCP tool calls are request and response; there is no push. Any agent that reacts to a reply the moment it lands needs HeyReach webhooks, which live outside the MCP surface entirely.

The second is the shared rate limit. Three hundred requests per minute sounds generous until an agent paginates a lead list with four thousand entries while a scheduled stats job runs alongside it.

The gap that is not there

Worth naming the absence: the headless gap does not exist here. On Salesforce or Slack, MCP forces an interactive OAuth flow and blocks background agents. HeyReach's MCP key is static, so a nightly job can hold it as easily as a chat client can. That is convenient, and it is exactly why the credential question gets harder rather than easier.

The auth path each one puts you on

Both paths hand your agent a bearer-equivalent secret with full workspace reach. The difference is where the secret sits, and where it leaks.

MCP puts the key in a URL

The MCP Key travels inside the Connection URL. That is why setup is a copy and paste, and it is also why the credential ends up in places you did not choose.

URLs get written to claude_desktop_config.json and equivalents. They get logged by forward proxies. They appear in shell history when someone tests with curl. A header-borne secret is redacted by convention in most tooling; a path-borne secret usually is not.

The API puts the key in a header

X-API-KEY is the better shape for the same secret. It stays out of URLs and request lines, and most logging middleware already knows to strip it.

The key itself is no weaker and no stronger. HeyReach documents it as non-expiring, which means the only lifecycle event is manual deletion. As explored in OAuth vs API keys for AI agents, static, non-expiring credentials are a structural liability in production systems.

Why the usual MCP argument does not apply

Across this series the structural point has been that MCP gives you a token per user while direct API calls give you a credential per user, and that neither solves storage, rotation, or revocation. HeyReach breaks the first half of that sentence.

Neither path produces per-user identity. There is no consent flow, no scope, and no way for HeyReach to distinguish which of your users triggered a call. Every action arrives at HeyReach as the workspace. What the user can and cannot do stops being enforceable by the provider, which means it becomes your problem.

What you own in production

Choosing a path does not change the operational load much. Both leave the same four things on your side of the line.

The rate budget is shared and org-wide

Three hundred requests per minute is a single pool. Your agent, your existing Zapier scenarios, and any human-facing integration draw from it together, and exceeding it returns 429.

Agentic workflows issue several sequential calls per user action. Pagination on heyreach_get_conversations or heyreach_get_leads_from_list compounds that quickly, since HeyReach's own defaults can return payloads in the hundreds of kilobytes. Cap your limits explicitly and back off on 429 from day one.

Rotation is a blast-radius event

Because keys never expire, rotation only happens when you force it. And because one key serves the entire workspace, rotating it breaks every agent, script, and integration using that workspace at the same moment.

On the MCP path this is worse, because generating a new MCP Key rewrites the Connection URL. Every client holding the old URL has to be reconfigured, not just re-keyed. This is a core example of the credential ownership problem that multi-tenant agent architectures must solve.

Offboarding has no provider-side hook

When a team member leaves, disabling their identity provider account does nothing to a HeyReach key that was minted eight months ago and pasted into a config file. There is no OAuth grant for your identity provider to cascade into.

The agent does not decide to keep using that credential. It just does.

Schema drift against an unpublished contract

HeyReach can add, rename, or change MCP tools without a versioned manifest for you to diff against. Your only detection mechanism is a tools/list call in CI that compares against a checked-in snapshot. Build that before you need it.

When to use MCP, when to use the API

The choice is narrower than usual here, because the auth models converge. It comes down to who is driving and what has to happen in real time.

Use the HeyReach MCP server when

  • A human is in the loop in an MCP client such as Claude or Cursor, and the workflow is exploratory: auditing a campaign, cleaning a list, reading the day's replies
  • You are running agency-style work where one workspace maps cleanly to one client, and the per-workspace Connection URL is the isolation boundary you actually want
  • You are prototyping and want a working tool surface without writing schemas
  • The task is read-heavy and bounded, so the shared rate budget is not at risk

Use the HeyReach API when

  • Your agent runs on a schedule and you need explicit control over pagination, retry, and backoff against the 300 per minute ceiling
  • You need to react to replies as they land, which requires webhooks rather than polling
  • You are building a deterministic pipeline and cannot absorb an unannounced tool-schema change
  • You need a specific endpoint and cannot confirm it exists on the MCP surface, since there is no manifest to check

The credential problem that exists on both paths

This is the part that determines whether your HeyReach agent survives its second customer.

One key, every workspace member

A single HeyReach credential grants full workspace access: launching campaigns, reading inbox conversations, modifying lead lists. There is no read-only variant and no per-tool scope.

In a multi-tenant B2B product, that means an agent acting for one user holds exactly the same reach as an agent acting for anyone else in that workspace. Attribution collapses. Your audit trail says the workspace did it, which is not an answer a security reviewer accepts. This is precisely why access control for multi-tenant AI agents requires a layer above whatever the provider exposes.

What you still have to build

Storage that is encrypted at rest and isolated per tenant. Resolution that fetches the right credential server-side so it never enters the agent runtime or the LLM context. Revocation that fails closed for one user without breaking the others. Logging that ties every tool call back to the human who authorized it.

None of that is on either HeyReach path. The token type is identical; the infrastructure is identical; the work is identical.

Building HeyReach agents with Scalekit

Scalekit's HeyReach connector is API key based, matching how HeyReach actually authenticates. What it adds is the per-user layer HeyReach does not have.

Register the connection and the per-user credential

Create the connection once in the Scalekit dashboard, then attach each user's HeyReach key to their identifier. The connectionName string must match the connection name configured in your dashboard exactly; this is the single most common integration error.

import { ScalekitClient } from '@scalekit-sdk/node' import 'dotenv/config' const scalekit = new ScalekitClient( process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET, ) // Call this when a user pastes their HeyReach key into your settings page. // 'heyreach' must match the connection name in your Scalekit dashboard. await scalekit.actions.upsertConnectedAccount({ connectionName: 'heyreach', identifier: 'user_123', credentials: { api_key: 'their-heyreach-api-key' }, })

There is no redirect and no consent screen, because HeyReach has neither. The key is vaulted from this point forward.

Retrieve the authorized surface, then execute

The agent does not load a connector catalog. It loads the tools this user's connected account is authorized to call, then runs the tool-calling loop against that surface.

import os import scalekit.client from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, ToolMessage scalekit_client = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) actions = scalekit_client.actions # page_size=100 so the connector's tool list is not truncated tools = actions.langchain.get_tools( identifier="user_123", providers=["HEYREACH"], page_size=100, ) tool_map = {t.name: t for t in tools} llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) messages = [HumanMessage( "Which of my active campaigns has the highest acceptance rate, " "and are there unread replies on it?" )] while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tc in response.tool_calls: result = tool_map[tc["name"]].invoke(tc["args"]) messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

The HeyReach key is resolved server-side on each call. It never reaches the agent process and never enters the model's context. This pattern is central to secure token management for AI agents at scale.

Proxy raw API calls when no tool fits

Because HeyReach's surface is not fully enumerable, you will eventually need an endpoint that has no prebuilt tool. The proxy path uses the same vaulted credential.

response = actions.request( connection_name="heyreach", identifier="user_123", path="/auth/CheckApiKey", method="GET", ) print("Credential valid:", response.status_code == 200)

Virtual MCP servers for multi-tool, multi-tenant agents

A HeyReach outreach agent rarely touches only HeyReach. It reads a CRM, drafts in a doc, and posts to Slack. That is where per-user isolation and tool scoping stop being nice to have.

Define the server once per agent role

A Virtual MCP server declares exactly which connections and which tools an agent can see. You create it once per role, not once per user, and you get a static mcp_server_url back.

import os from scalekit import ScalekitClient from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENV_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) vmcp_response = scalekit_client.actions.mcp.create_config( name="linkedin-reply-triage-agent", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="heyreach", tools=[ "heyreach_get_all_campaigns", "heyreach_get_conversations", "heyreach_get_overall_stats", ], ), McpConfigConnectionToolMapping( connection_name="slack", tools=["slack_send_message"], ), ], ) config_id = vmcp_response.config.id mcp_server_url = vmcp_response.config.mcp_server_url

A triage agent that only reads should not be able to call heyreach_add_leads_to_campaign. Here it cannot, because the tool is not on its server.

Mint a session token before each run

The endpoint is static. The identity is not. Before each run, confirm the user's connections are live, then mint a short-lived token bound to that user.

from datetime import timedelta accounts_response = scalekit_client.actions.mcp.list_mcp_connected_accounts( config_id=config_id, identifier="user_123", include_auth_link=True, ) for account in accounts_response.connected_accounts: if account.connected_account_status != "ACTIVE": print(f"{account.connection_name} needs auth: {account.authentication_link}") token_response = scalekit_client.actions.mcp.create_session_token( mcp_config_id=config_id, identifier="user_123", expiry=timedelta(minutes=30), ) mcp_server = { "url": mcp_server_url, "headers": {"Authorization": f"Bearer {token_response.token}"}, }

Why outreach agents need this specifically

HeyReach's own MCP endpoint is one static URL per workspace with one static key inside it. Sharing that across users means sharing everything.

A Virtual MCP server inverts it: one definition, a per-run token scoped to one user's connected accounts, and a tool list you chose deliberately. Trimming a forty-tool context down to five also removes roughly eight thousand tokens of overhead before the agent does any work. Surface reduction is the lever.

Observability, which HeyReach cannot give you

Outreach agents send messages to real prospects from real LinkedIn accounts. When something goes wrong, "which agent did this, for whom, and was it authorized" is not an academic question. Agent tool observability is what separates a system you can debug from one you can only restart.

What a shared key can tell you

Nothing useful. Every call arrives at HeyReach carrying the same organization-mapped credential. There is no sub, no acting party, and no consent record to point at.

If an agent enrolls the wrong two hundred leads, HeyReach's side of the story is that the workspace did it.

What per-user tool-call logs give you

Scalekit resolves the credential per user and logs the call. Every HeyReach tool invocation is attributed to the identifier that authorized it, retained for 90 days, and exportable to your SIEM, as described on the Scalekit HeyReach connector page.

That turns the question into a query. It also satisfies the audit-trail requirement your enterprise customers will raise long before they raise anything else about your agent. A proper audit trail for agent auth is a non-negotiable baseline for B2B SaaS.

Which one to build against

If a human is sitting in an MCP client and the work is exploratory, use HeyReach's MCP server. It is the fastest route to a working tool surface, and per-workspace Connection URLs are a reasonable isolation boundary for agency work.

If your agent runs unattended, needs webhook-driven reactions, or has to survive a schema change without an incident, build against the API and control your own pagination and backoff.

What does not change is the credential. Both paths hand you one static, non-expiring, workspace-wide key with no scopes and no user identity attached. Everything that makes that safe for a second customer is infrastructure you build or buy.

Talk to us

Building a HeyReach agent and want a second opinion on the auth model? Join the Scalekit community on Slack, or talk to an engineer if you need help now.

Browse the Scalekit HeyReach connector or read the HeyReach connector docs.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
zero upfront cost.

Every feature unlocked. No hidden fees.