> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appeeky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Link Building

> Find pages that already rank for your keywords, send personalized pitches from your own mailbox, and track every conversation until the link goes live.

**Link building** finds pages that rank for the keywords you track and could link to your app: roundups, review sites, resource pages, directories and pages with broken links. Appeeky looks for a contact address, writes a pitch based on what the page is about, sends it from your own mailbox and follows up until you get an answer.

> [!NOTE]
>
> Requires a **Startup** or **Agentic Scale** plan, an [SEO project](https://docs.appeeky.com/docs/seo-overview.md) with tracked keywords, and **Link building** turned on in the project's settings. To send email you also need a connected mailbox. In the dashboard: **SEO for Apps → Link building**.

***

## How it works

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart LR
  A[Rank scans] --> B[Prospects]
  B --> C[Draft pitch]
  C --> D[You review]
  D --> E[Send + follow-ups]
  E --> F{Answer}
  F -->|Link live| G[Won → backlink]
  F -->|Declined| H[Lost]
```

1. **Prospects.** Appeeky reads the results from your project's recent rank scans, opens each candidate page to classify it and find a contact, and skips pages that already link to you.
2. **Pitch.** A draft email is written from your product description and the prospect page. Nothing is sent until you approve it, unless autopilot is on.
3. **Send.** Approved pitches go out from your mailbox, within its daily limit.
4. **Follow up.** If nobody answers, follow-ups are sent about 4 days apart, 2 by default. A reply or a bounce stops them.
5. **Close.** Mark the thread **won** when the link is live, and it is added to your [backlinks](https://docs.appeeky.com/docs/seo-backlinks.md). Mark it **lost** if they say no.

When Link building is on, Appeeky also looks for new prospects once a week and drafts pitches for up to 10 of the strongest prospects that have a contact address, so you have a queue to review.

***

## Set up

**1. Describe your product**

In the project's **Settings**, fill in the product description, target audience and outreach persona (who the emails come from). Prospect scoring and pitches depend on them.

**2. Turn on Link building**

Switch on **Link building** in the project's **Settings**, or send `outreachEnabled: true` to `PATCH /v1/seo/projects/:id`.

**3. Connect a mailbox**

Under **Settings → Outreach mailbox**, add the address you want to send from. Outreach is sent over your own SMTP server, so replies land in your normal inbox. Add IMAP details too, so Appeeky can see replies and stop follow-ups.

**4. Find prospects**

Click **Find prospects** on the Link building tab, or call `POST /v1/seo/opportunities/discover`.

> [!WARNING]
>
> Outreach emails real people from your address. Read each draft before you approve it, and only turn on autopilot once you trust the drafts.

***

## Mailboxes

| Method | Endpoint | Description |
| - | - | - |
| GET | `/v1/seo/settings/mailboxes` | Connected mailboxes with their daily limit and how many sent today |
| PUT | `/v1/seo/settings/mailboxes` | Add or update a mailbox |
| POST | `/v1/seo/settings/mailboxes/:id/verify` | Test the connection again |
| DELETE | `/v1/seo/settings/mailboxes/:id` | Remove a mailbox |

`PUT` needs `fromName`, `fromEmail`, `smtpHost`, `smtpUser` and `smtpPass`. Optional: `label`, `replyTo`, `smtpPort` (default `587`), `smtpSecure`, `imapHost`, `imapPort` (default `993`), `imapSecure`, `imapUser`, `imapPass` and `dailySendLimit` (default `30`, at most `50`). The connection is tested before the mailbox is saved; a failed test returns `422 smtp_verify_failed`.

Use an app password from your email provider rather than your account password.

***

## Prospects

| Method | Endpoint | Description |
| - | - | - |
| GET | `/v1/seo/opportunities?project=` | List prospects |
| POST | `/v1/seo/opportunities/discover` | Find new prospects now |
| POST | `/v1/seo/opportunities` | Add one page as a prospect: `projectId`, `url` |
| PATCH | `/v1/seo/opportunities/:id` | Set `status` and optional `notes` |
| POST | `/v1/seo/opportunities/:id/draft` | Write a pitch for the prospect |

Each prospect has a type (`listicle`, `review_site`, `broken_link`, `resource_page` or `directory`), a 0–100 relevance score, the keyword and position it was found at, a contact email or contact form URL, and any competitors the page already mentions.

### Find prospects

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.appeeky.com/v1/seo/opportunities/discover \
  -H "X-API-Key: $APPEEKY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "projectId": "PROJECT_ID", "windowDays": 14, "maxInspections": 40 }'
```

| Field | Description |
| - | - |
| `projectId` | Required |
| `windowDays` | How many days of rank scan results to read, 1–90. Default `14` |
| `maxInspections` | Most pages to open, 1–100. Default `40` |

Discovery reuses results from your rank scans, so it costs 0 credits. Run a rank scan first if the project is new.

### List filters

| Param | Description |
| - | - |
| `status` | `new`, `queued`, `contacted`, `replied`, `won`, `rejected` or `ignored` |
| `minRelevance` | 0–100 |
| `hasContact` | `true` for prospects with a contact address |
| `limit`, `offset` | Paging. `limit` is 1–200, default `50` |

Set a prospect to `ignored` to drop it, or to `won` when a link went live without outreach.

### Draft a pitch

`POST /v1/seo/opportunities/:id/draft` returns a `draft` thread. Optional body fields: `mailboxId` to choose the sending mailbox, and `autoQueue: true` to approve it for sending right away. Prospects with only a contact form always stay drafts: copy the pitch into the form yourself.

***

## Outreach threads

A thread is one conversation with one prospect: the pitch, follow-ups and replies.

| Status | Meaning |
| - | - |
| `draft` | Written, waiting for you |
| `queued` | Approved, waiting to be sent |
| `sent` | Pitch sent, follow-ups scheduled |
| `replied` | They answered. Follow-ups stopped |
| `bounced` | The email bounced |
| `won` | The link is live |
| `lost` | They declined or never answered |
| `stopped` | You stopped follow-ups |

| Method | Endpoint | Description |
| - | - | - |
| GET | `/v1/seo/threads?project=` | List threads (`?status=`, `?limit=` 1–200, default `50`) |
| GET | `/v1/seo/threads/:id` | Thread with every message and its prospect |
| PATCH | `/v1/seo/threads/:id` | Edit `subject`, `pitchBody`, `contactEmail`, `mailboxId` or `maxFollowups` (0–5) |
| POST | `/v1/seo/threads/:id/queue` | Approve for sending. Optional `sendAt` (ISO time) to hold it until then |
| POST | `/v1/seo/threads/:id/send` | Send now |
| POST | `/v1/seo/threads/:id/stop` | Stop follow-ups without closing the thread |
| POST | `/v1/seo/threads/:id/won` | Mark won and register the backlink |
| POST | `/v1/seo/threads/:id/lost` | Mark lost |

Only `draft` and `queued` threads can be edited. Use **stop** when someone asks not to be contacted again.

### Mark a thread won

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.appeeky.com/v1/seo/threads/THREAD_ID/won \
  -H "X-API-Key: $APPEEKY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sourceUrl": "https://example.com/best-focus-apps", "targetUrl": "https://focustimer.app" }'
