RankParse

Outreach

Run AI-driven link-building outreach from your own Gmail. Your agent finds prospects and writes every email, you approve, and RankParse sends on a schedule.

Outreach turns competitor backlink data into a real link-building campaign. Your AI agent does the research, finds a contact at each domain and writes the copy through the RankParse tools. RankParse stores the campaign, and sends the emails from your connected Gmail account on a schedule with a daily cap, so replies land in your own inbox.

You approve before anything sends. When an agent launches a campaign through the RankParse MCP server, the emails go to your approval inbox instead of being queued. You read every email, remove any you do not like, and approve. Outreach is the one action that can never be set to run automatically.

Setup

  1. Add the RankParse MCP server to your agent. The outreach tools are on the API-key MCP endpoint only: https://mcp.rankparse.com/mcp for Claude Code, Cursor and other HTTP clients, or https://mcp.rankparse.com/ for clients that need the root path, with your API key. The secure OAuth connector used by Claude and ChatGPT on the web does not include outreach tools. See MCP server for the endpoint choice and client setup.
  2. Connect Gmail at Integrations. Emails are sent from that account.
  3. Start a campaign from Outreach and choose New campaign. The page gives you a ready-to-paste starter prompt that walks your agent through the whole flow: interview you about your site and competitors, mine competitor gaps for prospects, research a real contact at each domain, draft a short personalized email for each, show you everything, and only create and launch the campaign after you approve.

How a campaign runs

  1. Research. The agent builds a prospect list with get_competitor_gap and get_domain_authority (5 and 1 credits per call), then finds one real contact email per domain.
  2. Draft. It writes a short subject and body for each contact and shows you the drafts in chat.
  3. Create and fill. After you approve the drafts in chat, it calls outreach_create_campaign and outreach_add_contacts. This creates a draft campaign and stores the emails. Nothing is sent.
  4. Launch. It calls outreach_launch_campaign. For agents on the MCP server this creates an approval request and returns status: "awaiting_approval" with a review_url. A shortcut, propose_outreach_send, does steps 3 and 4 in one call.
  5. Approve. You open the review_url, read each email with its recipient, subject and body, optionally remove some, and approve. You get a daily email when items are waiting.
  6. Send. RankParse queues exactly the emails you approved. Sending is paced by your Gmail schedule and daily cap, so a campaign drains over days, not minutes.
  7. Track. Follow progress on the campaign page in the dashboard (stats, per-contact status, queued sends) or with outreach_get_campaign. Campaigns can be paused and resumed. Once an email is queued it can no longer be removed from the approval review.

Credits: creating campaigns, adding contacts, launching and sending cost 0 credits. Only the research calls (competitor gap, domain authority and the like) use credits.

What is held for approval

ActionBy an agent through MCPFrom the dashboard
Launch a campaign (send emails)Held for approvalYour own click, runs now
Raise the daily send limit, or switch auto-send onHeld for approvalApplies now
Lower the daily send limit, or switch sending offApplies immediatelyApplies now
Create a draft, add contacts, pause, resumeApplies immediately (nothing is sent)Applies now

Approval covers agents that use the RankParse MCP server, or that send the header X-RankParse-Client: mcp. A script that calls the REST routes below directly with your API key, without that header, launches immediately. See Where approval is enforced.

Rules for contacts

RuleValue
Contacts per add contacts callup to 100
Contacts per campaignup to 500
Contacts per agent approval requestup to 100
Per domainone contact per domain, and one per email address
Subjectup to 500 characters (aim for 2 to 5 words)
Bodyup to 10,000 characters, plain text
Nameup to 200 characters, optional
Already emailedAn address you contacted from an earlier campaign is skipped
Internationalized domainsUse the punycode (xn--) form

Contacts that fail a rule are not added and are returned in skipped with a reason: invalid_email, invalid_domain, missing_copy, copy_too_long, duplicate_email, duplicate_domain, campaign_full, or already_contacted. Add contacts to a campaign that has already launched to top it up; the new contacts stay inactive until the campaign is launched (and approved) again.

