Back to articles

How we normalized hiring data from 4 ATS platforms into one API

CleanJobData Engineering

Hiring data is notoriously messy. Every Applicant Tracking System (ATS) has its own way of representing jobs, locations, and compensation. When we set out to build CleanJobData, our goal was to shield developers from this complexity.

The Challenge

Each platform presents unique challenges:

  • Greenhouse: Uses a robust but deeply nested JSON structure.
  • Lever: Often has unstructured location strings that need parsing.
  • Ashby: Provides rich data but requires specific GraphQL queries.
  • Workable: Uses a different pagination model.

Our Approach

We built a layered normalization pipeline:

  1. Source-specific Adapters: Each ATS has a dedicated adapter that maps raw vendor JSON to our internal "raw" shape.
  2. Structural Enforcement: We ensure every job has a title, description, and canonical company object.
  3. Location Resolution: We resolve free-text locations against our global geo database.

By the time you query our API, the data is clean, consistent, and ready for your UI.