Unified.to
All articles

How to Deduplicate and Visualize Talent Pools Across ATS Platforms Using Unified's ATS API


February 25, 2026

Recruiting teams rarely operate in a single system.

They may use:

  • Different ATS platforms across regions
  • Multiple ATS instances for separate business units
  • An ATS plus an internal talent CRM
  • A sourcing database layered on top

From the recruiter's perspective, this creates blind spots:

  • Are we sourcing candidates who already exist in another system?
  • How many unique candidates do we actually have?
  • How many are active vs stale?
  • Where are candidates getting stuck in the funnel?

If you're building a recruiting product, this is a customer-facing feature:

A unified talent pool view across ATS platforms.

This guide walks through how to implement talent pool deduplication and visibility using Unified's ATS API.

This is a read + analytics workflow. No write-back required.

The Mental Model

Your product becomes a candidate identity layer.

It:

  1. Pulls candidates from one or more ATS connections
  2. Normalizes the candidate object
  3. Deduplicates across systems
  4. Aggregates application stages
  5. Computes recency and stale metrics
  6. Visualizes funnel distribution

Unified provides normalized candidate and application models across supported ATS integrations.

You provide:

  • Identity resolution logic
  • Cross-system merging
  • Analytics and visualization

Step 1: Pull Candidates from Each ATS Connection

Start by listing candidates for each connected ATS.

Endpoint

GET /ats/{connection_id}/candidate

Node SDK Example

const candidates = await sdk.ats.listAtsCandidates({
  connectionId,
  limit: 100,
  offset: 0,
  sort: 'updated_at',
  order: 'asc',
});

Important fields from AtsCandidate:

  • id
  • emails[]
  • telephones[]
  • link_urls[]
  • first_name, last_name
  • company_name
  • title
  • tags[]
  • metadata[]
  • updated_at
  • created_at

Store candidates in your own database. Do not run analytics directly off live API calls.

Step 2: Normalize Candidate Identity

You need a canonical identity key across systems.

Use the following priority order:

1️⃣ Email (primary key)

emails[] contains structured email objects:

{
  "name": "Jane Doe",
  "email": "jane@example.com",
  "type": "WORK"
}

Deduplicate primarily on normalized email address:

  • Lowercase
  • Trim whitespace
  • Remove aliasing patterns if appropriate (e.g., Gmail dots)

Email is the most reliable cross-system identifier.

2️⃣ LinkedIn URL

link_urls[] includes:

URLs for web pages containing additional material about the candidate (LinkedIn, other social media, articles, etc.)

Extract LinkedIn URLs and normalize:

  • Remove tracking parameters
  • Standardize domain variants

This becomes your secondary dedupe key when email is missing.

3️⃣ Phone Number (fallback)

From telephones[], normalize:

  • Strip formatting
  • Standardize country codes

Phone numbers are useful but less consistent.

Step 3: Build a Canonical Candidate Record

After dedupe, merge candidate records into a single canonical entity:

CanonicalCandidate
  - primary_email
  - linkedin_url
  - phones[]
  - first_seen_at
  - last_updated_at
  - ats_sources[]
  - candidate_ids_by_connection

Store:

  • All ATS candidate IDs
  • Which connection they belong to
  • The most recent updated_at across systems

This lets you:

  • Avoid re-sourcing known candidates
  • Show a unified profile
  • Link back to each ATS record

Step 4: Merge Applications for Funnel Visibility

Now pull applications.

Endpoint

GET /ats/{connection_id}/application

Example

const applications = await sdk.ats.listAtsApplications({
  connectionId,
  limit: 100,
  offset: 0,
});

From AtsApplication, use:

  • candidate_id
  • status
  • applied_at
  • rejected_at
  • hired_at

Map each application to your canonical candidate record.

Step 5: Visualize Stage Distribution

Use status for stage aggregation.

To retrieve available stage vocabulary:

GET /ats/{connection_id}/applicationstatus

From AtsStatus:

  • status
  • original_status
  • description

Now compute:

  • Count of candidates per status
  • Count per ATS connection
  • Cross-ATS aggregated funnel

Example output:

StageCount
NEW125
REVIEWING82
FIRST_INTERVIEW34
OFFERED9
HIRED6

This becomes a funnel visualization in your product.

Step 6: Highlight Stale Candidates

Use updated_at on the candidate object.

Define stale logic, for example:

  • No updates in 90 days
  • No active applications
  • No interview scheduled

Example:

const isStale = daysSince(candidate.updated_at) > 90;

You can also compute:

  • Days since last application
  • Days since last interview
  • Days since stage change (if you track it yourself)

Unified does not expose historical stage transitions, so you must track changes over time if you need them.

Step 7: Merge Internal + ATS Data

If your product also has:

  • Internal CRM candidates
  • Sourced prospects
  • Event leads

You can unify them using the same identity logic:

  • Email
  • LinkedIn
  • Phone

Then show:

  • 'Already in ATS (Greenhouse)'
  • 'Previously applied in EMEA instance'
  • 'Rejected 6 months ago'

This prevents duplicate outreach and improves recruiter efficiency.

Architecture Recommendation

  1. Initial full sync of candidates and applications
  2. Store in internal database
  3. Deduplicate into canonical identities
  4. Compute analytics from your own DB
  5. Refresh via:
    • Webhooks (if enabled)
    • Or incremental polling using updated_gte

Do not recompute dedupe in real time on every page load.

Why This Matters to Your Customers

Talent pool visibility helps customers:

  • Avoid sourcing duplicates
  • Reduce recruiter fatigue
  • Understand true funnel size
  • Identify pipeline bottlenecks
  • Re-engage dormant candidates

By using Unified's normalized ATS API as a read layer, you can provide cross-platform visibility without building custom integrations for every ATS.

Closing Thoughts

Deduplicating and visualizing talent pools across ATS platforms is not an integration problem.

It's an identity and analytics problem.

Unified provides:

  • Structured candidate models
  • Standardized application objects
  • Stage vocabulary
  • Consistent pagination and incremental updates

Your product layers on:

  • Identity resolution
  • Canonical merging
  • Funnel analytics
  • Staleness detection
  • Recruiter-facing insights

That combination turns fragmented ATS data into actionable talent intelligence.

→ Start your 30-day free trial

→ Book a demo

All articles