Upgrade OAuth

Upgrade your OAuth integration to the Indeed OAuth endpoint v2.

📘

Note:

By using this API and its documentation and building an integration, you agree to the Additional API Terms and Guidelines.

To upgrade to the Indeed OAuth endpoint v2:

Once

1.

Update your app registration

For each user

2.

Get an authorization code

3.

Get an access token.

For each API call

4.

Pass your access token each time that you call an Indeed API.

Hour after refresh, or for each API call

5.

Refresh your access token

For a complete set of authorization instructions, see Authorization.

Update your app registration

  1. On Manage app credentials, review your app's information.

  2. Add at least one redirect URL.

    A redirect URL is a page on your website where Indeed redirects a user after attempting to authorize the user. If authorization succeeds, Indeed passes an authorization code to your redirect URL.

    To test your OAuth app on your local machine, set one of your redirect URLs to http://localhost.

Get an authorization code

The owner of an Indeed account must authorize your app to call the API on its behalf.

The URL path for the authorization link that you send to the user has changed.

From:

https://secure.indeed.com/account/oauth

To:

https://secure.indeed.com/oauth/v2/authorize

The parameters have not changed, but the redirect_uri parameter is now required.

The redirect_uri is the page on your site that captures the authorization code, which must match one of the redirect URLs that you registered with your app.

For example:

https://secure.indeed.com/oauth/v2/authorize?client_id=6nwwcdklwgktryjw2j5fxh5t2fyneule7zg7mvw3pf9jbx3wmewzlxkdz1jxvs6b&redirect_uri=http%3A%2F%2Fwww.acerecruitersllc.com%2Foauth%2Findeed&response_type=code&scope=email+offline_access&state=employer1234

If the user clicks Allow on the OAuth consent screen, Indeed redirects them to your app at the redirect_uri with the code and state parameters appended.

Your redirect_uri page must capture the code parameter:

GET http://www.acerecruitersllc.com/oauth/indeed?code=rXZSMNyYQHQ&state=employer1234

Get an access token

You exchange the authorization code for an access token.

You pass an access token in every API call. An access token identifies an Indeed account and proves that your app is authorized to make API calls on behalf of this account.

To get an access token, send the authorization code to Indeed:

POST https://apis.indeed.com/oauth/v2/tokens

The URL path has changed.

From:

https://secure.indeed.com/oauth/tokens

To:

https://apis.indeed.com/oauth/v2/tokens

The required headers have not changed.

The parameters have not changed, but the redirect_uri must match the one you used to get an authorization code.

For example:

curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json' \
 -d 'code=rXZSMNyYQHQ' \
 -d 'client_id=6nwwcdklwgktryjw2j5fxh5t2fyneule7zg7mvw3pf9jbx3wmewzlxkdz1jxvs6b' \
 -d 'client_secret=02KKpg6yLXw2v3FKf5lqyFGtMQCvPBNbJIw89SoSd9fts1LAdlvwUQQ6dwhAhEXv' \
 -d 'redirect_uri=http://www.acerecruitersllc.com/oauth/indeed' \
 -d 'grant_type=authorization_code' \
 https://apis.indeed.com/oauth/v2/tokens

The JSON response contains the access_token, id_token, expires_in, token_type, and refresh_token.

The id_token field is new. This field is a JSON Web Token that contains the same information that you can get from the userinfo endpoint:

  • sub
  • email
  • email_verified

The id_token includes the email and email_verified fields only if your app requests and is granted the email scope.

The format of the scope field has changed. In v1, this field returns the array ["all"]. In v2, this field returns a string of space-separated scopes.

Finally, in v2, Indeed returns a refresh token only when your app requests and is granted the offline_access scope. In this case, Indeed also includes the consented_scope field, which represents all scopes that a user has granted the app.

For example:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ[...]",
  "id_token": "eyJraWQiOiJlMzEzZTc4My1lM2YwLTQ3ZWMtY[...]",
  "refresh_token": "rXZSMNyYQHQ",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "email offline_access",
  "consented_scope": "email offline_access"
}

An error response looks like this:

{
  error: "invalid_request",
  error_description: "Invalid authentication request."
}

Call an Indeed API

This step has not changed.

Refresh your access token

