Direct employer integration with Indeed Apply
Integrate with Indeed Apply for direct employers and third parties representing direct employers.
By using this API and its documentation and building an integration, you agree to the Additional API Terms and Guidelines.
All Indeed Apply integrations must include Screener Question capabilities (including EEO for US employers) and Disposition Data by April 2025.
Use Partner Console to manage your apps, their credentials, and associated APIs and services, and access testing tools.
Overview
This resource contains integration instructions for direct employers. Any direct client that wants to provide an XML with or without an Indeed Apply integration should follow these guidelines.
Sending an XML feed to Indeed enables you to better control how your jobs appear on Indeed. Indeed Apply enables job seekers to easily apply to your jobs on Indeed, which improves the job seeker experience and helps you make the right hires faster.
If you have any questions, reach out to your Client Success representative. If you don't have a designated representative, contact us using this web form.
Requirements
To successfully integrate with Indeed Apply, you need:
- A signed Developer Agreement between your company and Indeed.
- A software developer who is familiar with your systems and HTTP, XML, and JSON.
- The capability, such as through FTP access, to publish and refresh the XML feed you build.
- The capability to publish screener questions associated with jobs from your system to an HTTPS URL.
- An Indeed Apply API token. See Generate an API token.
Estimated time to develop and deploy
Experience with hundreds of integrated partners shows that it generally takes six weeks to configure, test, work with Indeed team members to review your Indeed Apply integration, and deploy it for client adoption.
An XML integration requires you to configure and publish an XML feed to Indeed on a regular schedule. These actions let you control how key details about your jobs are displayed on Indeed. You append metadata to each job in this feed to activate the Indeed Apply functionality on Indeed.com, which enables you to surface screener questions in the Indeed Apply application flow and designate where candidate information is delivered to your system.
After you initially configure the XML feed with the Indeed Apply metadata and optional screener questions, Indeed reviews the feed for technical quality assurance and policy compliance.
To designate a method for publishing and updating the feed and to understand the results of Indeed’s review and any required remediation, work with your Client Success representative team.
Roadmap
Complete these XML feed-based integration steps:
- Generate an API token
- Create an XML feed
- Configure Indeed Apply for your jobs
- Add Indeed Apply screener questions
- Receive application data from Indeed
- Test your Indeed Apply configuration
- Monitor integration health
- Submit your XML feed for review
- Send disposition data to Indeed
Generate an API token
Indeed configures your app as part of the onboarding process. After Indeed has configured your app, approved partners can access credentials in Partner Console. For more information, see Credentials.
Get your client ID and secret from Partner Console, and use them to generate an access token.
Create an XML feed
To configure Indeed Apply, create and maintain an XML feed, which is an XML document that defines your jobs and how they appear on the Indeed site.
When you create job listings in your system, those listings go from your XML feed directly to the Indeed XML feed.
An XML feed includes:
- Basic feed nodes. Define general details for an XML feed, including the XML version and encoding.
- Job feed elements. Define job-specific details. Include one set of these elements for each job that appears on Indeed.
See the XML feed reference.
Configure Indeed Apply for your jobs
To enable job seekers to quickly apply from Indeed, use the Easily apply feature through Indeed Apply.
Jobs with the Easily apply feature receive 12% more clicks. Indeed Apply also gives job seekers the option to use their Indeed Resume, further simplifying the application process.
To configure Indeed Apply for your jobs:
- Add Indeed Apply configuration parameters to an
<indeed-apply-data>
element for jobs in your XML feed. - Set up a
postUrl
value in the<indeed-apply-postUrl>
parameter to accept applications from Indeed. - Ensure your system can parse and handle the application data, as necessary.
For configuration parameters, see Indeed Apply configuration reference.
For the <indeed-apply-data>
element, see Indeed Apply XML feed with <indeed-apply-data>
element example.
For more information about the Easily apply feature, see Policy - Indeed Apply and What does easily apply mean?
Add Indeed Apply screener questions
Screener questions enable employers to quickly determine whether an applicant meets their criteria. Adding screener questions to jobs enables employers to focus on connecting with rather than vetting candidates.
Indeed does not host screener questions on your behalf. If your system supports screener questions, you must implement them on Indeed Apply to have your integration approved.
To surface screener questions in the Indeed Apply application flow, format them in JSON and host them at an HTTPS URL that you include in each <job>
in the <indeed-apply-questions>
parameter under the <indeed-apply-data>
element.
See Indeed Apply XML feed with <indeed-apply-data>
element example.
See the Indeed Apply configuration reference.
Considerations
-
You can ask a maximum of 500 questions.
Data indicates that a sharp drop-off in conversion occurs when you ask more than 20 questions.
-
Questions files have a maximum size of 1 MB.
-
Unique question URLs cache questions files server-side. They refresh every 24 hours, or sooner if new requests come in after the cache age exceeds one hour.
-
Indeed does not allow employer requests for unnecessary personally identifiable information (PII) in a job description or during the application process. For more information, see Policy - Personally Identifiable Information (PII).
When a job seeker starts the Indeed Apply process and Indeed requests questions, questions are cached.
JSON for screener questions
For a list of parameters and examples of specific question types, see Screener questions.
Receive application data from Indeed
To receive application data from Indeed, specify a URL in the feed for each job.
This URL receives candidate information in the form of JSON documents for that job.
Application delivery
To process applications programmatically, specify a URL where Indeed Apply sends a POST
request. The <indeed-apply-postUrl>
parameter is a string that defines the URL where Indeed posts the application data. This URL must be HTTPS.
postUrl example
indeed-apply-postUrl=https%3A%2F%2Fyourposturl.com
Make sure your system returns an HTTP 2XX
status code for all applications that it successfully receives. Indeed Apply considers any other HTTP status codes, post timeouts, or connection timeouts as failures.
If Indeed does not receive an HTTP 2XX
status code either through a connect timeout, post timeout, or invalid HTTP response, Indeed tries to resend the application. Indeed uses an exponential backoff method for automatic resends. After the last automatic retry, if delivery is still unsuccessful, Indeed terminally fails the application.
Employers should NOT perform any validation on the content of the job application during the POST
. If you wish to validate the job content and disqualify the applicant, that should occur downstream of the POST
. If there are any HTTP failures related to employer validation of job seeker data, Indeed Apply may be disabled for the company where the application was submitted or for the entire feed.
See the Application delivery reference.
Do not redirect the POST
request to another URL, such as through a 301
or 302
redirect. Indeed Apply does not support redirects.
Duplicate applications
For the purposes of responding to the POST
, an application should only be considered a duplicate if it is for the same Job ID and from the same Job Seeker email as an Indeed application within the last 120 days.
Applications originally submitted from a source other than Indeed should not be used in determining whether an application is a duplicate when responding to the POST
. Applications from the same Job Seeker email to a different Job ID at the same company should similarly NOT be considered a duplicate.
Application data
Because Indeed sends the application data as the raw body of the HTTP POST
request, the request cannot be processed like a typical form. The body of the request contains a JSON document that must be read and parsed. Not all JSON fields are provided, so use a robust JSON parser that treats missing fields as empty and ignores unrecognized fields.
A JSON data payload has no maximum size.
The POST
body is encoded as UTF-8 and contains an authenticity header that is used to verify that Indeed is sending you the application.
A file portion of the Applicant
field contains the contentType
, data
, and fileName
fields.
contentType
is determined based on the fileName
.
The data
field contains the raw resume file, which is Base64-encoded.
The third party must support the following file types: .txt, .pdf, .doc, .docx, and .rtf.
If the third party already has a version of the provided resume saved in their system, they must still store and use the updated version provided in the application JSON.
For application data details, see the Application data reference.
Authentication of the POST request
Indeed Apply sends a POST
request to your postUrl
that contains an HTTP header that you can use to verify the authenticity of the POST
.
Using the shared API secret, which has the Indeed Apply credential type, Indeed uses the HMAC-SHA1 algorithm to compute a message signature. This signature is sent as an HTTP X-Indeed-Signature
header.
To generate signatures, Indeed Apply uses the full unaltered JSON payload, including the curly brackets ({}
) and the shared secret.
For code examples that show how the message signature is generated, see the Message signature generation reference.
Supported SSL certificates
For supported certificates, see the Trusted root SSL certificates.
If your certificate is not listed, contact your Client Success representative.
Email
If you choose to receive applications by email, you must set the email configuration attribute in your button’s configuration. When a user completes the application, Indeed sends an email containing the user’s full name, email address, cover letter, and their resume as an attachment. If the user applies with an Indeed Resume, the version of the resume is directly included in the email and a PDF version is attached. The email address must be encrypted.
The following are not supported by email integrations:
- Screener questions introduced in schema version
1.0
or greater. - Equal Employment Opportunity (EEO) questions.
Encrypted email example 1
<span class="indeed-apply-widget" data-indeed-apply-apiToken="8f57d522dc544a737f70ad5828d5ace1" data-indeed-apply-jobLocation="New York, NY 10110" data-indeed-apply-jobCompanyName="Your Company" data-indeed-apply-jobTitle="Test Engineer" data-indeed-apply-email="b18d0be4c173dfa2b7cb7856e7c7b6f02a563867a9df67ca208c8b9654966299"></span>
Encryption and decryption
When using Indeed Apply through email, you must encrypt the email to which Indeed sends the applications. Indeed expects the email to be encrypted using the AES algorithm with your 128-bit secret key. The cipher mode is CBC with PKCS5 padding. The initialization vector is 16 bytes of 00.
Do not include more than one email address in the data-indeed-apply-email
attribute for any job in your XML feed. Including multiple email addresses results in errors, which removes Indeed Apply from this job.
To encrypt your emails:
- Using your secret key, generate a 128-bit secret key using the first 16 bytes.
- Read the bytes of the plain-text email encoded in UTF-8.
- Encrypt the email using the AES algorithm and your 128-bit key. Be sure to use CBC mode and PKCS5 padding.
- Convert the encrypted bytes to a hex string.
- Use this hex string as your
data-indeed-apply-email
attribute.
Then, use the encrypted email in place of the plain-text email. Indeed Apply recognizes that you are using an encrypted email.
Encrypted email example 2
<span class="indeed-apply-widget" data-indeed-apply-apiToken="8e94c9959e5021fc7f70ad5828d5ace1" data-indeed-apply-jobLocation="Austin TX" data-indeed-apply-jobCompanyName="Your Company" data-indeed-apply-jobTitle="Engineer" data-indeed-apply-email="b18d0be4c173dfa2b7cb7856e7c7b6f02a563867a9df67ca208c8b9654966299"></span>
Encryption and decryption examples
Using C# (version 4.0)
using System.Text;using System.IO;using System;using System.Security.Cryptography;
public class IA_email_encryption_test {
public static void Main(string[] args) {
string email = "john.doe@example.com"; string key = "your api secret key";
// only use first 16 bytes of the key byte[] keybytes = Encoding.UTF8.GetBytes(key); byte[] truncatedkeybytes = new byte[16]; Array.Copy(keybytes, truncatedkeybytes, 16); // initialization vector is all 0's; no additonal initilization required byte[] iv = new byte[16];
byte[] ciphertext = Encrypt(email, truncatedkeybytes, iv);
string hexciphertext = ByteArrayToHexString(ciphertext);
if (!hexciphertext.Equals("eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb")) { Console.WriteLine("invalid encrypted value!"); } else { Console.WriteLine("hex encoded encrypted email: " + hexciphertext); // we decrypt merely as an exercise string decrypted = Decrypt(ciphertext, truncatedkeybytes, iv); Console.WriteLine("Decrypted E-mail: " + decrypted); } }
public static byte[] Encrypt(string plainText, byte[] key, byte[] iv) {
var cypher = new AesManaged(); cypher.Mode = CipherMode.CBC; cypher.Padding = PaddingMode.PKCS7; cypher.KeySize = 128; cypher.BlockSize = 128; cypher.Key = key; cypher.IV = iv;
var icTransformer = cypher.CreateEncryptor(); var msTemp = new MemoryStream();
var csEncrypt = new CryptoStream(msTemp, icTransformer, CryptoStreamMode.Write); var sw = new StreamWriter(csEncrypt); sw.Write(plainText); sw.Close(); sw.Dispose();
csEncrypt.Clear(); csEncrypt.Dispose();
byte[] bResult = msTemp.ToArray();
return bResult; }
public static string Decrypt(byte[] ciphertext, byte[] key, byte[] iv) {
var cypher = new AesManaged(); cypher.Mode = CipherMode.CBC; cypher.Padding = PaddingMode.PKCS7; cypher.KeySize = 128; cypher.BlockSize = 128; cypher.Key = key; cypher.IV = iv;
var icTransformer = cypher.CreateDecryptor(); var msTemp = new MemoryStream(ciphertext);
var csDecrypt = new CryptoStream(msTemp, icTransformer, CryptoStreamMode.Read); var sr = new StreamReader(csDecrypt);
string plaintext = sr.ReadToEnd();
csDecrypt.Clear(); csDecrypt.Dispose();
return plaintext; }
private static string ByteArrayToHexString(byte[] bytes) { StringBuilder sbHex = new StringBuilder(); foreach(byte b in bytes) sbHex.AppendFormat("{0:x2}", b); return sbHex.ToString(); }}
Using Java (version 1.8)
import java.nio.ByteBuffer;import java.nio.charset.Charset;import java.lang.RuntimeException;import javax.crypto.Cipher;import javax.crypto.spec.*;import javax.crypto.spec.SecretKeySpec;
public class Main {
public static void main(String[] args) {
String email = "john.doe@example.com"; String apiSecret = "your api secret key"; String encrypted_email = encrypt(email, apiSecret); String decrypted_email = decrypt(encrypted_email, apiSecret); if (encrypted_email.equals("eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb")) { System.out.println("B64 encoded encrypted email: " + encrypted_email); System.out.println("decrypted email: " + decrypted_email); } else { System.out.println("invalid encrypted value!"); } }
static String encrypt(String message, String apiSecret) { try { // get api secret bytes byte[] keyBytes = apiSecret.getBytes(Charset.forName("UTF-8")); // get message bytes byte[] message_bytes = message.getBytes("UTF-8"); // note that we only use the first 16 bytes of the key SecretKeySpec key = new SecretKeySpec(keyBytes, 0, 16, "AES"); // get appropriate cipher using PKCS5 padding Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); IvParameterSpec ivspec = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); cipher.init(Cipher.ENCRYPT_MODE, key, ivspec); // encrypt the message byte[] email_encrypted = cipher.doFinal(message_bytes); // this is the value that should be sent to Indeed return bytesToHexString(email_encrypted); } catch (Exception e) { System.out.println(e.getMessage()); throw new RuntimeException(e); } }
static String decrypt(String message, String apiSecret) { try { // get api secret bytes byte[] keyBytes = apiSecret.getBytes(Charset.forName("UTF-8")); // get message bytes byte[] message_bytes = message.getBytes(Charset.forName("UTF-8")); // convert from b64 encoding message_bytes = decodeHex(message_bytes); // Create a SecretKeySpec using api secret // note that we only use the first 16 bytes of the key SecretKeySpec key = new SecretKeySpec(keyBytes, 0, 16, "AES"); // get appropriate cipher using PKCS5 padding Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); IvParameterSpec ivspec = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); cipher.init(Cipher.DECRYPT_MODE, key, ivspec); // decrypt the message byte[] email_decrypted = cipher.doFinal(message_bytes); return new String(email_decrypted, "UTF-8"); } catch (Exception e) { System.out.println(e.getMessage()); throw new RuntimeException(e); } }
static String bytesToHexString(byte[] in) { final StringBuilder builder = new StringBuilder(); for (byte b: in) { builder.append(String.format("%02x", b)); } return builder.toString(); }
static byte[] decodeHex(byte[] data) throws Exception { String text = new String(data, "UTF-8"); char[] chars = text.toCharArray();
int len = chars.length; byte[] out = new byte[len >> 1]; int i = 0;
for (int j = 0; j < len; ++i) { int f = toDigit(chars[j], j) << 4; ++j; f |= toDigit(chars[j], j); ++j; out[i] = (byte)(f & 255); } return out; }
static int toDigit(char ch, int index) throws Exception { int digit = Character.digit(ch, 16); if (digit == -1) { throw new Exception("Illegal hexadecimal character " + ch + " at index " + index); } else { return digit; } }}
Using Perl (version 5.0)
use Crypt::CBC;use Encode;
# your secret keymy $secret = encode('UTF-8', 'your api secret key');# truncate key to 16 bytesmy $key = substr($secret, 0, 16);# initialization vector of zerosmy $iv = "\0"x 16;# create ciphermy $cipher = Crypt::CBC - & gt;new(-literal_key = & gt; 1, -header = & gt; 'none', -key = & gt; $key, -keysize = & gt; 16, -iv = & gt; $iv, -cipher = & gt; "Crypt::OpenSSL::AES");# Encrypt the UTF - 8 encoded string into a hex version of the datamy $email_encrypted = $cipher - & gt;encrypt_hex(encode('UTF-8', 'john.doe@example.com'));
if ($email_encrypted eq 'eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb') { print "Hex value of encrypted: $email_encryptedn"; # Decrypt the hex string to see if it 's still intact my $email_decrypted = $cipher - & gt; decrypt_hex($email_encrypted); print "Decrypted: $email_decryptedn";} else { print "invalild encrypted value! $email_encryptedn";}
Using PHP (version 7.0)
function pkcs5_pad ($text) { $blocksize = 16; $pad = $blocksize - (strlen($text) % $blocksize); $text .= str_repeat(chr($pad), $pad); return $text;}
function pkcs5_unpad($text) { $pad = ord($text{strlen($text)-1}); if ($pad > strlen($text)) return false; if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false; return substr($text, 0, -1 * $pad);}
function encrypt($str, $key) { $iv = str_repeat("\0", 16); $str = pkcs5_pad($str); $opts = OPENSSL_RAW_DATA; $encrypted = openssl_encrypt($str, 'AES-128-CBC', $key, $opts, $iv); return $encrypted;}
function decrypt($str, $key) { $iv = str_repeat(""\0", 16); $opts = OPENSSL_RAW_DATA; $decrypted = openssl_decrypt($str, 'AES-128-CBC', $key, $opts, $iv); return pkcs5_unpad($decrypted);}
$api_secret = "your api secret key";$email_address = "john.doe@example.com";
// truncate api-secret to first 16 bytes$newkey = mb_strcut($api_secret, 0, 16, "UTF8");// encrypt$encrypted = encrypt($email_address, $newkey);// we decrypt merely as an exercise$decrypted = decrypt($encrypted, $newkey);// this is the value to send to Indeed$encryptedhex = bin2hex($encrypted);if($encryptedhex != "eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfba655e21c3309d9343206ae55866764e8") print("invalid encrypted hex value!");print("Hex value of encrypted: " . $encryptedhex . "n");print("Decrypted: " . $decrypted . "n");
Using Python (version 2.7)
# https://pypi.python.org/pypi/pycryptodome/3.5.1from Crypto.Cipher import AES# https://pypi.python.org/pypi/pkcs7/0.1.2from pkcs7 import PKCS7Encoder# your secret keysecret = 'your api secret key'.encode('utf-8')# truncate key to 16 byteskey_bytes = secret[0:16]# initialization vector of zerosiv = '\0' * 16# the email address to encryptmessage_plaintext = 'john.doe@example.com'# pad the plaintext to 16 byte boundaryPKCS7encoder = PKCS7Encoder()message_plaintext_padded = PKCS7encoder.encode(message_plaintext);# encrypt the message bytescipher = AES.new(key_bytes, AES.MODE_CBC, iv)message_encrypted_raw = cipher.encrypt(message_plaintext_padded)# this is the value that should be sent to Indeedmessage_encrypted_hex = message_encrypted_raw.encode('hex')# we need a new instance for decrypt because the ciphers are statefuldecipher = AES.new(key_bytes, AES.MODE_CBC, iv)# we decrypt here simply as an exercisemessage_decrypted_raw = decipher.decrypt(message_encrypted_raw)# strip paddingmessage_decrypted = PKCS7encoder.decode(message_decrypted_raw)# confirm encrypted valueif message_encrypted_hex == "eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb": print 'Hex value of encrypted: ' + message_encrypted_hex print 'Decrypted: '+message_decryptedelse: print 'invalild encrypted value! ' + message_encrypted_hex
Using Python (version 3.6)
# https://pypi.python.org/pypi/pycryptodome/3.5.1from Crypto.Cipher import AES
# https://pypi.python.org/pypi/pkcs7/0.1.2from pkcs7 import PKCS7Encoder
# your secret keysecret = "your api secret key".encode("utf-8")# truncate key to 16 byteskey_bytes = secret[0:16]# initialization vector of zerosiv = bytes("\0" * 16, encoding="UTF-8")# the email address to encryptmessage_plaintext = "john.doe@example.com"# pad the plaintext to 16 byte boundaryPKCS7encoder = PKCS7Encoder()message_plaintext_padded = PKCS7encoder.encode(message_plaintext)# encrypt the message bytesmessage_bytes = message_plaintext_padded.encode("UTF-8")cipher = AES.new(key_bytes, AES.MODE_CBC, iv)message_encrypted_raw = cipher.encrypt(message_bytes)# this is the value that should be sent to Indeedmessage_encrypted_hex = message_encrypted_raw.hex()# we decrypt here simply as an exercisedecipher = AES.new(key_bytes, AES.MODE_CBC, iv)message_decrypted_raw = decipher.decrypt(message_encrypted_raw).decode("UTF-8")# strip paddingmessage_decrypted = PKCS7encoder.decode(message_decrypted_raw)# confirm encrypted valueif ( message_encrypted_hex == "eaaacff9df2e4c2a63083a303d4521f0bd41e375232a2895310179bc030addfb"): print("Hex value of encrypted: " + message_encrypted_hex) print("Decrypted: " + message_decrypted)else: print("invalild encrypted value! " + message_encrypted_hex)
Test your Indeed Apply configuration
Indeed provides a number of tools that enable you to test the components of your Indeed Apply integration.
To identify and proactively correct integration issues, review these topics to learn about the available testing tools and resources.
Test Indeed Apply application flow and applicant delivery
To test your integration setup and make sure that everything is running smoothly prior to pushing a job or integration live, Indeed provides the Apply XML Configuration Testing Tool.
You can input your Indeed Apply XML metadata for a job into the tool or the tool can generate XML metadata for you based on a number of configurable parameters. The tool identifies errors in formatting and content, enabling you to quickly identify any issues.
If no errors are detected, the tool shows the Start testing button. To see what the application process looks like to a prospective job seeker and to submit a test application to ensure the process works correctly, select Start testing. Assuming your postUrl
is valid, the test application sent to the postUrl
with the application data payload can help you validate that your system is correctly parsing the JSON document and that the applicant info is showing in your system as you would expect.
Test your Indeed Apply XML metadata
The first tab of the Indeed Apply XML Configuration Testing Tool enables you to input the Indeed Apply metadata from XML and review it in the Indeed Apply application flow. So that you can see your detected job elements, the Configuration section in this tab also lists all parameters that are included in the XML.
For more information about the supported parameters, see the Indeed Apply configuration reference.
Indeed Apply XML configuration testing tool - XML tab
Additionally, the tool automatically identifies any errors within your metadata that might cause Indeed Apply to malfunction. For example, the tool detects whether a required parameter is missing or the file is not formatted correctly. In either case, the tool shows an alert.
Example: Incorrect parameter format error
Example: Missing parameter error
The second tab of the Apply XML Configuration Testing Tool enables you to fill in a variety of configurable parameters and generates corresponding XML metadata for Indeed Apply automatically. You can also see how the job appears in the application flow with the provided information.
Once generated, you can add the metadata into your existing XML feed. For an example, see the Create an XML feed.
Configuration testing tool - Configurable parameters tab
Beyond the default parameters provided, you can also add additional parameters from a list of options. Once selected and filled in, these parameters are automatically added to the generated XML.
This tool enables you to mock up your Indeed Apply and by providing your postUrl
within the Indeed Apply tags, the tool enables you walk through the application experience and POST
the application to the URL specified in the tools sample data.
Test your Indeed Apply screener questions
You can also verify the syntax of your Screener Questions JSON file by using the Indeed Apply Questions tool. This tool displays how screener questions appear in the Indeed Apply application flow. This tool displays how screener questions appear in the Indeed Apply application flow.
Indeed Apply Questions tool
You can paste your entire JSON file into the main field of this interactive tool to highlight errors in formatting.
Error message examples
Right-click on the editor to run basic text commands.
Basic text commands
For more advanced commands, such as those in VS code, select the "Command Palette" or press F1.
More advanced commands
The tool also includes a link back to this documentation so that you can reference the relevant JSON parameters as needed.
After your JSON appears to be formatted correctly, select Start testing to see a preview of how your screener questions appear to job seekers.
Monitor integration health
When you integrate with Indeed Apply, set up monitoring to ensure that:
- The integration successfully delivers job applications.
- Questions files are valid and consistently available.
Indeed also monitors whether applications are delivered successfully via integrations, along with other integration health indicators. If any problems arise, Indeed might contact you. In some cases, Indeed can disable the Indeed Apply feature for some or all of your feed’s jobs until you correct any issues.
Undelivered applications are not lost. In case of failure, retry attempts are made automatically at periodic intervals after the original application is submitted. If delivery is not possible, applications are retained for 60 days and retry attempts can be made on request by contacting your Client Success representative.
If your integration supports screener questions, verify that the pages that host those files are consistently available, do not redirect, and are properly formatted.
Submit your XML feed for review
To avoid delays, review and complete the following checklist before submitting the XML feed to your Client Success representative.
Pre-submission checklists
XML file
Checklist | Confirm (Yes/No) |
---|---|
Verify that the XML file defines all basic feed nodes, including the XML version and encoding:
| |
Verify that the XML file includes a | |
Verify that the XML file includes all companies associated with jobs. | |
Verify that the XML file does not include any TEST jobs. | |
All URLs that the XML file includes as metadata are URL-encoded. URL elements include the | |
No HTML escape characters ANYWHERE : (&, <, >, and so on) | |
Salary tags are provided for all jobs. | |
External ID matches the career website content. | |
All jobs have an |
Indeed Apply - Screener questions
Checklist | Details | Confirm (Yes/No) |
---|---|---|
XML content | Verify that the | |
All URLs within the Indeed Apply parameter are URL-encoded.URL elements include the | ||
The | ||
HTTP codes / Security for post requests | HTTP 200 response for successful applications | |
HTTP 409 for duplicate applications | ||
HTTP 410 for applications on expired jobs | ||
HTTP 400 if the structure of the JSON payload is missing a required key | ||
HTTP 401 for an invalid or missing X-Indeed-Signature header value | ||
HTTP 404 for an invalid job (job does not exist) | ||
HTTP 413 for payload too large | ||
HTTP 422 for missing required answer to screener questions | ||
The X-Indeed-Signature header is being verified (Authentication of the POST requests.) | ||
Indeed Apply POST URL, screener questions URL are secure HTTPS. | ||
Alerts and logging | Enable alerting for Post requests delivery logs should include:
Provide an example of these logs (screenshot or text file.) | |
Enable alerting for GET requests for screener questions URL to capture failures. Screener question logs include:
Provide an example of logs (screenshot or text file.) | ||
Job seeker application data delivery | The candidate’s first and last name are obtained from the JSON applicant.firstName and applicant.lastName fields. | |
Uploaded CV file is captured and stored correctly on your platform (Example.) | ||
Indeed Resume CV file is captured and stored correctly on your platform (Example.) | ||
Confirm there are no application payload size restrictions. | ||
Screener questions | Screener questions are constructed by following the best practices. | |
Additional cover letters and other docs included as part of the application are captured and stored (Applicant fields.) | ||
See Policy - Personally Identifiable Information (PII) for PII restrictions. PII, such as the full Social Security Number (SSN), cannot be asked as a screener question. | ||
General requirements | Ensure you identify the job seeker applications received through Indeed Apply with source as “Indeed” on your platform. | |
Verify that your analytics field can categorize applications as organic, sponsored, or Indeed Targeted Ad. | ||
Check that your SSL certificate is valid and up-to-date. |
Send disposition data to Indeed
Disposition data is information about an update to an application in your system.
An update can be a change in your workflow or an action that you take after the candidate applies. An example of disposition data is, a candidate is hired.
By sending disposition data to Indeed, you receive higher quality applications over time.
See the Disposition Sync API Guide.