- Authorization code grant type (3-legged OAuth) overview
- Become an Indeed partner
- Get an authorization code
- Get your OAuth credentials
- Get a 3-legged access token
- Refresh your 3-legged access token
- Call Indeed APIs
- Get an access token that represents an employer
- Show the Indeed employer selection screen
- Show a custom employer selection screen
- Get employer access token
- Get user information
- ID token
- The userinfo endpoint
- Dynamically redirect a user to multiple URLs
- Guidelines
- Prevent the authorization code from leaking
- Do not append query parameters to the redirect URI
- See also
Authorization code grant type (3-legged OAuth)
Authorize your app to act on behalf of Indeed user accounts and associated employer accounts.
By using this API and its documentation and building an integration, you agree to the Additional API Terms and Guidelines.
Authorization code grant type (3-legged OAuth) overview
Use the authorization code grant type (3-legged OAuth) to authorize your app to act on behalf of Indeed user accounts and associated employer accounts.
When you become an Indeed partner, Indeed sets up an app for your integration. Sign in to Partner Console to view your app and OAuth credentials (client ID, secret, and authorization code for 3-legged OAuth). Exchange credentials for an access token to authenticate API calls.
You can also complete these tasks:
- Get an access token that represents an employer.
- Get information about the user account that registered an app.
- Dynamically redirect user to multiple URLs.
- Prevent the authorization code from leaking.
Become an Indeed partner
If you are not already a partner, become an Indeed partner.
Get an authorization code
Your app must request the 3-legged OAuth credential: an authorization code.
To initiate the authorization code flow, create a request URL to Indeed's OAuth 2.0 server, requesting the email, offline_access, and employer_access permissions from the user.
After you create this request URL, redirect the user to it. Then, Indeed shows the OAuth consent screen to the user.
If the user selects Allow, Indeed passes an authorization code to the redirect_uri endpoint with the code and state response fields appended. An authorization code expires in 10 minutes.
-
Create the request URL to the Indeed OAuth 2.0 server at
https://secure.indeed.com/oauth/v2/authorize.This example request URL requests the
email,offline_access, andemployer_accesspermissions from the user.This example URL includes line breaks and spaces for readability:
https://secure.indeed.com/oauth/v2/authorize?client_id=c4acac1b35917a14c11947f6564ee28a0758398cd0fdf4deec685c40f14bb8a8&redirect_uri=http%3A%2F%2Fwww.acerecruitersllc.com%2Foauth%2Findeed&response_type=code&scope=email+offline_access+employer_access&state=employer1234The query parameters for
oauth/v2/authorizeare:oauth/v2/authorize query parameters Query parameter Required Description client_id✔
Client ID.
redirect_uri✔
URL-encoded redirect URL. Identifies the redirect page on your site where you capture the authorization code. It must match one of the redirect URLs that your app registers.
response_type✔
Value is always
code.scope✔
Permissions that the client app requests. You must URL-encode and space-delimit scopes, which replaces the spaces with plus signs (
+).In this example, the client requests the
email,offline_access, andemployer_accesspermissions from the user.stateRecommended
Prevents CSRF attacks. Can be any unique string your app creates to maintain state between the request and callback. Indeed passes this parameter to your redirect URI.
-
Redirect the user to the request URL.
-
Indeed shows the OAuth consent screen to the end user that owns the account to which you want access.
If the end user selects Allow, Indeed passes an authorization code to the
redirect_uriwith thecodeandstateresponse fields appended. -
Capture the
codeparameter from theredirect_uripage.For example:
GET http://www.acerecruitersllc.com/oauth/indeed?code=rXZSMNyYQHQ&state=employer1234
Get your OAuth credentials
-
Sign in to Partner Console with your Indeed user account.
-
On the Dashboard, select your app in the Apps list.
The Credentials tab on the app details page lists your OAuth credentials: a client ID and secret.
Get a 3-legged access token
Access tokens are valid for one hour. To refresh an access token, see Refresh your 3-legged access token.
To get an access token, make a POST request to the https://apis.indeed.com/oauth/v2/tokens endpoint with Accept and Content-Type request headers, and request body parameters
curl -L -X POST 'https://apis.indeed.com/oauth/v2/tokens' \ -H 'Accept: application/json' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=authorization_code' \ -d 'client_id=<client_id>' \ -d 'client_secret=<client_secret>' \ -d 'code=<authorization_code>' \ -d 'code_verifier=<code_verifier>' \ -d 'redirect_uri=http://www.acerecruitersllc.com/oauth/indeed'The request headers are:
The request body parameters for oauth/v2/tokens are:
| Request body parameter | Required | Value |
|---|---|---|
grant_type | ✔ | authorization_code |
client_id | ✔ | Your client ID. |
client_secret | ✔ | Your client secret. |
scope | Conditional | Scopes that grant your app permissions. |
code | ✔ | Your authorization code |
code_verifier | ✔ when PKCE is used | The code verifier that generates code_challenge. The code_challenge is recommended for confidential clients. OAuth PKCE code challenge generated from code verifier in RFC 7636: Proof Key for Code Exchange by OAuth Public Clients. |
redirect_uri | ✔ | Your URL-encoded redirect URL. Must match the redirect URL you specified when you got an authorization code. |
{ "access_token": "<access_token>", "convid": "1eis1tplg01fe802", "refresh_token": "<refresh_token>", "scope": "offline_access email", "token_type": "Bearer", "expires_in": 3600}Refresh your 3-legged access token
To refresh an access token, POST to the https://apis.indeed.com/oauth/v2/tokens endpoint with Accept and Content-Type request headers, and request body parameters:
curl -L -X POST 'https://apis.indeed.com/oauth/v2/tokens' \ -H 'Accept: application/json' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=refresh_token' \ -d 'client_id=<client_id>' \ -d 'client_secret=<client_secret>' \ -d 'refresh_token=<refresh_token>' The request headers are:
| Header | Value |
|---|---|
Accept |
|
Content-Type |
|
The request body parameters for oauth/v2/tokens are:
| Request body parameter | Required | Value |
|---|---|---|
grant_type | ✔ | refresh_token |
client_id | ✔ | Your client ID. |
client_secret | ✔ | Your client secret. |
refresh_token | ✔ | Your refresh token. |
{ "access_token": "<access_token>", "id_token": "<id_token>", "refresh_token": "<refresh_token>", "convid": "1c1a1s8540kkt89p", "scope": "email offline_access", "token_type": "Bearer", "expires_in": 3600}Call Indeed APIs
To call an Indeed GraphQL API, send a POST request to https://apis.indeed.com/graphql with these headers and your GraphQL query or mutation:
curl -L 'https://apis.indeed.com/graphql' \ -H 'Authorization: Bearer <access_token>' \ -H 'Content-Type: application/json' \ -d '{"query":"query {\n jobSearch(\n location: { radius: 5, radiusUnit: MILES, where: \"Austin\" }\n what: \"Nurse\"\n limit: 5\n ) {\n results {\n job {\n title\n sourceEmployerName\n }\n }\n }\n}","variables":{}}'Request headers:
| Header | Value | Description |
|---|---|---|
|
| Authenticate with the server to access protected resources. Pass the access token in this header using the note For the See Get an access token and Authorization header. |
|
| The media type of the resource. See Content-Type header. |
The -d parameter specifies the GraphQL query:
query { jobSearch(location: { radius: 5, radiusUnit: MILES, where: "Austin" } what: "Nurse" limit: 5) { results { job { title sourceEmployerName } } }}{ "errors": [{ "message": "The client does not have access to the 'job-retrieval-service' service.", "extensions": { "code": "INTERNAL_SERVER_ERROR" } }], "data": null}Get an access token that represents an employer
Some Indeed APIs require an access token that represents an employer or advertiser.
You can show the user either:
On either screen, a user selects an employer from the list of employers associated with the user.
Then, you get an access token for that employer.
Each access token represents one employer. To switch employers, get a new access token.
Show the Indeed employer selection screen
-
To request the creation of an authorization link to display the Indeed employer selection screen, call the
https://secure.indeed.com/oauth/v2/authorizeendpoint with theprompt=select_employerandscope=employer_accessquery parameters.This call includes both the
prompt=select_employerandscope=employer_accessquery parameters:https://secure.indeed.com/oauth/v2/authorize?client_id=<client_id>&redirect_uri=https%3A%2F%2Fexample.com%2Foauth&response_type=code&state=random&scope=email+offline_access+employer_access&prompt=select_employerThis authorization link triggers the display of these screens:
Indeed-provided screens Screen Description Authentication
Appears when the user is signed out of Indeed.
OAuth consent
Enables a user to grant consent for any scopes that the OAuth app requests, such as the
employer_accessscope.Indeed employer selection
Enables a user to select an employer from a list of employers associated with the user account.
Use Partner Console to view what the OAuth consent screen looks like to your users.
-
If the user selects an employer, a redirect URI parameter transmits the employer ID to your OAuth app:
https://example.com/oauth/callback?state=random&employer=6d2f02224e30d401810b1726eb246d8d&code=e_IEr5UlBysThe URL includes an
employerparameter, which contains an employer ID value.Don't assume that the redirect URI includes an
employerparameter even when you use theprompt=select_employerparameter. -
Proceed to Get employer access token.
Show a custom employer selection screen
Although Indeed recommends that you enable users to select an employer from the standard Indeed employer selection screen, you can also create a custom employer selection screen:
-
Get a 3-legged access token to trigger the OAuth consent screen. When you get the token, request the
employer_accessandoffline_accessscopes.The query returns an access token, ID token, and refresh token.
-
To list employers for the current user, use the JSON Web Tokens Debugger to decode the ID token.
-
Build a custom employer selection screen that enables the user to select an employer.
-
Proceed to Get employer access token.
Get employer access token
Get an access token that represents the employer that the user selects from the employer selection screen.
To get an access token that represents the employer, POST to the https://apis.indeed.com/oauth/v2/tokens endpoint with Accept and Content-Type request headers, and request body parameters:
curl -L -X POST 'https://apis.indeed.com/oauth/v2/tokens' \ -H 'Accept: application/json' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=authorization_code' \ -d 'client_id=<client_id>' \ -d 'client_secret=<client_secret>' \ -d 'redirect_uri=http://localhost' \ -d 'code=<authorization_code>' \ -d 'employer=<employer_id>'The request headers are:
| Header | Value |
|---|---|
Accept |
|
Content-Type |
|
The request body parameters for oauth/v2/tokens are:
| Request body parameter | Required | Value |
|---|---|---|
grant_type | ✔ |
Or:
When using a refresh token to get an access token, no OAuth consent screen is required. |
client_id | ✔ | Your client ID. |
client_secret | ✔ | Your client secret. |
code | ✔ when using an authorization code to get an access token | The authorization code. |
redirect_uri | ✔ | Your URL-encoded redirect URL. |
refresh_token | ✔ when using a refresh token to get an access token | The refresh token. |
employer | ✔ | The ID of the employer. Specify the ID of the employer that the user selected. |
The response contains an access token that represents the employer.
{ "access_token": "<access_token>", "scope": "employer_access", "token_type": "Bearer", "expires_in": 3600}If you request an access token for an employer that is not associated with the user that registered the app, this error occurs:
{ "error_description": "Invalid request", "error": "invalid_request"}Use this access token for API calls on behalf of the consenting user and only for this employer.
You can also use the employer parameter when you exchange a refresh token for an access token.
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.
Get user information
To get information about the user account that registers an app, use either the:
ID token
An ID token is a Base64-encoded JSON Web Token (JWT) that you get automatically when you Get an access token. This token proves that the user has been authenticated.
An Indeed API reads an access token while a third-party app reads an ID token to verify the user's identity.
The ID token contains information about the current user. See id_token.
Because the JSON Web Token is signed, use the public key to verify that the token is valid:
https://secure.indeed.com/.well-known/keysFor information about ID tokens, see ID Token in the OpenID Connect Core 1.0 incorporating errata set 1 specification.
-
So that the ID token includes the
emailandemail_verifiedfields, your app must get theemailscope. -
To get an access token, make a
POSTrequest to thehttps://apis.indeed.com/oauth/v2/tokensendpoint withAcceptandContent-Typerequest headers, and request body parameters:curl -L -X POST 'https://apis.indeed.com/oauth/v2/tokens' \-H 'Accept: application/json' \-H 'Content-Type: application/x-www-form-urlencoded' \-d 'grant_type=authorization_code' \-d 'client_id=<client_id>' \-d 'client_secret=<client_secret>' \-d 'redirect_uri=http://localhost' \-d 'code=<authorization_code>'The request headers are:
Get access token request headers Header Value Acceptapplication/jsonContent-Typeapplication/x-www-form-urlencodedThe request body parameters for
oauth/v2/tokensare:oauth/v2/tokens request body parameters Request body parameter Required Value grant_type✔ authorization_codeOr:
refresh_tokenWhen you use a refresh token to get an access token, an OAuth consent screen is not necessary.
client_id✔ Your client ID.
client_secret✔ Your client secret.
code✔ when using an authorization code to get an access token The authorization code. redirect_uri✔ Your URL-encoded redirect URL. refresh_token✔ when using a refresh token to get an access token The refresh token. employer✔ The employer ID. Specify the ID of the employer that the user selected. The JSON response shows the
id_tokenfield:{"access_token": "<access_token>","convid": "1erq23om7t5bu800","scope": "email employer_access","id_token": "<id_token>","token_type": "Bearer","expires_in": 3600} -
To decode the ID token value, copy it into the JSON Web Tokens Debugger.
The response shows the
subfield, which is the user's account ID:{"sub": "d2d1962c0664d970"}The response shows the
emailandemail_verifiedfields:{"aud": "a0c3b1092225d3e99f85d7aa3fe1e6001f9a0bb798717cbc2008e58fbda3ef16","sub": "d2d1962c0664d970","employers": [{"id": "13ef9940a7c1f0500a7e411e74178c4e","name": "Dharma Initiative"}, {"id": "6d2f02224e30d401810b1726eb246d8d","name": "Umbrella Corporation"}],"email_verified": true,"iss": "https://secure.indeed.com","exp": 1610417960,"iat": 1610414360,"email": "somebody@indeed.com"}
The userinfo endpoint
To get account information for the current user, make a GET request to the https://secure.indeed.com/v2/api/userinfo endpoint with the Authorization: Bearer <access_token> request header. This endpoint does not have any query parameters or request body parameters.
For example, make this request to get account information when you create Log in with Indeed buttons.
The response contains same information that the ID token returns.
A successful request returns the HTTP status code 200 and a response payload:
HTTP/1.1 200 OKContent-Type: application/json
{ "sub": "248289761001", "email": "mina.ray@myemail.world", "email_verified": true}To call the v2/api/userinfo endpoint:
-
Request the
emailscope to return theemailandemail_verifiedfields. -
Get a 3-legged access token with the authorization code grant type.
-
Make a
GETrequest to thehttps://secure.indeed.com/v2/api/userinfoendpoint with theAuthorization: Bearer <access_token>request header:The response contains information for the scopes that a user grants to your OAuth app:
-
The response shows the
subfield, which is the user's account ID:{"sub": "d2d1962c0664d970"} -
The response shows the
emailandemail_verifiedfields:{"sub": "a95064930d19bbc7","email": "somebody+samples@indeed.com","email_verified": true} -
The response lists employers, or advertisers, for the user account:
{"sub": "bc8c847009a955c9","email": "somebody+employer@indeed.com","email_verified": true,"employers": [{"id": "084a39249af95beedfb90cc5d2b8833c","name": "Dharma Initiative"},{"id": "865e08b649774436ee1f410b611fad7c","name": "Umbrella Corporation"},{"id": "4bc393648e880bc94dd6cef8efbc8486","name": "US Robotics and Mechanical Men"}]}
-
Dynamically redirect a user to multiple URLs
When you register an OAuth client app that uses the authorization code grant type (3-legged OAuth), Indeed limits the number of redirect URLs to five, which conforms to the security best practices for OAuth OAuth apps.
To dynamically redirect a user to multiple URLs:
-
Add a
stateparameter to your authorize URL: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+employer_access&state=AnyValue -
Indeed returns the
statequery parameter value in your redirect URL:GET http://www.acerecruitersllc.com/oauth/indeed?code=rXZSMNyYQHQ&state=AnyValue -
To pass a URL with the
stateparameter, such ashttps://somesite.com, URL-encode it: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+employer_access&state=https%3A%2F%2Fsomesite.com -
When Indeed redirects the user to your app, use the
stateparameter value to redirect them to another destination, such ashttps://somesite.com.
Guidelines
Prevent the authorization code from leaking
If you redirect a user to an untrusted website, you inadvertently reveal the OAuth authorization code in the HTTP Referer header, which contains the URL that requested a page.
You might unintentionally expose the authorization code to the website that the state parameter represents. That website likely logs the authorization code in its website logs.
To prevent the authorization code from leaking, redirect the user to another trusted page in your app before you redirect them to the untrusted app. The HTTP Referer header reveals only the latest URL and not any URLs requested before that.
Do not append query parameters to the redirect URI
Currently, Indeed supports query parameters in the redirect_uri parameter.
https://secure.indeed.com/oauth/v2/authorize?client_id=80f9f4bd6a34cac31daebe1a093a606ce6b34e91ae6cfa139432ae387269a529&response_type=code&state=random&scope=email+offline_access+employer_access&redirect_uri=https%3A%2F%2Fsomesite.com%3Freturn%3Dhttps%3A%2F%2Fsomeothersite.comIn this example, the redirect_uri parameter is included in the https://secure.indeed.com/oauth/v2/authorize endpoint.
The redirect_uri parameter value is https://somesite.com?return=https://someothersite.com, which includes the return query parameter that contains another redirect URL.
Indeed recommends using the state parameter instead of query parameters in the redirect_uri parameter.
See also
- Credentials
- HTTP request headers
- oauth/v2/tokens endpoint
- v2/api/appinfo endpoint
- Basic authentication scheme
- Request body parameters for oauth/v2/tokens
- Troubleshoot OAuth errors
- Troubleshoot GraphQL errors