Skip to main content

Receiving Application Data

Overview

To receive applications from the Talroo Apply system, you must specify a POST endpoint for each job within the postUrl in your XML Job Feed. Talroo will send POST requests to this endpoint using a JSON payload in the request body containing the application data.

Required POST endpoint Behavior

The POST endpoint must utilize HTTPS protocol and must return a 2XX status code for all successful applications received.

POST endpoint example in XML

<postUrl>
<![CDATA[http://www.example.com/appication?jobid=unique123456]]>
</postUrl>

Application Data

Talroo sends application data as a JSON within the body of the POST request send to the provided <postUrl>. The JSON will contain data for the job that was applied to, applicant data, and data for all Application Questions viewed by the applicant (hierarchical and conditional questions may not always be displayed). Optional questions viewed by applicant that are unanswered will contain a null answer value.

note

If a question is not seen by an applicant, it will not be included in the application data JSON sent by Talroo.

The fields included in this JSON are as follows:

  • id: Talroo delivery system event Id
  • type: The type of Talroo system event
  • createdAt: The UTC timestamp this event was created
  • data: JSON object containing the application data
    • data.id: Talroo Job Application Id
    • data.job: JSON object containing information on the specific job that was applied to
      • data.job.jobId: Talroo's internal job identifier
      • data.job.jobReference: Reference number used by Talroo - Can be differ from reference number supplied in job feed if title expansions are used
      • data.job.originalJobReference: Reference number supplied in job feed for this job
      • data.job.company: The job's company
      • data.job.title: The job's title
      • data.job.zipcode: The job's advertising zipcode
      • data.job.city: The job's advertising city
      • data.job.state: The job's advertising state abbreviation
      • data.job.sourceId: Talroo's internal job source identifier
    • data.tlrSid: Talroo Click ID. Same as the tlr_sid used in Click ID conversion tracking
    • data.applicant: JSON object containing information on the job applicant
      • data.applicant.firstName: Job applicant's first name
      • data.applicant.lastName: Job applicant's last name
      • data.applicant.phone: Job applicant's phone number
      • data.applicant.emailAddress: Job applicant's email address
      • data.applicant.address: Job applicant's address - Can be null if omitted by applicant
      • data.applicant.city: Job applicant's city
      • data.applicant.state: Job applicant's state
      • data.applicant.zipcode: Job applicant's zipcode
      • data.applicant.resume: JSON object containing job applicant's resume file, if provided
        • data.applicant.resume.fileName: Resume file name
        • data.applicant.resume.contentType: Resume file type
        • data.applicant.resume.contentSha256: Resume content Sha256
        • data.applicant.resume.data: Base64 encoding of resume file
    • data.completed: Will always be true
    • data.qualified: Whether or not this is a qualified application - only applies if Qualifying Questions are utilized and you are opted in to receive unqualified applications
    • data.createdAt: The UTC timestamp this Job Application was created - This is effectively when the job application was started by job applicant
    • data.campaignId: The corresponding jobCampaign.id of the Campaign the job applied to is assigned
    • data.segmentId: The corresponding jobCampaign.id of the Segment the job applied to is assigned - Can be null if segments are not used
    • data.redirectUrl: URL user was directed too after submitting application - Will be null if not applicable
    • data.tlrApplicationId: Talroo's Unique Application ID (should be used with the Disposition System)
    • data.applicationTime: The UTC timestamp this Job Application was completed and submitted by the job applicant
    • data.questionsAndAnswers: Array of JSON objects containing the additional question and their answers the job applicant provided with the Job Application
      • data.questionsAndAnswers[X].question: Corresponding question JSON
      • data.questionsAndAnswers[X].answer: String or array of answer(s) value supplied by the job applicant
    • data.qualifyingQuestionAnswers: Deprecated
    • data.analytics: JSON object with technical details of job applicant
      • data.analytics.userAgent: Job Applicant's userAgent

Example JSON body of POST request

{
"id": "0G8DF0QYD1ED4",
"initiator": "22shs9d39l300tc1j2nrs7h3pl",
"requestId": "04e0b188-b058-440d-86a5-bfaabdccee9f",
"correlationId": "1c33696c-e6d8-4a19-b421-a68131791e8b",
"type": "platform:JobApplication:completed:v2",
"data": {
"id": 1977758,
"job": {
"city": "Austin",
"jobId": 30604479565,
"state": "TX",
"title": "Noel's Job Level Apply Job Single Pagebreak",
"company": "Noel's Humble Giant Corporation",
"zipcode": 78756,
"sourceId": 12345,
"jobReference": "unique2",
"originalJobReference": "unique2"
},
"tlrSid": "9e212544-9a85-48w8-85e9-889wt9387c9c",
"applicant": {
"city": "Austin",
"phone": "5551112222",
"state": "TX",
"address": "6433 Champion Grandview Way Bldg 2, Ste 100",
"zipcode": "78750",
"lastName": "Doe",
"firstName": "John",
"emailAddress": "john.doe@examplee.com",
"resume": {
"fileName": "21.21.33.612359635.pdf",
"contentType": "application/octet-stream",
"contentSha256": "5ab9b544e43986e6c35de1fe7f744722c8b44faf08d2ec2a5885aa4e6a5bf42b",
"data": "JVBERi...."
}
},
"completed": true,
"qualified": true,
"createdAt": "2024-06-04T21:21:13Z",
"segmentId": null,
"campaignId": 72920,
"redirectUrl": null,
"tlrApplicationId": "55e3c166-b03f-11f0-837b-0e09a3d063d1",
"applicationTime": "2024-06-04T21:23:47Z",
"questionsAndAnswers": {
"questionsAndAnswers": [
{
"question": {
"id": "work_eligibility",
"type": "select",
"question": "Are you eligible to work in the United States?",
"options": [
{
"label": "No",
"value": "no",
"correct": null
},
{
"label": "Yes",
"value": "yes",
"correct": true
},
{
"label": "Yes, with sponsorship",
"value": "sponsorship",
"correct": true
}
],
"required": true
},
"answer": "yes"
},
{
"question": {
"id": "previous_company",
"type": "text",
"question": "What company did you work for previously?",
"required": true,
"limit": 100
},
"answer": "Previous Company Answer"
},
{
"question": {
"id": "work_environment",
"type": "textarea",
"question": "Describe your ideal work environment:"
},
"answer": "I'd probably do best in an environment that mostly reflects a luscious green grass field in need of a good mow."
},
{
"question": {
"id": "start_date_one",
"type": "date",
"question": "Start date",
"required": true
},
"answer": "2001-01-01"
},
{
"question": {
"id": "gpa",
"type": "text",
"question": "What was your GPA?",
"required": true,
"format": "decimal"
},
"answer": "3.8"
},
{
"question": {
"id": "has_rn_license",
"type": "hierarchical",
"question": "Do you have a Registered Nurse license?",
"options": [
{
"label": "No",
"value": "0",
"correct": null
},
{
"label": "Yes",
"value": "1",
"correct": null
}
],
"hierarchicalOptions": [
{
"id": "nursing_school",
"question": "Are you currently attending nursing school?",
"options": [
{
"label": "No",
"value": "0",
"correct": null
},
{
"label": "Yes",
"value": "1",
"correct": null
}
],
"required": null,
"condition": {
"id": "has_rn_license",
"value": "0"
}
},
{
"id": "nursing_school_graduation",
"question": "When are you expected to graduate?",
"options": [
{
"label": "Within the next six months",
"value": "0",
"correct": null
},
{
"label": "Within the next year",
"value": "1",
"correct": null
},
{
"label": "More than a year from now",
"value": "2",
"correct": null
}
],
"required": true,
"condition": {
"id": "nursing_school",
"value": "1"
}
},
{
"id": "rn_license_time",
"question": "Have you had your RN license for more than six months?",
"options": [
{
"label": "No",
"value": "no",
"correct": null
},
{
"label": "Yes",
"value": "yes",
"correct": null
}
],
"required": null,
"condition": {
"id": "has_rn_license",
"value": "1"
}
}
],
"required": true
},
"answer": {
"has_rn_license": "1",
"rn_license_time": "yes"
}
},
{
"question": {
"id": "currently_work_here",
"type": "select",
"question": "I currently work here",
"options": [
{
"label": "No",
"value": "0",
"correct": null
},
{
"label": "Yes",
"value": "1",
"correct": null
}
],
"required": false
},
"answer": "1"
},
{
"question": {
"id": "school_years",
"type": "text",
"question": "How many years of nursing school did you attend?",
"format": "numeric_text"
},
"answer": "5"
},
{
"question": {
"id": "availability",
"type": "multiselect",
"question": "Please select all shifts you are available to work:",
"options": [
{
"label": "Morning",
"value": "0",
"correct": null
},
{
"label": "Afternoon",
"value": "1",
"correct": null
},
{
"label": "Evening",
"value": "2",
"correct": null
},
{
"label": "Night",
"value": "3",
"correct": null
}
]
},
"answer": [
"0",
"1",
"3"
]
},
{
"question": {
"id": "recent_example_work",
"type": "file",
"question": "Please attach a cover letter.",
"required": false
},
"answer": {
"fileName": "21.21.33.612359987.pdf",
"contentType": "application/octet-stream",
"contentSha256": "5ab9b544e43446e6c35de1fe7f744722c8b44faf08d2ec2a5885aa4e6a5bf42b",
"data": "JVBERi...."
}
},
{
"question": {
"id": "desired_hours",
"type": "text",
"question": "How many hours would you like to work a week?",
"required": false,
"format": "integer",
"min": "0",
"max": "80"
},
"answer": "40"
}
]
},
"qualifyingQuestionAnswers": [],
"analytics": {
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36"
}
},
"createdAt": "2024-06-04T21:23:47Z"
}

Pulling Job Application Data via API

In addition to receiving application data via POST requests, you can manually retrieve Job Application data using the Talroo Platform API. This allows you to pull both complete and incomplete applications on-demand.

Prerequisites

To access the Job Applications endpoint, you'll need to authenticate using the Talroo Platform API, which requires creating an App Client. See the Authentication guide for detailed instructions on setting up your App Client and generating access tokens.

Using the Job Applications Endpoint

The Job Applications endpoint allows you to retrieve application data programmatically:

You can query this endpoint to retrieve job applications with various filters, including filtering by completion status, date ranges, and other criteria. Refer to the Platform API documentation for complete details on available query parameters and response formats.

Retrieving Incomplete Applications

To support applicant follow-up efforts, the Job Applications endpoint allows you to retrieve incomplete applications. These are applications where job seekers started but did not complete the application process.

Key differences for incomplete applications:

  • The data.completed field will be false
  • Some applicant information may be partially filled or missing
  • The data.questionsAndAnswers array may be empty or contain only partially answered questions

By filtering for incomplete applications, you can identify applicants who showed interest but didn't finish applying, enabling you to:

  • Send follow-up reminders to encourage application completion
  • Re-engage interested candidates

Security

Talroo X-Talroo-Signature

The POST request Talroo Apply sends to your postUrl will contain the HTTP header, X-Talroo-Signature you can use to verify the authenticity of the POST. This header contains the timestamp used to create the signature, and the SHA256 HMAC signature created using the JSON payload and a secret set by Talroo, or yourself, during the integration onboarding process.

Example Signature

x-talroo-signature:  
t=1685045143,
v1=7d0sd2b25451b9b21bf9dc27b401c7671accf8cc8000c87b1c45b59991b7f9d9
info

In_ the x-talroo-signature example above, newlines have been added for clarity, but a real x-talroo-signature header will be a single line.

To confirm authenticity, you can use the JSON within the POST request body and the secret to generate a signature used to compare with the X-Talroo-Signature.

Generating the Signature

See Java and Python Code snippets below for an example on how to generate the signature for comparison.

Java Code Example

import lombok.Builder; 
import lombok.Data;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.Objects;

/**
* Generates and verifies Webhook signatures using HMAC SHA256.
* The formula for the signature is:
* <code>
* t=<unix time>,v1=hex(hmacsha256(<unix time>.<body>))
* </code>
*/
public class WebhookSignatureGenerator {
static final String ALGORITHM_V1 = "HmacSHA256";

@SneakyThrows({NoSuchAlgorithmException.class, InvalidKeyException.class})
private String generateSignatureV1(String secret, long unixTime, String payload) {
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), ALGORITHM_V1);
Mac mac = Mac.getInstance(ALGORITHM_V1);
mac.init(secretKey);
String signatureInput = unixTime + "." + payload.trim();
byte[] signatureBytes = mac.doFinal(signatureInput.getBytes(StandardCharsets.UTF_8));
return Hex.encodeHexString(signatureBytes);
}

public WebhookSignature generate(SignatureOptions options) {
long unixTime = options.getT()
.getEpochSecond();
return WebhookSignature.builder()
.t(unixTime)
.v1(generateSignatureV1(options.getSecret(), unixTime, options.getPayload()))
.build();
}

public boolean verify(SignatureVerifyOptions options) {
String oldSignature = options.getSignature()
.getV1();
String newSignature = generateSignatureV1(options.getSecret(),
options.getSignature().getT(),
options.getPayload());
return Objects.equals(oldSignature, newSignature);
}

@Data
@Builder
public static class SignatureOptions {
private final String secret;
@Builder.Default
private final Instant t = Instant.now();
private final String payload;
}

@Data
@Builder
public static class SignatureVerifyOptions {
private final WebhookSignature signature;
private final String secret;
private final String payload;
}
}