Access tokens are valid for one hour (3600 seconds). To get a new access token, use the refresh token returned with your user's access token. Indeed returns a refresh token with the access token only when your app requests and is granted the offline_access scope.

The refresh token is valid for 60 days from when it was issued. With each refresh, the refresh token's expiration date is extended to 60 days from the most recent refresh.

The URL path has changed.

From:

https://secure.indeed.com/oauth/tokens

To:

https://apis.indeed.com/oauth/v2/tokens

Refresh token headers

The required headers have not changed.

Refresh token fields

The scope response field has changed. In v1, this field returns the array ["all"]. In v2, this field returns a string representing all of the scopes that have been granted by the user. For example, if your app requests the email and offline_access scopes and the user grants these scopes during the authorization step, then the scope response field has the value email offline_access as a string.

Example refresh token request

curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json' \
  -d 'refresh_token=8qE_nKXUng4' \
  -d 'client_id=6nwwcdklwgktryjw2j5fxh5t2fyneule7zg7mvw3pf9jbx3wmewzlxkdz1jxvs6b' \
  -d 'client_secret=02KKpg6yLXw2v3FKf5lqyFGtMQCvPBNbJIw89SoSd9fts1LAdlvwUQQ6dwhAhEXv' \
  -d 'grant_type=refresh_token' \
  https://apis.indeed.com/oauth/v2/tokens

Example refresh token response

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "refresh_token": "rXZSMNyYQHQ",
  "convid": "1c1a1s8540kkt89p",
  "scope": "email offline_access",
  "token_type": "Bearer",
  "expires_in": 3600
}

📘

Note:

The new access token is also valid for one hour only. You must refresh this token after that.

Additional tasks

Get user info

The endpoint that you use to request account information has changed. This endpoint returns the user ID, email address, and email verification status associated with the access token.

If you request the email scope and the user grants it to you, the response shows the email and email_verified fields.

The host name, secure.indeed.com, remains the same. However, the endpoint path is now /v2/api/userinfo instead of /v1/api/account:

GET/POST https://secure.indeed.com/v2/api/userinfo

Also, you can no longer pass the access token as a URL parameter. You must pass the access token in an Authorization header with the Bearer authentication scheme.

This endpoint does not have any request body parameters.

For example:

GET /v2/api/userinfo HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Host: secure.indeed.com

A successful request returns the HTTP 200 status code and a response payload:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "sub": "248289761001",
  "email": "min[email protected]",
  "email_verified": true
}

Get and manage scopes

When you request an access token, you request scopes that define your app's permissions.

Indeed authorization scopes

For a list of Indeed-supported scopes, see scopes.

When using the authorization code flow (3-legged OAuth), the authorizing user grants scopes to your app. They can grant no scopes, specific scopes, or all scopes to your app.

To determine which scopes your app has, read the scope field in a tokens response:

{
  "access_token": "eyJraWQiOiI1OTdjYTgxNC03YTA2LTRkZTMtO",
  "refresh_token": "ZenoK4KeQsg",
  "id_token": "eyJraWQiOiI1OTdjYTgxNC03YTA2LTE69SSJkjQQ",
  "scope": "offline_access employer_access email",
  "consented_scope": "offline_access employer_access email",
  "convid": "1er835qvtu54n800",
  "token_type": "Bearer",
  "expires_in": 3600
}

Use incremental authorization

Incremental authorization enables apps to request only the scopes that they need. Incremental authorization requires the offline_access, which maintains the permissions that your app has. For example, if your app requests the email scope, your app must also request the offline_access scope.

After a user grants your app a scope, they do not need to grant the scope again.

For example, if the user requests functionality from your app that requires the employer_access scope, the OAuth consent screen prompts the user to grant only the employer_access scope and not the email and offline_access scopes.

The Current permissions tab on the OAuth consent screen lists the app's scopes.

Revoke OAuth scopes

When using the authorization code flow (3-legged OAuth), a user can use the Authorized Applications page to revoke scopes from an app.

📘

Note:

You cannot revoke scopes individually. You can revoke all scopes and, when using the app, grant scopes again.

Associate user account with employer account

You can associate an Indeed user account with one or more employer accounts. When you call an Indeed API, the API might require you to represent a particular employer. To associate an employer with an access token, use either the Indeed employer selection screen or your own employer selection screen.

