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

# ATS, CRM, and outreach

> Poll profile diffs into Greenhouse, Ashby, Lever, HubSpot, or a sequencer. Stages stay in FreshTalent until someone is a real candidate.

Recruiters work **Lists** and **Targets** in FreshTalent. Your ATS or CRM should see **people who moved**, keyed by LinkedIn URL — not a second copy of the whole graph.

The integration contract is [GET /events](/api-reference/events/list) (dashboard: **Monitoring**). Those rows are people on a **List** or **Monitored** on a Target. Email and Slack (Settings → **Notifications**) are graph-wide on the fields you enable — not the same membership. Poll events for systems.

## Recommended architecture

<Steps>
  <Step title="Source in FreshTalent">
    Search → Lists (**To contact**) → Targets + **Accept**. Do not create ATS candidates for every **Pending Approval** person.
  </Step>

  <Step title="Poll events on a schedule">
    Every 5–15 minutes, start a pass with an absolute `since` timestamp and no cursor. Follow `meta.next` toward older events until `has_more` is false. Keep `since` fixed. After all writes succeed, checkpoint the pass start time; use an overlap and deduplicate event IDs.
  </Step>

  <Step title="Upsert by LinkedIn URL">
    `person.linkedin_url` is the join key. Create or update the candidate/contact. Write `field`, `before`, `after`, `label`, `seen_at` onto an activity or note.
  </Step>

  <Step title="Promote when outreach starts">
    When a recruiter actually sequences someone, create the ATS job application (or CRM opportunity) and PATCH the FreshTalent list member to `contacted` (**Contacted**).
  </Step>
</Steps>

## Event payload

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "…",
  "field": "left_company",
  "before": "Palantir",
  "after": "Anduril",
  "seen_at": "2026-08-23T10:00:00.000Z",
  "severity": "hot",
  "label": "Left Palantir → Anduril",
  "person": {
    "slug": "derek-morrow",
    "name": "Derek Morrow",
    "linkedin_url": "https://www.linkedin.com/in/derek-morrow",
    "current_company": "Anduril"
  }
}
```

Filter with `type=` (`open_to_work`, `left_company`, `joined_company`, …) or `list=` (name or uuid) if you only want one pipeline.

## Poll loop (Node)

Use the [complete runnable tutorial](/guides/first-integration), with bounded GET retries, both HTTP error shapes, fixed-window pagination, and a local checkpoint. Replace its local sink with an idempotent ATS write.

A cursor pages backward through one pass. Do not carry the last page cursor into the next scheduled poll: it would keep requesting older events rather than new ones. Store event UUIDs for deduplication only after the destination write succeeds. Use an idempotent destination or transactional outbox for crashes between the write and checkpoint.

## Stage mapping

| Dashboard  | API          | Typical ATS / CRM                                   |
| ---------- | ------------ | --------------------------------------------------- |
| To contact | `to-contact` | Sourced / talent pool — often **no** ATS record yet |
| Contacted  | `contacted`  | Reached out / sequenced                             |
| Responded  | `responded`  | Replied                                             |
| Passed     | `passed`     | Rejected / do not contact                           |

Do not mirror every **Pending Approval** Target member into the ATS. **Accept** first (API `watching` or MCP `admit`), then sync.

## What not to do

* Do not expect a Gateway **push webhook** for events yet. A webhook URL can be stored on the org; notify today is email + Slack.
* Do not scrape FreshTalent HTML. Use REST or MCP.
* Do not send the API key to the browser. Poll from your backend or iPaaS (Workato, Zapier with a server-side catch, n8n).

## Auth and limits

Bearer `ft_live_…`, 300 requests/minute at the Gateway (IP-based bucket). [Authentication](/authentication), [Rate limits](/rate-limits).