Python Code Example

import hmac
import hashlib
import time
from typing import Dict

def generate_signature(secret: str, payload: str, timestamp: int = None) -> Dict[str, str]:
"""
Generate a webhook signature using HMAC SHA256.

Args:
secret (str): The secret key used for HMAC.
payload (str): The payload to sign.
timestamp (int, optional): Unix time. Defaults to the current time.
Returns:
dict: A dictionary containing the timestamp and signature.
"""
if timestamp is None:
timestamp = int(time.time())

message = f"{timestamp}.{payload}".encode('utf-8')
secret = secret.encode('utf-8')

signature = hmac.new(secret, message, hashlib.sha256).hexdigest()

return {
"t": timestamp,
"v1": signature
}

def verify_signature(secret: str, payload: str, signature_data: Dict[str, str]) -> bool:
"""
Verify a webhook signature.

Args:
secret (str): The secret key used for HMAC.
payload (str): The payload to verify.
signature_data (dict): The signature data containing the timestamp and signature.

Returns:
bool: True if the signature is valid, False otherwise.
"""
timestamp = signature_data["t"]
expected_signature = signature_data["v1"]

generated_signature = generate_signature(secret, payload, timestamp)

return hmac.compare_digest(expected_signature, generated_signature["v1"])

# Example usage:
if __name__ == "__main__":
secret_key = "secret"
payload_data = """{"id":"EXAMPLEID", "name":"TEST JSON PAYLOAD"}"""
signature = {'t': 1718049653, 'v1': '2c1f4ad009adbdbf1c440d1362fbb825b2a3250b4f3526d62da8bb940d703f31'}

# Verify signature
is_valid = verify_signature(secret_key, payload_data, signature)
print(f"Signature is valid: {is_valid}")