Sending

  • Daily cap. max_sends_per_day is between 1 and 100 and applies across all your campaigns. It defaults to 20.
  • Auto-send is a master switch. When it is off, a launch still queues emails but nothing sends until you turn it on; the launch response includes a warning.
  • Pausing one campaign holds its queued emails without losing them. Other campaigns keep sending.
  • Estimate. The launch response gives estimated_days, the queue divided by the daily cap, rounded up.

Tools

Available on the API-key MCP endpoint. Each is 0 credits.

ToolWhat it doesREST route
outreach_create_campaignCreate a draft campaign.POST /v1/outreach/campaigns
outreach_add_contactsAdd contacts with copy to a campaign.POST /v1/outreach/campaigns/:id/contacts
outreach_launch_campaignQueue the reviewed contacts (held for approval for agents).POST /v1/outreach/campaigns/:id/launch
outreach_get_campaignStatus and delivery counts.GET /v1/outreach/campaigns/:id
outreach_list_campaignsList campaigns, optionally for one website.GET /v1/outreach/campaigns
outreach_suggest_prospectsContext for topping up: capacity, queue and domains to exclude.GET /v1/outreach/campaigns/:id/prospecting
outreach_sending_statusGmail pipeline status.GET /v1/outreach/sending
outreach_configure_sendingChange the daily cap or auto-send.PATCH /v1/outreach/sending
outreach_pause_campaignPause a campaign.POST /v1/outreach/campaigns/:id/pause
outreach_resume_campaignResume a campaign.POST /v1/outreach/campaigns/:id/resume
propose_outreach_sendCreate or top up a campaign and ask for approval in one call.POST /v1/proposals with kind: "outreach_send"

REST API

The same operations are available over REST at https://api.rankparse.com/v1/outreach with your X-API-Key. All routes cost 0 credits, share the 60 requests per minute limit, and need Gmail connected for anything that sends. Errors use the standard { error, code, message } shape.

Create a campaign

POST /v1/outreach/campaigns

FieldTypeRequiredDescription
namestringYesUp to 200 characters.
your_domainstringYesThe site you are building links for. URL prefixes and www. are stripped.
goalstringNoA note for the campaign record.
site_idstringNoA website id from GET /v1/websites. Omit to leave the campaign unassigned.
curl -X POST "https://api.rankparse.com/v1/outreach/campaigns" \
  -H "X-API-Key: rp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "SaaS blogs, competitor gap Oct 2026", "your_domain": "example.com", "site_id": "site_abc123"}'
import requests

res = requests.post(
    "https://api.rankparse.com/v1/outreach/campaigns",
    headers={"X-API-Key": "rp_your_key"},
    json={
        "name": "SaaS blogs, competitor gap Oct 2026",
        "your_domain": "example.com",
        "site_id": "site_abc123",
    },
)
campaign = res.json()
print(campaign["id"], campaign["status"])
const res = await fetch("https://api.rankparse.com/v1/outreach/campaigns", {
  method: "POST",
  headers: { "X-API-Key": "rp_your_key", "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "SaaS blogs, competitor gap Oct 2026",
    your_domain: "example.com",
    site_id: "site_abc123",
  }),
});
const campaign = await res.json();
console.log(campaign.id, campaign.status);
{ "id": "V1StGXR8_Z5jdHi6B-myT", "status": "draft", "max_contacts": 500, "site_id": "site_abc123" }

Add contacts

POST /v1/outreach/campaigns/:id/contacts with { "contacts": [ ... ] }. Works on a draft, a ready-to-review campaign, or a launched one (a top-up).

curl -X POST "https://api.rankparse.com/v1/outreach/campaigns/V1StGXR8_Z5jdHi6B-myT/contacts" \
  -H "X-API-Key: rp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [{
      "email": "ann@alpha-blog.com",
      "name": "Ann Lee",
      "domain": "alpha-blog.com",
      "subject": "your AI tools guide",
      "body": "Hi Ann, I read your guide to AI writing tools and ...",
      "domain_authority": 54
    }]
  }'
{
  "added": 1,
  "total_contacts": 1,
  "skipped": []
}

On a launched campaign the response also carries next_step, reminding you that the new contacts are inactive until the next launch. Skipped contacts look like { "email": "bob@beta.com", "reason": "already_contacted" }.

Launch

