How to fetch job application data from Lever ATS API

Introduction

This article is part of an in-depth series on the Lever API and focuses specifically on retrieving job application data from Lever ATS. The objective is straightforward: help you pull application-level data in a clean, reliable, and production-ready way.

If you’re looking for a broader overview of the Lever API, including authentication models, rate limits, and other supported use cases, refer to the comprehensive Lever API directory available on the Knit blog.

This post assumes you already know why you need application data. The focus here is how to get it right without breaking your integration later.

Get Job Application Data from Lever ATS

Prerequisites

Before you begin, make sure the basics are locked in:

  • A Lever account with sufficient permissions to access application data
  • An API key or OAuth credentials configured for Lever
  • Familiarity with Lever’s API documentation, especially around scopes and pagination

Skipping any of these will slow you down later. Treat this as table stakes.

API Endpoint

To retrieve job application data, Lever exposes the following endpoint:

GET https://api.lever.co/v1/applications

This endpoint returns application-level records tied to candidates and job postings.

Step-by-Step Process

Step 1: Authentication

Authentication can be handled using OAuth or an API key. For OAuth-based access, the flow starts with user authorization.

import requests

# Step 1: Request User Authorization
auth_url = "https://auth.lever.co/authorize"
params = {
    "client_id": "your_client_id",
    "redirect_uri": "https://yourapplication.com/callback",
    "response_type": "code",
    "state": "random_state_string",
    "scope": "applications:read:admin",
    "audience": "https://api.lever.co/v1/"
}
response = requests.get(auth_url, params=params)
print(response.url)  # Direct user to this URL for authorization

The user must complete this step before you can proceed. This is a hard dependency.

Step 2: Exchange Authorization Code for Access Token

Once authorization is complete, exchange the authorization code for an access token.

# After user authorization, exchange code for access token
token_url = "https://auth.lever.co/oauth/token"
data = {
    "grant_type": "authorization_code",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret",
    "code": "authorization_code_received",
    "redirect_uri": "https://yourapplication.com/callback"
}
token_response = requests.post(token_url, data=data)
access_token = token_response.json().get("access_token")

This token is required for all subsequent API calls.

Step 3: Retrieve Application Data

Use the access token to call the applications endpoint.

# Use access token to retrieve application data
headers = {"Authorization": f"Bearer {access_token}"}
applications_url = "https://api.lever.co/v1/applications"
applications_response = requests.get(applications_url, headers=headers)
applications_data = applications_response.json()
print(applications_data)

At this stage, you should have raw application data ready for processing or downstream workflows.

Common Pitfalls

Most Lever API integrations fail for predictable reasons. Avoid these upfront:

  1. Not handling access token expiration and refresh logic
  2. Mismatched or incorrectly configured redirect URIs
  3. Missing required scopes during the OAuth authorization request
  4. Skipping validation of the state parameter in the OAuth flow
  5. Relying on deprecated fields such as candidateId
  6. Ignoring Lever’s API rate limits and throttling behavior
  7. Assuming happy-path responses and not handling API errors explicitly

Frequently Asked Questions

  1. What is the difference between an opportunity and an application?
    An opportunity represents the candidate profile, while an application represents a specific job submission linked to that opportunity.
  2. How do I handle pagination in application responses?
    Use the next parameter returned in the API response to fetch subsequent result pages.
  3. Can applications be filtered by status?
    Yes. Query parameters can be used to filter applications based on status and other supported attributes.
  4. Can application data be updated via the API?
    Updates require the appropriate PUT or PATCH endpoints and permissions, depending on the field being modified.
  5. What information is available for each application?
    Application records typically include candidate details, application type, associated job, and related metadata.
  6. Is there a limit to how many applications can be retrieved?
    Yes. Retrieval is subject to Lever’s rate limits and pagination rules.
  7. What’s the recommended approach for error handling?
    Always inspect HTTP status codes and error payloads, and implement retries or fallbacks where appropriate.

Knit for Lever ATS Integration

Direct integration with the Lever API works, but it comes with ongoing overhead. Authentication management, token refresh, API changes, and edge-case handling quickly add up.

Knit simplifies this by abstracting the entire integration layer. With a single integration to Knit, you get managed authentication, authorization, and long-term API maintenance handled for you. The result is faster implementation, lower maintenance cost, and fewer production surprises.

If your goal is reliability at scale, this approach is simply more efficient.

#1 in Ease of Integrations

Trusted by businesses to streamline and simplify integrations seamlessly with GetKnit.