Retrieve Candidates API guide
Get candidate information from Indeed for employers.
By using this API and its documentation and building an integration, you agree to the Additional API Terms and Guidelines.
API overview
Call the Retrieve Candidates API to get candidate information from Indeed for employers.
Asset types
The Retrieve Candidates API returns these candidate asset types, which implement the AtsSyncCandidateSyncAsset interface:
-
AtsSyncCandidateSyncInterestedCandidateAssetfrom Smart Sourcing.Includes this candidate information (
AtsSyncCandidateSyncInterestedCandidate):AtsSyncCandidateSyncInterestedCandidate fields Field Description Type:
String!The candidate's full name. Type:
EmailAddress!The candidate's email address.
Type:
StringThe candidate's location, if provided.
A presigned S3 URL to download the candidate's resume. See Download and upload objects with presigned URLs (opens in a new window).
-
AtsSyncCandidateSyncSmartScreeningUpdateAssetfrom Smart Screening updates.Smart Screening updates apply to the partner, not to one employer registration, so any Smart Screening job can produce application updates. Fetch results omit
employerIdentifierand staging input omitsmetadata.employerIdentifier, so use the Indeed Apply ID to identify the application.Smart Sourcing requires
employerIdentifierbecause it targets one employer registration.Includes this candidate information (
AtsSyncCandidateSyncSmartScreeningUpdate):AtsSyncCandidateSyncSmartScreeningUpdate fields Field Description Application ID for the screening update. Select the Indeed Apply union member and read its indeedApply.indeedApplyId.Type:
FloatThe candidate's smart fit score, if available. Returns
nullif no score was staged.The candidate's resume file. Use:
resume {urlnamecontentType}The download URL is a short-lived presigned URL. See Download and upload objects with presigned URLs (opens in a new window).
Type:
DateTime!When the screening update was created. Order updates by this timestamp.
These fetch operations can return both types:
Create test assets (stageAssets) accepts either asset type as input.
Best practices
| Best practice | Description |
|---|---|
| Handle interfaces and unions defensively | For the For the |
| Apply updates in order | Order Smart Screening updates by Do not order Smart Screening updates by If you apply updates out of order, older data can overwrite newer data. |
API steps
After you integrate with the Retrieve Candidates API, complete these steps to get candidate information from Indeed for employers:
1. Authenticate
When you become an Indeed partner, Indeed creates an app for your integration. Sign in to Partner Console (opens in a new window) to view the app and your OAuth credentials: client ID, secret, and a 3-legged OAuth authorization code. Exchange those credentials for an access token to authenticate API calls.
Each Candidate Sync API operation requires an OAuth token:
| API and operations | OAuth token type |
|---|---|
| Authenticate with a 3-legged OAuth token that represents an employer and has the employer.ats_candidate.sync scope. This token links the employer's Indeed account to their ATS account. An Indeed administrator or owner must create it. If registerEmployer returns a missing scope error, the token might not be associated with an employer. |
| Authenticate with a 2-legged OAuth token, which requires no user interaction. |
Securely store access tokens in your ATS, and don't share them between users. Indeed trusts that your system is the source of truth for a job. If you use a user's access token for a job that another user posted, Indeed might grant that user access to the other user's job on Indeed.
After you get an access token, include this token in the query or mutation. Indeed recommends that you refresh your access tokens before they expire to avoid asking users to sign in every time they need to view updated job statuses.
See Integrate with Indeed and call APIs and Scopes.
2. Register employer
Use the Employer Registration API to register an employer.
Request – Register employer
To register an employer and return registration information, call registerEmployer.
Authenticate with a 3-legged OAuth token that represents an employer and has the employer.ats_candidate.sync scope. This token links the employer's Indeed account to their ATS account. An Indeed administrator or owner must create it. If registerEmployer returns a missing scope error, the token might not be associated with an employer.
Provide these input fields in RegisterEmployerInput:
| Field | Required | Description |
|---|---|---|
Type: | ✅ | An ID you provide to uniquely identify the employer. You can register one |
Type: | ✅ | The name you provide for the employer. Employers see this name on Indeed. |
Response – Register employer
The API returns an EmployerRegistration. Store its id for later Candidate Sync API calls, or query findRegisteredEmployers with the partnerEmployerId to get it again.
3. Get unacknowledged assets
Call fetchAssets to get unacknowledged assets in the order you staged them, from oldest to newest.
fetchAssets returns assets from:
- Smart Sourcing outreach (
AtsSyncCandidateSyncInterestedCandidateAsset) - Smart Screening updates (
AtsSyncCandidateSyncSmartScreeningUpdateAsset)
A single request can return a mix of both asset types. Indeed might add asset types, so handle types you do not recognize rather than assuming every asset is one of these two.
Authenticate with a 2-legged OAuth token. Your application authenticates directly with Indeed's authorization server without user interaction.
Smart Sourcing assets use employerIdentifier.
Smart Screening assets use applicationIdentifier.indeedApply.indeedApplyId.
Either the employerIdentifier or the indeedApplyId in the response matches the ID you sent when you created the registration. Use it to identify which employer receives the candidate.
Request — Get unacknowledged assets
This mutation returns a token, asset metadata, candidate details for interested candidates, and screening update details for Smart Screening assets:
mutation FetchAssets($input: FetchAssetsAtsSyncCandidateSyncInput) { atsSyncCandidateSync { fetchAssets(input: $input) { token assets { id metadata { stagedAt stagedTest employerIdentifier completeSourceAttribution { enumKey name } } ... on AtsSyncCandidateSyncInterestedCandidateAsset { contact { candidate { email location name phone resume { files { url name contentType } } } job { sourcedPostingId } tracking { recruiterEmail } } } ... on AtsSyncCandidateSyncSmartScreeningUpdateAsset { smartScreeningUpdate { smartFitScore createdAt applicationIdentifier { __typename ... on AtsSyncCandidateSyncIndeedApplyApplicationIdentifier { indeedApplyId } } resume { url name contentType } } } } } }}Provide these input fields:
Response — Get unacknowledged assets
The API returns a FetchAssetsAtsSyncCandidateSyncPayload object with these fields:
| Field | Type | Description |
|---|---|---|
assets | [AtsSyncCandidateSyncAsset]! | Next available |
token | String | Acknowledgment token for this batch. Pass it in the next fetchAssets call to acknowledge receipt and request the next batch. If the token is null or empty, Indeed has delivered all assets, so wait the standard polling interval before you call again. |
4. Get assets by time range
After you acknowledge assets, call assetsByTimeRange to fetch them again. Use this query to recover from data loss, and persist asset data in your own data store. For pagination best practices, see the GraphQL Cursor Connections Specification (opens in a new window).
Authenticate with a 2-legged OAuth token. Your application authenticates directly with Indeed's authorization server without user interaction.
To retrieve new assets, use fetchAssets.
Request — Get assets by time range
If you omit a start or end date, the query uses the earliest and latest acknowledgment dates as defaults.
This query returns assets for a time range, including candidate details, Smart Screening updates, and pagination information:
query AssetsByTimeRange($input: AtsSyncCandidateSyncAssetsByTimeRangeInput!, $after: String) { atsSyncCandidateSync { assetsByTimeRange(input: $input, after: $after) { assets { id metadata { employerIdentifier stagedAt stagedTest completeSourceAttribution { enumKey name } } ... on AtsSyncCandidateSyncInterestedCandidateAsset { contact { candidate { email location name phone resume { files { url name contentType } } } job { sourcedPostingId } tracking { recruiterEmail } } } ... on AtsSyncCandidateSyncSmartScreeningUpdateAsset { smartScreeningUpdate { smartFitScore createdAt applicationIdentifier { __typename ... on AtsSyncCandidateSyncIndeedApplyApplicationIdentifier { indeedApplyId } } resume { url name contentType } } } } pageInfo { hasNextPage endCursor } } }}Response — Get assets by time range
assetsByTimeRange returns the same asset data as fetchAssets, but only for acknowledged assets. See Response — Get unacknowledged assets.
Test assets expire after 14 days and stop appearing in assetsByTimeRange responses. See Create test assets.
5. Create test assets
Call stageAssets to create test candidate assets in sandbox mode. Test assets behave like real ones, so you can retrieve them with fetchAssets to test your workflow.
Authenticate with a 2-legged OAuth token. Your application authenticates directly with Indeed's authorization server without user interaction.
Requirements
Before you stage test assets:
- For Smart Sourcing test assets,
metadata.employerIdentifiermust match theemployerIdentifierof an employer registration that you created throughregisterEmployer. - Smart Screening test assets do not use
metadata.employerIdentifier. - The
sourcedPostingIdmust be a UUID, but does not need to match an existing job posting. - Indeed removes test asset data 14 days after you stage it.
Request — Create test assets
To create test assets:
- Call
stageAssetswith test candidate details such as name, email, phone, and location. To include a test resume, setincludeResumetotrue. The API returns a unique ID for each staged asset. - Call
fetchAssetsto retrieve the staged candidates. - Verify that your integration processes the candidate data. To identify test assets, check the
stagedTestfield on themetadataof eachassetsentry.
This mutation stages a Smart Sourcing candidate asset for an employer and returns the created asset IDs. Provide these required and optional fields:
| Field | Required | Type | Description |
|---|---|---|---|
metadata | Yes | AtsSyncCandidateSyncAssetMetadataInput | Asset metadata. |
contact | Yes | AtsSyncCandidateSyncInterestedCandidateContactInput | The candidate's contact information. |
job | No | AtsSyncCandidateSyncInterestedCandidateContactJobInput | Job information for the contact. |
tracking | No | AtsSyncCandidateSyncInterestedCandidateTrackingInput | Tracking information for attribution and reporting. |
mutation { atsSyncCandidateSync { stageAssets(input: { assets: [{ smartSourcingContact: { metadata: { employerIdentifier: "employer-123" } contact: { candidate: { name: "Jane Smith" email: "jsmith@example.com" location: "Syracuse, New York 13209" phone: "+10001112223" includeResume: true } job: { sourcedPostingId: "e29aaba8-2cef-447f-a1e0-bcb7ec3fa730" } tracking: { recruiterEmail: "recruiter@example.com" } } } }] }) { ids } }}This mutation stages a Smart Screening update asset for an Indeed Apply application and returns the created asset IDs.
smartScreeningUpdate is one member of the oneOf AtsSyncCandidateSyncStageableAssetInput. Set exactly one asset type for each list entry.
Provide these required and optional fields:
| Field | Required | Type | Description |
|---|---|---|---|
indeedApplyId | Yes | ID! | Indeed Apply ID for the application that was updated. applicationIdentifier is a oneOf, so set only indeedApply. |
smartFitScore | No | Float | The candidate's smart fit score, if available. Omit this field to return null for the score. |
createdAt | No | DateTime | The time when the screening update was created. Order updates by this timestamp. Defaults to the current time if omitted. |
mutation { atsSyncCandidateSync { stageAssets(input: { assets: [{ smartScreeningUpdate: { applicationIdentifier: { indeedApply: { indeedApplyId: "example-indeed-apply-id" } } smartFitScore: 0.87 createdAt: "2026-06-22T12:00:00Z" } }] }) { ids } }}Screening does not use an includeResume flag. Screening updates always include a resume, so Indeed always attaches a fixed sample resume PDF.
6. Troubleshoot errors
For OAuth errors, which occur before you reach GraphQL, see Troubleshoot OAuth errors.
For GraphQL errors, see Troubleshoot GraphQL errors.
GraphQL API reference
registerEmployer— Registers an employer. Authenticate with a 3-legged OAuth token that represents an employer and theemployer.ats_candidate.syncscope.fetchAssets— Returns unacknowledged assets in the order you staged them, from oldest to newest.assetsByTimeRange— Returns acknowledged assets in a time range.stageAssets— Creates test assets for integration testing.