Inbound link-building API — autonomous negotiator for link requests
An autonomous negotiator that handles inbound link-building emails on your behalf. Drafts (and optionally sends) replies to negotiate swaps, paid placements, guest posts, and insertions — with eval gates that escalate to a human.
The inverse of outreach: an autonomous negotiator that handles inbound link-building requests on your behalf. Watches your connected inbox, drafts (and optionally sends) responses to negotiate link swaps, paid placements, guest posts, and link insertions. You configure eval gates — conditions that escalate to a human (e.g., partner asks for money, sender DR is below threshold, message looks like spam).
Conceptual overview
Every inbound link-building email becomes an InboundMessage. The agent (using the inbound_negotiator skill) decides what to do:
new email lands
↓
InboundMessage created
↓
classified (intent, sender DR, target page, prior history with partner)
↓
eval gates checked
↓
either: drafts reply autonomously OR escalates → WAITING_APPROVAL
↓ ↓
sent + LinkBuildingEvent logged human reviews + decidesThree layers of control:
| Layer | What it controls |
|---|---|
| Workspace settings | Master switch (on/off), default tone, default targeting angles you'll consider, default escalation thresholds |
| Per-account settings | Per partner: "auto-respond OK", "always escalate", "decline by default" |
| Eval gates | Conditional rules — if message mentions $X+, escalate; if senderDR < 25, decline; if requestedAt > 3am, hold |
Per-partner history is preserved on LinkBuildingRelationship — every inbound + every outbound reply shows up on the relationship timeline, so the next inbound has full context.
→ Concept: Link Building → Concept: Eval Gates → Concept: Approval Workflows
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/link-building/inbound | List inbound messages |
| GET | /v1/link-building/inbound/{id} | Get one inbound message + draft state |
| POST | /v1/link-building/inbound/ingest | Ingest a message (Gmail/Outlook webhook target) |
| POST | /v1/link-building/inbound/{id}/draft | Re-draft a response |
| POST | /v1/link-building/inbound/{id}/approve | Approve and send draft |
| POST | /v1/link-building/inbound/{id}/reject | Reject (decline, mark spam, archive) |
| GET | /v1/link-building/inbound/pending | List inbound items waiting for manual action |
| GET | /v1/link-building/inbound/history | Full message history with a partner |
| CRUD | /v1/link-building/inbound/settings | Workspace-level inbound behavior |
| CRUD | /v1/link-building/inbound/account-settings/{accountId} | Per-partner overrides |
| CRUD | /v1/link-building/inbound/eval-gate/{...} | Eval gate definitions |
GET /v1/link-building/inbound
curl -G .../v1/link-building/inbound \
--data-urlencode "status=DRAFT_READY,PENDING_REVIEW" \
--data-urlencode "since=2026-05-20T00:00:00Z" \
--data-urlencode "limit=50"{
"data": [
{
"id": "msg_***",
"subject": "Quick request — guest post on Acme blog",
"fromEmail": "alex@partnermag.com",
"fromDomain": "partnermag.com",
"senderDR": 38,
"classification": "guest_post_pitch",
"status": "DRAFT_READY",
"linkedRelationshipId": "rel_***",
"linkedAccountId": "acct_***",
"receivedAt": "2026-05-23T11:32:00Z",
"escalatedReason": null
},
{
"id": "msg_***",
"subject": "Re: paid link insertion offer",
"fromEmail": "...",
"classification": "paid_link_insertion",
"status": "PENDING_REVIEW",
"escalatedReason": "Eval gate matched: payment_request_escalation"
}
],
"total": 12
}| Param | Notes |
|---|---|
status | NEW, DRAFT_READY, SENT, PENDING_REVIEW, DECLINED, MARKED_SPAM |
classification | guest_post_pitch, link_swap, link_insertion, paid_link_insertion, partnership, update_link, other |
escalatedOnly | true to filter to inbound that's waiting for review |
accountId | All messages from one partner |
GET /v1/link-building/inbound/{id}
curl .../v1/link-building/inbound/msg_***{
"id": "msg_***",
"subject": "Quick request — guest post on Acme blog",
"fromEmail": "alex@partnermag.com",
"fromName": "Alex Partner",
"fromDomain": "partnermag.com",
"senderDR": 38,
"originalBody": "Hi team,\n\nLove your blog. I'd love to contribute a guest post on ...",
"receivedAt": "2026-05-23T11:32:00Z",
"classification": "guest_post_pitch",
"classificationConfidence": 0.91,
"linkedRelationshipId": "rel_***",
"linkedAccountId": "acct_***",
"status": "DRAFT_READY",
"draft": {
"subject": "Thanks for reaching out — guest post specifics",
"body": "Hi Alex,\n\nThanks for the kind words. We're open to contributors ...",
"draftedBy": "agent",
"agentId": "agt_***",
"invocationId": "inv_***",
"draftedAt": "2026-05-23T11:34:00Z",
"tone": "friendly",
"anglesConsidered": ["guest_post", "link_insertion"]
},
"evalGatesEvaluated": [
{ "gateId": "payment_request_escalation", "matched": false },
{ "gateId": "low_dr_decline", "matched": false }
],
"prevExchanges": 0
}POST /v1/link-building/inbound/ingest
Webhook target for Gmail / Outlook integrations. Most users set this up once and never call it directly.
curl -X POST .../v1/link-building/inbound/ingest \
-H "Content-Type: application/json" \
-d '{
"source": "gmail",
"messageId": "<gmail-message-id>",
"from": { "email": "alex@partnermag.com", "name": "Alex Partner" },
"to": ["seo@acme.com"],
"subject": "Quick request — guest post on Acme blog",
"body": "Hi team, ...",
"receivedAt":"2026-05-23T11:32:00Z"
}'CitationBench classifies, runs eval gates, drafts a response (if gates pass), and returns the new InboundMessage.
POST /v1/link-building/inbound/{id}/draft
Re-draft the response (e.g., after editing the targeting angle or the tone).
curl -X POST .../v1/link-building/inbound/msg_***/draft -d '{
"tone": "firm",
"angle": "link_insertion",
"customInstructions": "Decline guest post but offer a paid link-insertion alternative."
}'Returns the new draft (overwrites the previous).
POST /v1/link-building/inbound/{id}/approve
curl -X POST .../v1/link-building/inbound/msg_***/approve -d '{
"edits": {
"body": "Hi Alex, thanks — yes, here's our methodology PDF ..."
},
"scheduleAt": "2026-05-24T09:00:00-04:00"
}'Sends the (optionally edited) draft. Creates a LinkBuildingEvent. Status moves to SENT.
POST /v1/link-building/inbound/{id}/reject
curl -X POST .../v1/link-building/inbound/msg_***/reject -d '{
"action": "decline",
"reason": "Off-topic",
"markRelationship": "NOT_INTERESTED"
}'action values:
decline— send a polite decline (templated)mark_spam— move to spam, no responsearchive_silent— archive without respondingblock_sender— add sender to workspace blocklist
GET /v1/link-building/inbound/pending
curl .../v1/link-building/inbound/pendingThe action queue for humans. Same shape as the list endpoint, filtered to PENDING_REVIEW and grouped by why they were escalated.
{
"byReason": {
"payment_request": [
{
"id": "msg_***",
"subject": "Re: paid link insertion offer",
"fromEmail": "..."
}
],
"low_sender_dr": [],
"suspicious_content": [
{ "id": "msg_***", "subject": "...", "fromEmail": "..." }
],
"first_contact_with_high_value_account": [{ "id": "msg_***", "...": "..." }]
},
"total": 7
}GET /v1/link-building/inbound/history
Full message history with one partner (across both inbound and outbound).
curl -G .../v1/link-building/inbound/history \
--data-urlencode "accountId=acct_***"Returns the merged event timeline (inbound messages + outbound emails + status changes).
CRUD: /v1/link-building/inbound/settings
curl .../v1/link-building/inbound/settings{
"enabled": true,
"connectedInbox": {
"type": "gmail",
"address": "seo@acme.com",
"connectedAt": "..."
},
"defaultTone": "friendly",
"defaultAnglesYouConsider": ["guest_post", "link_insertion", "link_swap"],
"autoSendIfAllGatesPass": false,
"responseTimeoutDays": 7
}curl -X PATCH .../v1/link-building/inbound/settings -d '{
"autoSendIfAllGatesPass": true,
"defaultTone": "firm"
}'CRUD: /v1/link-building/inbound/account-settings/{accountId}
Per-partner overrides.
curl -X PUT .../v1/link-building/inbound/account-settings/acct_*** -d '{
"mode": "always_escalate",
"customNotes": "Long-time partner; double-check anything beyond a friendly reply"
}'mode values:
inherit(default) — use workspace settings + eval gatesauto_respond— always auto-respond, skip eval gatesalways_escalate— always require human reviewauto_decline— automatic polite declineblock— auto-spam every inbound from this account
CRUD: /v1/link-building/inbound/eval-gate
See Eval Gates concept for the rule language. CRUD operations:
curl .../v1/link-building/inbound/eval-gate # list
curl -X POST .../v1/link-building/inbound/eval-gate # create
curl -X PATCH .../v1/link-building/inbound/eval-gate/gate_***
curl -X DELETE .../v1/link-building/inbound/eval-gate/gate_***
curl -X POST .../v1/link-building/inbound/eval-gate/gate_***/test # test against historical inboundMCP
> What inbound link-building messages need my review?Claude calls link_building.inbound.pending.
> Show the message from alex@partnermag.com.Claude calls link_building.inbound.list + link_building.inbound.get.
> Approve and send the draft. Add a quick note that I'll send the methodology PDF.Claude calls link_building.inbound.approve with edits.
> Always escalate inbound from engineering-blog.com — they're a high-value partner.Claude calls link_building.inbound.account_settings.update.
Errors
| Status | Code | Cause |
|---|---|---|
| 404 | inbound_message_not_found | — |
| 422 | already_responded | Trying to draft/approve a message that's already been sent |
| 422 | eval_gate_blocks | A gate forbids auto-send |
| 503 | inbox_unavailable | Gmail / Outlook connection failed |
Cost
| Action | Credits |
|---|---|
| Per inbound classified | 0.5 |
| Per draft | 3 |
| Per re-draft | 3 |
| Approve + send | 2 (the send) |
| Reject (decline send) | 1 |
| GETs | free |
Use cases (string things together)
A. Set up the autonomous responder
# 1. Connect Gmail
curl -X POST .../v1/link-building/inbound/settings -d '{ "enabled": true, "connectedInbox": { "type": "gmail" } }'
# (OAuth flow ...)
# 2. Set up two essential eval gates
curl -X POST .../v1/link-building/inbound/eval-gate -d '{
"name": "payment_request",
"when": { "llm_check": "Is the sender asking for money?" },
"then": { "action": "escalate_to_approval" }
}'
curl -X POST .../v1/link-building/inbound/eval-gate -d '{
"name": "low_dr_decline",
"when": { "field_lt": { "senderDR": 20 } },
"then": { "action": "decline" }
}'
# 3. Enable auto-send when all gates pass
curl -X PATCH .../v1/link-building/inbound/settings -d '{ "autoSendIfAllGatesPass": true }'B. Daily approval queue
curl .../v1/link-building/inbound/pending | jq '.byReason'Pipe to your portal or Slack.
C. Bulk-mark partners
for ACCT in acct_A acct_B acct_C; do
curl -X PUT .../v1/link-building/inbound/account-settings/$ACCT -d '{ "mode": "always_escalate" }'
doneD. Audit what the agent declined last month
curl -G .../v1/link-building/inbound \
--data-urlencode "status=DECLINED" \
--data-urlencode "since=$(date -u -d '30 days ago' -Iseconds)"Related
- API: Link Building · serp outreach
- API: Link Building · CRM
- API: Link Building · campaign management
- Concept: Link Building
- Concept: Eval Gates
- Concept: Approval Workflows
- Playbook: Auto-respond to link requests
Competitor outreach
Seed a campaign with a competitor domain. The agent pulls their backlinks via Ahrefs, filters for quality and relevance, discovers contacts, and drafts personalized outreach pitching your content as a parallel option.
Campaign management
Unified campaign endpoints across SERP, competitor, and custom outreach. List campaigns, read metrics, pause and resume, send one-off emails, and respond to inbound replies from one endpoint family.