📘

Note:

An access token can represent only one employer at a time. To switch employers, generate an access token. For example, use a refresh token to generate an access token.

Show the Indeed employer selection screen

To request the creation of an authorization link to display the Indeed employer selection screen, use the prompt=select_employer parameter.

When you specify this parameter, your OAuth app must also request scope=employer_access. Otherwise, the Indeed employer selection screen does not appear.

For example, this link includes both the prompt=select_employer parameter and a request for the employer_access scope:

https://secure.indeed.com/oauth/v2/authorize?client_id=bf7622efee705862320df0f5c7690b22f60ba24f236aaf4adf5b7a36fa0adcf1&redirect_uri=https%3A%2F%2Fexample.com%2Foauth&response_type=code&state=random&scope=email+offline_access+employer_access&prompt=select_employer

This authorization link triggers these screens to appear:

Screen Description
Authentication Appears when the user is logged out of Indeed.
OAuth consent Enables a user to grant consent for any scopes that the OAuth app requests, such as the employer_access scope.
Indeed employer selection Enables a user to select an employer from a list of employers associated with the user account.

The Indeed employer selection screen lists the employers associated with the user account:

  • US Robotics and Mechanical Men
  • Umbrella Corporation

If the user selects one of the employers and submits the page, a redirect URI parameter transmits the employer ID to your OAuth app:

https://example.com/oauth/callback?state=random&employer=6d2f02224e30d401810b1726eb246d8d&code=e_IEr5UlBys

The URL includes an employer parameter that represents an employer ID. Use this ID when your request an access token to associate the access token with an employer, like this:

curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json' \
 -d 'code=e_IEr5UlBys' \
 -d 'client_id=bf7622efee705862320df0f5c7690b22f60ba24f236aaf4adf5b7a36fa0adcf1' \
 -d 'client_secret=02KKpg6yLXw2v3FKf5lqyFGtMQCvPBNbJIw89SoSd9fts1LAdlvwUQQ6dwhAhEXv' \
 -d 'redirect_uri=https://example.com/oauth' \
 -d 'grant_type=authorization_code' \
 -d 'employer=6d2f02224e30d401810b1726eb246d8d' \
 https://apis.indeed.com/oauth/v2/tokens

When you use a refresh token to get an access token, you can also use the employer parameter. If the user does not select an employer or the user account has no associated employers, then the redirect URI does not include an employer parameter.

🚧

Warning:

Don't assume that the redirect URI includes an employer parameter even when you use the prompt=select_employer parameter.

Show a custom employer selection screen

Indeed recommends that you use the standard Indeed employer selection screen to enable users to select a particular employer. To customize the employer selection screen, then you also have the option of getting employers and creating an employer selection screen.

Follow these steps:

  1. Get credentials. Get an access token to trigger the OAuth consent screen, and get an access token with the employer_access and offline_access scopes.

    The query returns an access token, ID token, and refresh token.

  2. To list employers for the current user, decode the ID token. See Get user info.

  3. Create a custom employer selection screen. You can build a user interface that enables the user to select an employer.

  4. Get an access token that represents an employer.

    To get an access token that represents the employer, pass the employer ID in the employer parameter of the oauth/v2/tokens endpoint.

    curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json' \
      -d 'refresh_token=4U0xku8M9u0' \
      -d 'client_id=b0c3b1092225d3e99f85d7aa3fe1e6001f9a0bb798717cbc2008e58fbda3ef16' \
      -d 'client_secret=2YFoyZOWmr83njlsIuyCL9QQq5jZkRCR4UtmHGp22MRzjIhe5RbynnAGmuYLFbYx' \
      -d 'grant_type=refresh_token' \
      -d 'employer=13ef9940a7c1f0500a7e411e74178c4e' \
      https://apis.indeed.com/oauth/v2/tokens
    

    📘

    Note:

    In the request:

    • The grant_type parameter has the refresh_token value.
    • The refresh_token parameter contains the refresh token.
    • The employer parameter has the Dharma Initiative employer ID value.

    When you use a refresh token to get an access token, an OAuth consent screen is not necessary.

    Use this access token for API calls on behalf of the consenting user and only for this employer.

See also