Recommended architecture
1
Source in FreshTalent
Search → Lists (To contact) → Targets + Accept. Do not create ATS candidates for every Pending Approval person.
2
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.3
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.4
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).Event payload
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, 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
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
Bearerft_live_…, 300 requests/minute at the Gateway (IP-based bucket). Authentication, Rate limits.