curl --fail-with-body --max-time 30 -X POST "https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members" \
-H "Authorization: Bearer $FRESHTALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status":"watching",
"apply":"selected",
"urls":["https://www.linkedin.com/in/derek-morrow"]
}'
curl --fail-with-body --max-time 30 -X POST "https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members?status=proposed&stint=alum" \
-H "Authorization: Bearer $FRESHTALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"watching","apply":"filter"}'
const id = "550e8400-e29b-41d4-a716-446655440000";
const response = await fetch(`https://api.freshtalent.ai/v1/targets/${id}/members`, {
method: "POST",
signal: AbortSignal.timeout(30_000),
headers: {
Authorization: `Bearer ${process.env.FRESHTALENT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
status: "watching",
apply: "selected",
urls: ["https://www.linkedin.com/in/derek-morrow"],
}),
});
const body = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${JSON.stringify(body)}`);
console.log(body.data.updated);
import json
import os
import urllib.request
payload = json.dumps({
"status": "watching",
"apply": "selected",
"urls": ["https://www.linkedin.com/in/derek-morrow"],
}).encode()
request = urllib.request.Request(
"https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members",
data=payload,
method="POST",
headers={
"Authorization": f"Bearer {os.environ['FRESHTALENT_API_KEY']}",
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request, timeout=30) as response:
body = json.load(response)
print(body["data"]["updated"])
{ "data": { "updated": 12 } }
Accept target members
Set the membership status of selected or filtered Target members; despite the dashboard name, this operation also supports exclude and reset-to-proposed.
POST
/
targets
/
{id}
/
members
curl --fail-with-body --max-time 30 -X POST "https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members" \
-H "Authorization: Bearer $FRESHTALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status":"watching",
"apply":"selected",
"urls":["https://www.linkedin.com/in/derek-morrow"]
}'
curl --fail-with-body --max-time 30 -X POST "https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members?status=proposed&stint=alum" \
-H "Authorization: Bearer $FRESHTALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"watching","apply":"filter"}'
const id = "550e8400-e29b-41d4-a716-446655440000";
const response = await fetch(`https://api.freshtalent.ai/v1/targets/${id}/members`, {
method: "POST",
signal: AbortSignal.timeout(30_000),
headers: {
Authorization: `Bearer ${process.env.FRESHTALENT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
status: "watching",
apply: "selected",
urls: ["https://www.linkedin.com/in/derek-morrow"],
}),
});
const body = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${JSON.stringify(body)}`);
console.log(body.data.updated);
import json
import os
import urllib.request
payload = json.dumps({
"status": "watching",
"apply": "selected",
"urls": ["https://www.linkedin.com/in/derek-morrow"],
}).encode()
request = urllib.request.Request(
"https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members",
data=payload,
method="POST",
headers={
"Authorization": f"Bearer {os.environ['FRESHTALENT_API_KEY']}",
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request, timeout=30) as response:
body = json.load(response)
print(body["data"]["updated"])
{ "data": { "updated": 12 } }
This route is the Target member status mutation. “Accept” is the dashboard action for setting
The JSON body is an object with
status to watching, but the API also supports excluded and proposed.
Request
string
required
Target UUID.
status required and no unknown properties:
string
required
Exact enum:
watching, excluded, or proposed.
watching is Monitored, proposed is Pending Approval, and excluded is Removed.string
selected or filter. If omitted, the service uses the selected-URL path. filter applies to every row matching the request query filters and ignores urls.string[]
Used for selected updates. The route accepts 1–500 strings when supplied. URLs are normalized as LinkedIn URLs, de-duplicated, and invalid/unparseable values are silently ignored. The field is not required by the route; missing or unusable URLs updates zero rows.
Filter mode
With"apply": "filter", put filters on the request URL. The supported filters are the same member filters as List target members: status, q/keywords, stint, location, exclude_locations, company, roles, exclude_recruiters, depth, first_seen_after, company_current, and company_left_min_months_ago. limit and offset do not apply to this mutation; every matching row is updated.
When setting watching or proposed, the filter path excludes existing excluded rows. When setting excluded, it can update all matching rows, including already excluded rows. Include status=proposed when accepting only pending members.
Response
200 OK returns { "data": { "updated": integer } }. updated is the number of rows matched and updated by the database, including rows already at the requested status, not the number of URLs submitted or the number of rows later enriched.
{ "data": { "updated": 12 } }
Examples
curl --fail-with-body --max-time 30 -X POST "https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members" \
-H "Authorization: Bearer $FRESHTALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status":"watching",
"apply":"selected",
"urls":["https://www.linkedin.com/in/derek-morrow"]
}'
curl --fail-with-body --max-time 30 -X POST "https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members?status=proposed&stint=alum" \
-H "Authorization: Bearer $FRESHTALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"watching","apply":"filter"}'
const id = "550e8400-e29b-41d4-a716-446655440000";
const response = await fetch(`https://api.freshtalent.ai/v1/targets/${id}/members`, {
method: "POST",
signal: AbortSignal.timeout(30_000),
headers: {
Authorization: `Bearer ${process.env.FRESHTALENT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
status: "watching",
apply: "selected",
urls: ["https://www.linkedin.com/in/derek-morrow"],
}),
});
const body = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${JSON.stringify(body)}`);
console.log(body.data.updated);
import json
import os
import urllib.request
payload = json.dumps({
"status": "watching",
"apply": "selected",
"urls": ["https://www.linkedin.com/in/derek-morrow"],
}).encode()
request = urllib.request.Request(
"https://api.freshtalent.ai/v1/targets/550e8400-e29b-41d4-a716-446655440000/members",
data=payload,
method="POST",
headers={
"Authorization": f"Bearer {os.environ['FRESHTALENT_API_KEY']}",
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request, timeout=30) as response:
body = json.load(response)
print(body["data"]["updated"])
Lifecycle, side effects, and retry safety
Setting at least one matched member towatching queues a refresh_watch job only if members need enrichment and no job is already pending/running, and synchronizes the Target’s default lists. Setting proposed or excluded does not queue enrichment. The worker can enrich asynchronously; updated is not a monitoring or enrichment completion signal. Monitoring selects Target members with watching status, but this endpoint does not guarantee when the next profile refresh or diff will appear.
The selected operation is deterministic for the same normalized URLs, but there is no idempotency key. Replaying filter mode can update new rows that entered the filter after the first request. After a timeout, re-list the intended members and reconcile statuses before replaying, especially for broad filters or excluded.
Errors and recovery
400 invalid_request: missingstatus, wrong type, invalid enum, more than 500urls, or invalid JSON. Fix the request.401 unauthorized,402 payment_required, and platform-key400 invalid_request: fix authentication/access or the organization header.404 not_found: the Target is not in the authenticated organization. Do not retry unchanged.409 conflict: the route preserves a service conflict if one occurs; re-read members before retrying.429/5xx: back off. Reconcile a timed-out mutation instead of blindly replaying it.
Next
- List target members to verify the affected statuses.
- Get target to inspect aggregate counts and job progress.
- Update target to change the Target-wide
auto_admitdefault.