POST /v1/outreach/campaigns/:id/launch (no body). Safe to call again: it only queues contacts that are not already queued or sent.

Direct REST call, without the agent header:

{
  "queued": 18,
  "suppressed": 2,
  "auto_send_enabled": true,
  "max_sends_per_day": 20,
  "estimated_days": 1
}

suppressed counts contacts skipped because you already emailed them from another campaign. A warning field appears when auto-send is off, and paused_warning when the campaign is paused. If every contact was suppressed, the response is queued: 0 with a message.

Agent call (MCP, or the X-RankParse-Client: mcp header) in an account with the inbox enforced:

{
  "queued": 0,
  "suppressed": 0,
  "auto_send_enabled": true,
  "max_sends_per_day": 20,
  "estimated_days": 0,
  "status": "awaiting_approval",
  "proposal_id": "prp_K3mP9xQ2vLw8Rt5Yn1BzA",
  "review_url": "https://rankparse.com/dashboard/sites/site_abc123/today?proposal=prp_K3mP9xQ2vLw8Rt5Yn1BzA",
  "message": "Sending now waits for the user's approval in RankParse (...)."
}

If status is approved, a person already approved this exact set and it is running; do not launch again. An approval request carries at most 100 contacts, so a larger campaign needs a further launch after the first is approved. See Proposals.

Read a campaign

  • GET /v1/outreach/campaigns/:id returns id, name, your_domain, goal, status, paused, created_at, site_id, site_host and contacts with total, awaiting_launch, queued, sending, sent and skipped.
  • GET /v1/outreach/campaigns returns { "campaigns": [...] }, newest first, at most 100, each with total_contacts, queued_contacts, sent_contacts and paused. Add ?site_id= to filter to one website.
  • GET /v1/outreach/campaigns/:id/prospecting returns the campaign, its capacity, its send queue, exclude_domains (every domain you have used in any campaign, to filter new prospects against), exclude_domains_truncated, recommended_batch_size and a next_step sentence.

Campaign status is one of draft, ready_to_review, pushing (a launch is running), pushed (launched; can still be topped up) or a legacy wizard state.

Sending settings

GET /v1/outreach/sending returns connected, gmail_email, auto_send_enabled, max_sends_per_day, sent_today, remaining_today, queued_across_campaigns and estimated_days_to_drain. Without Gmail it returns { "connected": false, "message": "..." }.

PATCH /v1/outreach/sending changes the settings. At least one field is required.

FieldTypeDescription
max_sends_per_dayinteger1 to 100, across all campaigns.
auto_send_enabledbooleanfalse stops all sending, true resumes it.

A direct call replies { "ok": true }. For an agent, lowering the cap or turning sending off applies immediately, while raising the cap or turning sending on is held for approval and replies 202 with ok: true, status, proposal_id, review_url and message. A mixed request applies the stop now and proposes the rest; the response then includes applied. If another sending change is already approved and running, the increase is refused with 409 change_in_progress.

Pause and resume

POST /v1/outreach/campaigns/:id/pause and /resume return { "ok": true, "paused": true } or { "ok": true, "paused": false }. Repeating either is harmless and adds a message.

Errors

HTTPCodeWhen
400invalid_jsonThe body is not valid JSON.
400invalid_name, invalid_domain, invalid_site_idA required field is missing or malformed.
400no_contactsNothing to add, or no ready contacts to launch.
400too_many_contactsMore than 100 contacts in one call.
400gmail_not_connectedConnect Gmail first.
400sending_provider_unsupportedOnly Gmail campaigns can be launched this way.
400invalid_send_cap, invalid_auto_send, nothing_to_updateBad PATCH /sending body.
403capability_missingYour role in the workspace does not allow this.
404campaign_not_found, site_not_foundThe campaign or website is not in your account.
409campaign_not_editableThe campaign is mid-launch or in a state that cannot take contacts. Retry shortly.
409campaign_launch_in_progressAnother launch of this campaign is running. Nothing was lost; retry.
409change_in_progressA different sending change is already approved and running.
429rate_limitedMore than 60 requests in a minute.

Agent-origin launches and sending changes can also return the proposal errors listed on Proposals, such as too_many_pending_proposals.

Troubleshooting

On this page