List the people found at a prospect's site
curl --request GET \
--url https://api.snowseo.com/v3/outreach/prospects/{id}/people \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.snowseo.com/v3/outreach/prospects/{id}/people"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.snowseo.com/v3/outreach/prospects/{id}/people', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.snowseo.com/v3/outreach/prospects/{id}/people",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.snowseo.com/v3/outreach/prospects/{id}/people"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.snowseo.com/v3/outreach/prospects/{id}/people")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snowseo.com/v3/outreach/prospects/{id}/people")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"people": [
{
"id": "<string>",
"isNew": true,
"createdAt": "<string>",
"updatedAt": "<string>",
"lastActivityAt": "<string>",
"fullName": "<string>",
"title": "<string>",
"seniority": "<string>",
"companyName": "<string>",
"linkedinUrl": "<string>",
"location": "<string>",
"countryCode": "<string>",
"status": "<string>",
"lastError": "<string>",
"isTarget": true,
"email": {
"id": "<string>",
"email": "<string>",
"name": "<string>",
"role": "<string>",
"verifiedStatus": "<string>",
"confidence": 123,
"isPrimary": true
},
"emails": [
{
"id": "<string>",
"email": "<string>",
"name": "<string>",
"role": "<string>",
"verifiedStatus": "<string>",
"confidence": 123,
"isPrimary": true
}
]
}
]
}Backlink Outreach
Contacts
Find who to pitch at a prospect’s site, then resolve the email addresses of the people worth writing to.
GET
/
v3
/
outreach
/
prospects
/
{id}
/
people
List the people found at a prospect's site
curl --request GET \
--url https://api.snowseo.com/v3/outreach/prospects/{id}/people \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.snowseo.com/v3/outreach/prospects/{id}/people"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.snowseo.com/v3/outreach/prospects/{id}/people', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.snowseo.com/v3/outreach/prospects/{id}/people",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.snowseo.com/v3/outreach/prospects/{id}/people"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.snowseo.com/v3/outreach/prospects/{id}/people")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snowseo.com/v3/outreach/prospects/{id}/people")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"people": [
{
"id": "<string>",
"isNew": true,
"createdAt": "<string>",
"updatedAt": "<string>",
"lastActivityAt": "<string>",
"fullName": "<string>",
"title": "<string>",
"seniority": "<string>",
"companyName": "<string>",
"linkedinUrl": "<string>",
"location": "<string>",
"countryCode": "<string>",
"status": "<string>",
"lastError": "<string>",
"isTarget": true,
"email": {
"id": "<string>",
"email": "<string>",
"name": "<string>",
"role": "<string>",
"verifiedStatus": "<string>",
"confidence": 123,
"isPrimary": true
},
"emails": [
{
"id": "<string>",
"email": "<string>",
"name": "<string>",
"role": "<string>",
"verifiedStatus": "<string>",
"confidence": 123,
"isPrimary": true
}
]
}
]
}Getting someone to write to is deliberately two steps: first find out who works at a site, then buy an address only for the people you actually want. That split is what stops you paying for forty addresses when one person was the right one.
What
Requests are scoped to the brand your API key belongs to. See Authentication.
Find people
POST /outreach/prospects/find-people
Open the request and response reference.
Looks up the people worth pitching at one site or a batch of them - editors, writers, whoever can actually add the link. Nothing is bought here: you get names, job titles and seniority so you can decide.
Body: prospectIds, up to 50. Optionally pass terms, 3-25 distinct job titles to match; omit it for the default editorial, SEO, marketing, and owner roles.
Runs in the background. The response has enqueuedCount, enqueuedProspectIds, skipped, and creditsCharged. Poll Outreach Prospects while each enqueued site’s status is finding_people, then read the result with List a prospect’s people.
Costs 5 AI credits per site. Sites whose search is already running are skipped and cost nothing, so a retry is safe. Do not re-run it on prospects that already have people.
GET /outreach/prospects/people-search-terms returns suggested title groups, defaults, and the allowed term count before a custom search.
List a prospect’s people
GET /outreach/prospects/{id}/people
Everyone found at one site.
| Field | Description |
|---|---|
fullName | Their name |
title | Job title - the thing worth deciding on |
seniority | Founder, C-Suite, Vice President, Director, and so on |
companyName | Where they actually work. Often not the site being pitched, since people search returns guest authors and contributors |
linkedinUrl | Their profile, when there is one |
status | pending, enriching, enriched, no_email, failed |
email | The resolved address, or null if you have not bought one yet |
For a link on a blog post, a content editor or head of content answers far more reliably than a founder. Read
title, not seniority.List every person
GET /outreach/prospects/people
The same rows across all prospects, with their site, role and resolved address, for export. Cap with limit; the response flags when the ceiling was hit.
Resolve email addresses
Use Find Outreach Email for people at one prospect, or Find Emails in Bulk for people across prospects. Both pages render the request and response schemas from OpenAPI. Costs 10 AI credits per person actually looked up. Anyone already enriched or mid-lookup is dropped server-side and costs nothing, so a retry is safe. Anyone with no findable address is refunded automatically.There is no product cap on how many people you enrich at once, only a request-size bound well above any real contact list. The cost is per person, so check the count before you send it.
List a prospect’s addresses
GET /outreach/prospects/{id}/emails
Every address found for one prospect, best first. The id of a row here is the prospectEmailId that Queue pitches and Draft a pitch take.
| Field | Description |
|---|---|
email | The address |
name / role | Who it belongs to |
verifiedStatus | valid, catchall, greylisted, unknown, invalid |
confidence | 0-100 |
sourceLayer | How it was found |
isPrimary | The address to use for the person it belongs to |
What verifiedStatus means
| Value | Meaning | Safe to send? |
|---|---|---|
valid | Their mail server confirmed the inbox exists | Yes |
catchall | The server accepts mail to any address, so this exact inbox is unproven | Usually, expect the odd bounce |
greylisted | The server asked us to check back later, so the check did not finish | Retry later |
unknown | Their mail server could not be reached | Your call |
invalid | The server rejected the address outright | No - it will bounce |
Sending to
invalid addresses is the fastest way to damage a sending domain’s reputation, and a held-back reputation affects every email you send afterwards. Filter them out before queueing.Choose a person’s address
PATCH /outreach/prospects/{id}/emails/{emailId}
Body: isPrimary: true.
Picks which of one person’s addresses to write to, so promoting one leaves the other people at the site untouched. Most people have a single address, where it is already set.
Choose who to write to
PATCH /outreach/prospects/{id}/people/{personId}
Body: isTarget - true, false or null.
Marks one person as the site’s outreach target and clears the flag on the others. false rules a person out, and null leaves it undecided, which is the default: with nobody chosen, the strongest address wins.Was this page helpful?

