You can get candidate reports in bulk for a particular test using following API endpoint:
https://api.hackerearth.com/partner/hackerearth/events/candidates/bulk-reports/
The client authentication is done using your unique client_id and client_secret.
You can refer to your Dashboard settings, for client_id and client_secret under API details.
Type: String
Description: client_id is a 67 character random key that serves as an identification for a particular client and must be provided when communicating with the API as a parameter to the API endpoint.
Example: d8a20ae8e475209er4b1faa72ede88a174423cc2029c.api.hackerearth.com
Type: String
Description: client_secret is a 40 character random key that serves as an identification for a particular client and must be provided when communicating with the API as a parameter to the API endpoint.
Example: 2b0ff29f4f8751487540604cdab5611e6135f41c
Candidate reports are accessible only for published test.
client_id, client_secret and test_id are the required parameters for making request to this API endpoint. emails, filters, page_number and page_size are optional parameters which are explained below.
All the requests to the API must be made using POST request method.
client_id and client_secret are explained above.
Type: Integer
Description: test_id is a unique integer for your test. Refer to this article for a better understanding. In this article, Recruiter API ID is the test_id.
Example: 5841
Type: List
Description: emails is a list/array which contains candidate emails. If this field is provided, then candidate reports corresponding to only these candidates are returned, else, candidate reports of all the candidates are returned who have taken the test.
Example: ["foo@bar.com", "bob@alice.com", "hacker@hackerearth.com"]
Type: Dictionary
Description: This field can accept two type of filters start_datetime and finish_datetime.
start_datetime and finish_datetime are date-range fields that accept two attributes: min and max, that should be in ISO8601 date format. A date-range field should have at-least one of the two attributes.
Combination of above filters is supported.
Example:
{
"start_datetime":
{
"min": "2019-07-31T21:25:02+05:30",
"max": "2019-08-02T23:25:02+05:30"
},
"finish_datetime":
{
"min": "2019-07-31T22:25:02+05:30",
"max": "2019-08-02T23:25:02+05:30"
}
}
Type: Integer
Description: page_number is a valid page number for paginated reports. If this field is not provided, then by default page_number will be 1
Type: Integer
Description: page_size is a valid page size for paginated reports. If this field is not provided, then by default page_size will be 10. The maximum permitted value for page_size is 20.
Sample request using python
#!/usr/bin/env python
import json
import requests
CLIENT_ID = "d8a20ae8e475209e0eb1faa72ede88a174423cc2029c.api.hackerearth.com"
CLIENT_SECRET = "2b0ff29f4f8751487450604cdab5611e6135f41c"
TEST_ID = 53
EMAILS = ["sample@gmail.com", "alice@bob.com", "example@gmail.com", "dummy@gmail.com"]
FILTERS = {
"start_datetime":
{
"min": "2018-08-01T21:25:02+05:30",
"max": "2019-08-21T23:25:02+05:30"
},
"finish_datetime":
{
"min": "2018-08-01T22:25:02+05:30",
"max": "2019-08-21T23:25:02+05:30"
}
}
PAGE_NUMBER = 1
PAGE_SIZE = 5
payload = {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'test_id': TEST_ID,
'emails': EMAILS,
'filters': FILTERS,
'page_number': PAGE_NUMBER,
'page_size': PAGE_SIZE
}
r = requests.post("https://api.hackerearth.com/partner/hackerearth/events/candidates/bulk-reports/", data=json.dumps(payload))
print r.json()
Using cURL
curl --data '{
"client_id": "d8a20ae8e475209e0eb1faa72ede88a174423cc2029c.api.hackerearth.com",
"client_secret": "2b0ff29f4f8751487450604cdab5611e6135f41c",
"test_id": 53,
"emails": ["sample@gmail.com", "alice@bob.com", "example@gmail.com", "dummy@gmail.com"],
"filters": {
"start_datetime":
{
"min": "2018-08-01T21:25:02+05:30",
"max": "2019-08-21T23:25:02+05:30"
},
"finish_datetime":
{
"min": "2018-08-01T22:25:02+05:30",
"max": "2019-08-21T23:25:02+05:30"
}
},
"page_number": 1,
"page_size": 5
}' https://api.hackerearth.com/partner/hackerearth/events/candidates/bulk-reports/
Response returned will be in JSON format.
Sample response
{
"mcode": "success",
"message": "success"
"has_more": false,
"ecode": [
"NOTINVITED",
"NOTPARTICIPATED"
],
"emessage": [
"Candidate was never invited to this test.",
"Candidate was invited but he/she did not participate in this test."
],
"candidate_reports": {
"sample@gmail.com": {
"phone_number": null,
"full_report_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidates-report/c8001a2587a74c7cb80c552a92b009b9/5f2445dd4b1c7d08ef3c0307dc4ce90b/",
"anon_report_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidates-report/<hash1>/hash<2>/", // This feature is subjected to subscription.
"candidate_assessment_report_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidate-performance-report/c8001a2587a74c7cb80c552a92b009b9/66240bea5fc24e5baff57a6f9c44350f/",
"full_report_pdf": "https://he-pdf.s3.amazonaws.com/reports/id-test_id-date.pdf",
"anon_report_pdf_url": "https://he-pdf.s3.amazonaws.com/reports/id-test_id-date-anonymous.pdf",
"start_datetime": "2019-08-05T10:11:46-05:51",
"name": "sampleuser65",
"institute": "IIT Delhi",
"time_taken": "0:48:24",
"problem_type_scores": {
"Programming": 58.0,
"Multiple Choice Questions": 2.0
},
"section_scores": {
"Programming": {
"PSection1": 20.0,
"PSection2": 38.0
},
"Multiple Choice Questions": {
"MSection1": 2.0
}
},
"score": 60.0,
"status": "active",
"candidate_id": "dedewd",
"graduation_year": "2023",
"finish_datetime": "2019-08-05T10:12:10-05:51",
"percentage": 43,
"email": "sample@gmail.com",
"questions_attempted": 3,
"skill_scores": {
"Skill1": "45.0%",
"Skill2": "100.0%",
"Skill3": "75.0%"
},
"skill_scores_averages": {
"Skill1": "65.0%",
"Skill2": "100.0%",
"Skill3": "66.7%"
},
// This field is subjected to subscription.
"proctoring_information": {
"snapshots": {
"total_count": 30,
"discrepancies_count": 8,
"view_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidates-report/6c6512bdf2bd4cc1b17bb08439643fa8?show=view-snapshots",
"discrepancy_counts": {
"mobile_present": 2,
"multiple_persons": 2,
"wearing_earphones": 0,
"different_person": 0,
"no_person": 1,
"candidate_looking_away": 3,
"face_partially_hidden": 0
},
"candidate_reference_snapshot": "https://s3.ap-southeast-1.amazonaws.com/media.hackerearth.com/media/hackathon/test-draft-7-136/images/22199832/a102ab47c8374afa-1727675251-webcam.jpg"
}
},
"cutoff_qualified":"No"
}
},
"cutoff_qualified":"Yes"
},
"example@gmail.com": {
"phone_number": null,
"full_report_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidates-report/c8001a2587a74c7cb80c552a92b009b9/5f2445dd4b1c7d08ef3c0307dc4ce90b/",
"anon_report_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidates-report/<hash1>/hash<2>/", // This feature is subjected to subscription.
"candidate_assessment_report_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidate-performance-report/c8001a2587a74c7cb80c552a92b009b9/66240bea5fc24e5baff57a6f9c44350f/",
"full_report_pdf": "https://he-pdf.s3.amazonaws.com/reports/id-test_id-date.pdf",
"anon_report_pdf_url": "https://he-pdf.s3.amazonaws.com/reports/id-test_id-date-anonymous.pdf",
"start_datetime": "2019-08-05T10:11:46-05:51",
"name": "exampleuser65",
"institute": "IIT Delhi",
"time_taken": "0:23:48",
"problem_type_scores": {
"Programming": 51.0,
"Multiple Choice Questions": 2.0
},
"section_scores": {
"Programming": {
"PSection1": 20.0,
"PSection2": 31.0
},
"Multiple Choice Questions": {
"MSection1": 2.0
}
},
"custom_details": {
"Stream/Branch": "CSE",
"Degree": "B.Tech/B.E.",
"Resume": "http://he-s3.s3.amazonaws.com/hackathon/am-ex-challenge/misc/a0a11516cb-kforJobFinal.pdf",
"CGPA": "6.5",
"College": "Other College",
"Graduation Year": "Other"
},
"score": 53.0,
"status": "active",
"candidate_id": "dedewd",
"graduation_year": "2023",
"finish_datetime": "2019-08-05T10:12:10-05:51",
"percentage": 39,
"email": "example@gmail.com",
"questions_attempted": 3
"skill_scores": {
"Skill1": "34.2%",
"Skill2": "90.0%",
"Skill3": "85.0%"
},
"skill_scores_averages": {
"Skill1": "65.0%",
"Skill2": "100.0%",
"Skill3": "66.7%"
},
// This field is subjected to subscription.
"proctoring_information": {
"snapshots": {
"total_count": 19,
"discrepancies_count": 9,
"view_url": "https://www.hackerearth.com/recruiter/test-draft-7-136/candidates-report/6c6512bdf2bd4cc1b17bb08439643fa8?show=view-snapshots",
"discrepancy_counts": {
"mobile_present": 2,
"multiple_persons": 3,
"wearing_earphones": 0,
"different_person": 0,
"no_person": 0,
"candidate_looking_away": 4,
"face_partially_hidden": 0
},
"candidate_reference_snapshot": "https://s3.ap-southeast-1.amazonaws.com/media.hackerearth.com/media/hackathon/test-draft-7-136/images/22199832/a102ab47c8374afa-1727675251-webcam.jpg"
}
},
"cutoff_qualified":"No"
}
},
"candidate_reports_errors": {
"alice@bob.com": {
"emessage": "Candidate was never invited to this test.",
"ecode": "NOTINVITED"
},
"dummy@gmail.com": {
"emessage": "Candidate was invited but he/she did not participate in this test.",
"ecode": "NOTPARTICIPATED"
},
},
}
Type : String
Description: Message code abbreviated as mcode.
Type: String
Description: A message for user regarding the success of request.
message and mcode are related to each other according to the following table:
mcode | message |
---|---|
SUCCESS | Request successful |
FAILED | Request failed |
Type: List
Description: Error codes abbreviated as ecode.
Type: List
Description: A message explaining the error occurred during request processing.
emessage and ecode are related to each other according to the following table:
ecode | emessage |
---|---|
AUTHFAILED | Authentication Failed |
ARGMISSING | Request argument missing |
BADDATA | Invalid request data. |
TESTNOTFOUND | Test not found |
TESTNOTPUBLISHED | Test is not published. |
INVALIDEMAIL | Invalid email(s) exist. |
CANDIDATENOTFOUND | Candidate not found |
NOTINVITED | Candidate was never invited to this test. |
NOTPARTICIPATED | Candidate was invited but he/she did not participate in this test. |
NOREPORT | No report exist. |
LIMITEXCEEDED | The limit of the API requests has been reached. Contact support@hackerearth.com. |
ACCESSERROR | You are not authorized to access this feature. Please contact support@hackerearth.com. |
PAGINATIONBADDATA | Invalid pagination request data. |
Type: Dictionary (JSON)
Description: This JSON will contain candidate emails mapped to candidate details i.e. name, phone_number, status, start_datetime, finish_datetime, time_taken, institute, full_report_url, candidate_assessment_report_url, score, questions_attempted, graduation_year, questions_attempted, percentage, email, candidate_id, problem_type_scores (map of question type section and candidate's total score in that section), custom_details (map of Custom details fields and their values filled by the candidate), skill_scores, skill_scores_averages and proctoring_information (This field is subjected to subscription).
cutoff_qualified will have value "Yes" if candidate qulifies cutoff if not "No". if cutoff score for event is not set then value will be "NA".
Candidate's personal details like phone_number, institute, graduation_year and candidate_id will be set in response, if these fields were marked in Candidate Settings under Test Settings section and candidate has filled these details, otherwise, the value of these will be null
These candidate report details are sorted in descending order of candidate's test finish time.
status can have ['online', 'active', 'offered', 'archive'] values
Status | Description |
---|---|
online | Candidate is currently taking the test |
active | Candidate has finished the test and his result's review is pending |
offered | Candidate has been shortlisted |
archive | Candidate has been archived |
Note: anon_report_url i.e. Anonymous report url will be provided only if your company has subscribed to the anonymous reports feature.
Type: Dictionary (JSON)
Description: This JSON will contain candidate emails mapped to error objects (containing ecode and emessage), depicting the errors due to which no report is available for the corresponding emails.
Type: Boolean value (True/False)
Description: The value of this field indicates that whether next page exists or not. If the value of has_more is false, then the current page is the last page in paginated reports
If the client_id or client_secret attribute is incorrect, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"AUTHFAILED"
],
"emessage": [
"Authentication Failed"
],
"mcode": "FAILED"
}
If the mandatory POST arguments are not provided, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"ARGMISSING"
],
"emessage": [
"Request argument missing: 'test_id'"
],
"mcode": "FAILED"
}
If the provided data is invalid, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"BADDATA"
],
"emessage": [
"Invalid request data."
],
"mcode": "FAILED"
}
If the provided pagination data is invalid, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"PAGINATIONBADDATA"
],
"emessage": [
"Invalid pagination request data."
],
"mcode": "FAILED"
}
If wrong test_id is provided or the test has already been deleted, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"TESTNOTFOUND"
],
"emessage": [
"Test not found"
],
"mcode": "FAILED"
}
If a test is not published, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"TESTNOTPUBLISHED"
],
"emessage": [
"Test is not published."
],
"mcode": "FAILED"
}
If a user is not authorized to access the test, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"ACCESSERROR"
],
"emessage": [
"You are not authorized to access this feature. Please contact support@hackerearth.com."
],
"mcode": "FAILED"
}
If the limit of API requests (15000 requests) is reached, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"LIMITEXCEEDED"
],
"emessage": [
"The limit of the API requests has been reached. Contact support@hackerearth.com."
],
"mcode": "FAILED"
}
If the rate (60 per min or 10000 per day) at which API requests are made by a specific user is reached, then the JSON response that is returned is as follows:
{
"message": "Request failed",
"ecode": [
"RATELIMITEXCEEDED"
],
"emessage": [
"The rate at which the API requests are made has reached. Please try again after some time."
],
"mcode": "FAILED"
}
If any other issue occurred do reach us out at api@hackerearth.com