```

`sourceUrl` defaults to the prospect page and `targetUrl` to your project's website. The link is checked right away and appears in your [backlinks](https://docs.appeeky.com/docs/seo-backlinks.md).

### Errors

| Status | Code | When |
| - | - | - |
| 409 | `not_editable` | The thread was already sent |
| 409 | `not_queueable` | Only drafts can be queued |
| 409 | `skipped_no_mailbox` | No mailbox is connected |
| 409 | `skipped_mailbox_limit` | The mailbox reached its daily limit. Try again tomorrow |
| 409 | `skipped_no_contact_email` | The prospect has no email address. Use its contact form |
| 409 | `skipped_outreach_disabled` | Link building is off for the project |
| 422 | `unreachable_page` | A prospect page you added couldn't be loaded |
| 502 | `send_failed` | The message couldn't be sent from your mailbox |

***

## Autopilot

With **Outreach autopilot** on, new email pitches are queued for sending without waiting for your approval. Contact-form prospects still wait for you. Follow-ups are sent on schedule either way. Turn it on in the project's **Settings** or with `outreachAutopilot: true`.

***

## MCP

| Tool | Description |
| - | - |
| `seo_mailboxes_list` | Connected mailboxes. Mailboxes are added in the dashboard |
| `seo_opportunities_list` | List prospects |
| `seo_opportunities_discover` | Find new prospects |
| `seo_opportunities_add` | Add one page as a prospect |
| `seo_opportunities_review` | Change a prospect's status |
| `seo_opportunities_draft_pitch` | Write a pitch |
| `seo_threads_list` | List threads |
| `seo_threads_get` | Read a thread |
| `seo_threads_update` | Edit a draft |
| `seo_threads_queue` | Approve for sending |
| `seo_threads_send` | Send now |
| `seo_threads_stop` | Stop follow-ups |
| `seo_threads_won` | Mark won and register the backlink |
| `seo_threads_lost` | Mark lost |

Example prompt: *"Find link prospects for my Focus Timer project and draft pitches for the five most relevant review sites. Don't send anything."*

***

## Tips

* Start with `broken_link` and `listicle` prospects. They have the clearest reason to add you.
* Keep the daily send limit low on a new address.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.