# Adding Support for Snagajob's Easy Apply

{% hint style="warning" %}
Before implementing Easy Apply, please fill out our [Obtaining API Access](/authentication/obtaining-api-access.md#vendor-intake-form) to obtain your API secret and become a registered partner with Snagajob. We will not pass Easy Apply application data to unregistered partners.
{% endhint %}

## Brief Process Overview

1. You pass us job postings via an XML feed with the qualifications per requisition.
2. You pass us an endpoint URL (per job) via your feed within the `<PostUrl>`XML element&#x20;
   1. **Example:** `<PostUrl>https://myapplicantapi.com/sajeasyapply</PostUrl>`
3. **(Optional)** You pass us a URL containing JSON formatted screening questions in the `<ScreeningQuestionsUrl>` element per job.
4. We post your jobs and enable our Easy Apply application experience.
5. We send the application data back to the PostUrl each time a worker applies. Data is transmitted to the URL specified in the `<PostUrl>` element.

## Adding Easy Apply to your XML Feed

{% hint style="info" %}
Please reference[XML Feed Reference](/posting-creation/xml-feed-reference.md#easy-apply-feed-elements) for a list of XML feed elements to add to your feed files to enable Easy Apply.
{% endhint %}

Converting your postings to Easy Apply allows workers to apply to your jobs directly on Snagajob with their profile.

To convert your postings to Easy Apply, partners must add a `<PostUrl>` XML element to each job in their feed containing an HTTPS endpoint that Snagajob should POST applications to.

See this XML example: [XML Feed Reference](/posting-creation/xml-feed-reference.md#single-customer-feed-xml-example)

`<PostUrl>https://myapplicantapi.com/where-applications-should-go</PostUrl>`

## Using Screening Questions

Format screener questions in JSON and post them to a URL (HTTPS) included for each `<Item>` in the `<ScreeningQuestionsUrl>` element. Snagajob does not host screening questions on your behalf.

`<ScreeningQuestionsUrl>https://myapplicantapi.com/where-we-find-questions</ScreeningQuestionsUrl>`

### **JSON for screening questions**

This section lists the parameters used in building all question types. For examples of specific question types, refer to Screening question types.

#### Screening question parameters

<table data-full-width="true"><thead><tr><th>Name</th><th>Required</th><th>Description</th><th>Allowed values</th><th>Example</th></tr></thead><tbody><tr><td><code>id</code></td><td><mark style="background-color:yellow;"><strong>Yes</strong></mark></td><td>Unique ID for this question.</td><td>any string</td><td><code>question-123</code></td></tr><tr><td><code>type</code></td><td><mark style="background-color:yellow;"><strong>Yes</strong></mark></td><td>Describes the type of question.</td><td><strong>select</strong><br><strong>multiselect</strong><br><strong>textarea</strong></td><td><code>textarea</code></td></tr><tr><td><code>question</code></td><td><br><mark style="background-color:yellow;"><strong>Yes</strong></mark></td><td>The question text that applicants see.</td><td>any string</td><td>Are you 18 years or older?</td></tr><tr><td><code>options</code></td><td><mark style="background-color:yellow;"><strong>Yes</strong></mark> for <code>type=select</code> and <code>type=multiselect</code></td><td>The list of options available for the worker to answer.</td><td>JSON</td><td><code>[{ "value":"1", "label":"Yes" },</code><br><code>{ "value":"2", "label":"No" }]</code></td></tr><tr><td><code>value</code></td><td><mark style="background-color:yellow;"><strong>Yes</strong></mark> for <code>type=select</code> and <code>type=multiselect</code></td><td>The <code>value</code> corresponds to each option returned for questions with multiple options.</td><td>any string</td><td>1</td></tr><tr><td><code>label</code></td><td><mark style="background-color:yellow;"><strong>Yes</strong></mark> for <code>type=select</code> and <code>type=multiselect</code></td><td>The text displayed for each corresponding option.</td><td>any string</td><td>Yes</td></tr><tr><td><code>required</code></td><td>No</td><td>Allows you to set a question as required. When <code>required:true</code> is present, Snagajob forces a non-empty text field or a non-empty selection.</td><td>boolean</td><td><code>"required":true</code></td></tr><tr><td><code>format</code></td><td>No</td><td>The accepted format of the input. If left <code>null</code> , we will default to a <code>string</code> type.</td><td>Supported type enforcement:<br>- integer<br>- decimal</td><td><code>”format“: “integer”</code></td></tr><tr><td><code>condition</code></td><td>No</td><td><p>Marks a question as conditional, depending on the answer to a previous select question. Specify the id of the previous question and the option value that activates this question.</p><p>For example, you might ask applicants if they’ve previously worked for a specific employer. Then, depending on their selection, you could offer another question to describe their experience.</p></td><td>JSON</td><td><code>"condition": { "id": "parent", "value": 0}</code></td></tr></tbody></table>

#### Screening question types

**select**

This is a question type that presents all available options and allows the respondent to choose a single answer. Used for questions that should only have one answer.

**Example:**

```json
{
  "id": "gender",
  "type": "select",
  "question": "What is your gender?",
  "required": true,
  "options": [{
      "value": "0",
      "label": "Decline to answer"
    },
    {
      "value": "1",
      "label": "Male"
    },
    {
      "value": "2",
      "label": "Female"
    }
  ]
}
```

**multiselect**

This is a multiple-choice question that allows the user to select multiple answers.

**Example:**

```json
{
  "id": "availability",
  "type": "multiselect",
  "question": "Select the days you are available to work.",
  "required": true,
  "options": [{
      "value": "0",
      "label": "Monday"
    },
    {
      "value": "1",
      "label": "Tuesday"
    },
    {
      "value": "2",
      "label": "Wednesday"
    },
    {
      "value": "3",
      "label": "Thursday"
    },
    {
      "value": "4",
      "label": "Friday"
    },
    {
      "value": "5",
      "label": "Saturday"
    },
    {
      "value": "6",
      "label": "Sunday"
    }
  ]
}
```

**textarea**

A question that displays a text entry field.

**Example:**

```json
{
  "id": "color",
  "type": "textarea",
  "question": "Whats your favorite color?",
  "required": true
}
```

**Making questions conditional**

This is a question that may or may not be displayed based on the responses to previous questions. For instance, you may inquire if the applicants have worked for a particular employer before. Then, depending on their answer, you could present another question to have them describe their experience.

**Example:**

```json
[
  {
    "id": "previous-employment",
    "type": "select",
    "question": "Have you worked for this employer in the past?",
    "required": true,
    "options": [
      {
        "value": "0",
        "label": "Yes"
      },
      {
        "value": "1",
        "label": "No"
      }
    ]
  },
  {
    "id": "please-explain",
    "type": "textarea",
    "question": "If yes, please explain your experience there.",
    "required": true,
    "condition": {
      "id": "previous-employment",
      "value": "0"
    }
  }
]
```

## Application Data Delivery

To accept candidate data via API, you must include a POST URL on each posting in the XML feed you wish to accept programmatically.

### PostUrl

Specify a URL where Snagajob will send a `POST` request containing the application data. **Must be** `HTTPS`.

**Example URL:**

`<PostUrl>https://myapplicantapi.com/where-applications-should-go</PostUrl>`

### Sample JSON of Application Data from Snagajob

```json
{
	"id": "applicationId12345",
    "applicantAddress": {
        "line1": "123 Main St.",
        "line2": "",
        "city": "Richmond",
        "stateProvCode": "VA",
        "postalCode": "23219"
    },
    "emailAddress": "first.last@testing.com",
    "employment": [
        {
            "employerName": "We Paint Cars",
            "endDate": null,
            "jobTitle": "Automotive Painter",
            "startDate": "2019-01-01T05:00:00Z"
        },
        {
            "employerName": "Local Library",
            "endDate": "2018-05-01T04:00:00Z",
            "jobTitle": "Librarian",
            "startDate": "2015-01-01T05:00:00Z"
        },
        {
            "employerName": "Fast Food Chicken Chain",
            "endDate": "2014-12-01T05:00:00.00Z",
            "jobTitle": "Assistant Manager",
            "startDate": "2011-07-01T04:00:00Z"
        }
    ],
    "firstName": "First",
    "lastName": "Last",
    "fullName": "First Last",
    "isAuthorizedToWorkInUs": true,
    "phoneNumber": "8045551234",
    "ipAddress": "1.1.1.1",
    "userAgent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0",
    "qualifications": [
        {
            "displayText": "Background check",
            "isPass": true,
            "name": "q-basic-bgcheck",
            "required": false
        },
        {
            "displayText": "14 years or older",
            "isPass": true,
            "name": "q-basic-dob",
            "option": 1,
            "required": true
        },
        {
            "displayText": "Legally authorized to work in the United States",
            "isPass": true,
            "name": "q-basic-auth",
            "required": true
        },
        {
            "displayText": "At least associate's degree or higher",
            "isPass": true,
            "name": "q-exp-degree",
            "option": 2,
            "required": true
        }
    ],
    "requisitionId": "req12345",
    "resume": {
        "contentType": "application/pdf",
        "data": "U25hZ2Fqb2I="
    },
    "questionsAndAnswers": [
        {
            "question": {
                "id": "gender",
                "question": "What is your gender?",
                "type": "select",
                "required": true,
                "options": [
                    {
                        "value": "0",
                        "label": "Decline to answer"
                    },
                    {
                        "value": "1",
                        "label": "Male"
                    },
                    {
                        "value": "2",
                        "label": "Female"
                    }
                ]
            },
            "answer":{
	            "selectedAnswers": [
	                {
	                    "value": "2",
	                    "label": "Female"
	                }
	            ]
            }
        },
        {
            "question": {
                "id": "availability",
                "question": "Select the days you are available to work.",
                "type": "multiselect",
                "required": true,
                "options": [
                    {
                        "value": "0",
                        "label": "Monday"
                    },
                    {
                        "value": "1",
                        "label": "Tuesday"
                    },
                    {
                        "value": "2",
                        "label": "Wednesday"
                    }
                      {
                        "value": "3",
                        "label": "Thursday"
                    },
                    {
                        "value": "4",
                        "label": "Friday"
                    },
                    {
                        "value": "5",
                        "label": "Saturday"
                    },
                    {
                        "value": "6",
                        "label": "Sunday"
                    }
                ]
            },
            "answer": {
            	"selectedAnswers": [
	                {
	                    "value": "4",
	                    "label": "Friday"
	                },
	                {
	                    "value": "5",
	                    "label": "Saturday"
	                },
	                {
	                    "value": "6",
	                    "label": "Sunday"
	                }
	            ]
            }
        },
        {
            "question": {
                "id": "color",
                "type": "textarea",
                "question": "Whats your favorite color?",
                "required": true
            },
            "answer": {
            	"answerText": "blue"
        	}
        }
    ]
}
```

### Candidate Data Field Descriptions

#### **Applicant Fields** **Table**

<table data-full-width="true"><thead><tr><th width="367">Value</th><th>Always provided?</th><th width="323">Description</th><th>Type</th></tr></thead><tbody><tr><td>id</td><td><strong>Yes</strong></td><td>Unique ID for the application</td><td>string</td></tr><tr><td>applicantAddress</td><td><strong>Partially</strong></td><td>JSON object representing the user's location.</td><td>object</td></tr><tr><td>applicantAddress.line1</td><td>No</td><td>The address line 1 of the Candidate’s address</td><td>string</td></tr><tr><td>applicantAddress.line2</td><td>No</td><td>The address line 2 of the Candidate’s address</td><td>string</td></tr><tr><td>applicantAddress.city</td><td>No</td><td>The city of the Candidate’s address</td><td>string</td></tr><tr><td>applicantAddress.stateProvCode</td><td>No</td><td>The state province code of the Candidate’s address</td><td>string</td></tr><tr><td>applicantAddress.postalCode</td><td><strong>Yes</strong></td><td>The postal code of the Candidate’s address</td><td>string</td></tr><tr><td>emailAddress</td><td><strong>Yes</strong></td><td>The email address of the Candidate.</td><td>string</td></tr><tr><td>employment</td><td>No</td><td>JSON object representing the user's work history.</td><td>object</td></tr><tr><td>employment.employerName</td><td>No</td><td>The company's name.</td><td>string</td></tr><tr><td>employment.endDate</td><td>No</td><td>A string containing a timestamp representing the ending employment date.</td><td>string</td></tr><tr><td>employment.jobTitle</td><td>No</td><td>The title of the job.</td><td>string</td></tr><tr><td>employment.startDate</td><td>No</td><td>A string containing a timestamp representing the starting employment date.</td><td>string</td></tr><tr><td>firstName</td><td><strong>Yes</strong></td><td>The first name of the Candidate.</td><td>string</td></tr><tr><td>lastName</td><td><strong>Yes</strong></td><td>The last name of the Candidate.</td><td>string</td></tr><tr><td>fullName</td><td><strong>Yes</strong></td><td>The full name of the Candidate.</td><td>string</td></tr><tr><td>isAuthorizedToWorkInUs</td><td>No</td><td>Boolean field indicating a Candidates eligibility to work in the US.</td><td>boolean</td></tr><tr><td>phoneNumber</td><td><strong>Yes</strong></td><td>The phone number of the Candidate.</td><td>string</td></tr><tr><td><strong>[Obsolete]</strong> qualifications</td><td>No</td><td>JSON object representing the user's qualification question answers. <strong>This object will continue to be present as vendors transition to the new</strong> <code>questionsAndAnswers</code> <strong>object, but will eventually be depreciated.</strong></td><td>object</td></tr><tr><td><strong>[Obsolete]</strong> qualifications.displayText</td><td>No</td><td>This is the question displayed to the worker.</td><td>string</td></tr><tr><td><strong>[Obsolete]</strong> qualifications.isPass</td><td>No</td><td>"isPass": true means the worker answered Yes to the question "isPass": false means the worker answered No to the question</td><td>boolean</td></tr><tr><td><strong>[Obsolete]</strong> qualifications.name</td><td>No</td><td>The name of the qualification</td><td>string</td></tr><tr><td><strong>[Obsolete]</strong> qualifications.required</td><td>No</td><td>This field signifies if the employer requires the worker to answer 'Yes' ("isPass": true) to be qualified for the role.</td><td>boolean</td></tr><tr><td><strong>[Obsolete]</strong> qualifications.option</td><td>No</td><td>For Scaling (Type 3) questions, the employer can ask multiple variations of the same question (For example, asking if the worker has more than one type of food certification). This field indicates which answer the isPass answer corresponds to.</td><td>int</td></tr><tr><td>requisitionId</td><td><strong>Yes</strong></td><td>The requisition id of the job the Candidate is applying to. This id will match the id value passed into the feed.</td><td>string</td></tr><tr><td>resume</td><td><strong>Yes</strong></td><td>JSON object representing Candidate’s resume.</td><td>object</td></tr><tr><td>resume.contentType</td><td><strong>Yes</strong></td><td>The content type identified using the resume file's extension.</td><td>string</td></tr><tr><td>resume.data</td><td><strong>Yes</strong></td><td>The file's raw binary bytes encoded using base 64.</td><td>string</td></tr><tr><td>questionsAndAnswers</td><td>No</td><td>JSON object representing the user's screening questions and answers as outlined above</td><td>object</td></tr><tr><td>questionsAndAnswers.question</td><td>No</td><td>JSON object containing the question details</td><td>object</td></tr><tr><td>questionsAndAnswers.question.id</td><td>No</td><td>Unique ID for the question</td><td>string</td></tr><tr><td>questionsAndAnswers.question.question</td><td>No</td><td>The question text that applicants see.</td><td>string</td></tr><tr><td>questionsAndAnswers.question.type</td><td>No</td><td>Describes the type of question.</td><td>string</td></tr><tr><td>questionsAndAnswers.question.required</td><td>No</td><td>Identifies if the question contained a required input</td><td>boolean</td></tr><tr><td>questionsAndAnswers.question.options</td><td>No</td><td>The list of options that were available for the worker to answer.</td><td>array</td></tr><tr><td>questionsAndAnswers.answer</td><td>No</td><td>JSON object containing the answer details</td><td>object</td></tr><tr><td>questionsAndAnswers.answer.selectedAnswers</td><td>No</td><td>The answer options selected by the Worker. <strong>Note:</strong> This field will only be populated for questions with a <code>”type”:”select”</code> and <code>”type”:”multiselect”</code></td><td>array</td></tr><tr><td>questionsAndAnswers.answer.answerText</td><td>No</td><td>The answer text that was submitted by the Worker. <strong>Note:</strong> This field will only be populated for questions with a <code>”type”:”textarea”</code>.</td><td>string</td></tr><tr><td>ipAddress</td><td>No</td><td>The IP address of the Candidate’s device</td><td>string</td></tr><tr><td>userAgent</td><td>No</td><td>The user agent of the Candidate’s device</td><td>string</td></tr></tbody></table>

### **Validating the Posts Authenticity**

Snagajob signs each application post request made to your `PostUrl` with the HTTP header `X-SAJ-Signature` that partner can use to verify the post's authenticity. Snagajob Easy Apply computes the message signature using the HMAC-SHA1 algorithm using the shared API secret. This signature is sent as an `X-SAJ-Signature` HTTP header. An `X-SAJ-Date` HTTP header is also included and should be used to ignore any requests over 15 minutes old.&#x20;

The code examples below demonstrate how the message signature is generated.

```csharp
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
 
public class Program
{
    public static void Main(string[] args)
    {
        string requestBody = GetRequestBody();
        string apiSecret = "your api secret key";
        string requestXSAJDate = "Thu, 13 Jan 2022 17:21:07 GMT";
 
        string  signature = ComputeSignature($"{requestBody};{requestXSAJDate}", apiSecret);
        if (signature.Equals("AIAvMLdPqjbNocJ4UHZpg3Axxzk="))
        {
            Console.WriteLine("B64 HMAC SHA1: " + signature);
        }
        else
        {
            Console.WriteLine("invalid value: " + signature);
        }
    }
 
    private static string ComputeSignature(string input, String key)
    {
        byte[] keyBytes = Encoding.UTF8.GetBytes(key);
        using(HMACSHA1 myhmacsha1 = new HMACSHA1(keyBytes))
        {
            byte[] inputBytes = Encoding.UTF8.GetBytes(input);
            byte[] hash = myhmacsha1.ComputeHash(inputBytes);
            return Convert.ToBase64String(hash);
        }
    }
 
    private static string GetRequestBody()
    {
        return "{\"firstName\":\"John\", \"lastName\":\"Doe\", \"fullName\":\"John Doe\", \"email\":\"john.doe@example.com\"}";
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.snagajob.com/easy-apply/adding-support-for-snagajobs-easy-apply.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
