Toggl Hire
Toggl Hire API lets you export candidate data for custom integrations or analytics.
Versioning
Breaking changes in the API are released as new minor versions of the API. The API version is specified in the URL, for example https://api.hire.toggl.com/api/v2.1
. The latest version of the API is always available as v2
. We recommend using an exact version of the API.
To view the documentation for a specific API version use on of the links below.
Authentication
All endpoints require an API key to be supplied in the request. API keys for each workspace in Toggl Hire can be generated on the integration settings page.
Once you have the API key, set the Authorization
header to the value Bearer [your-api-key]
, for example:
Authorization: Bearer 11ZU1ZOJ0PDOQPVEZ12PPZTPRR933L6VE25LM0R0BEP7961KY3JVDE8VJZY2U28
Errors
If a request fails, the API will return a 4xx or 5xx response with error details in the response body. Currently only the error.type
field is provided, which contains the type of the error that occurred. The type should not be shown to the user, but it is human-readable.
{
"error": {
"type": "NotFoundError"
}
}
Pagination
Some endpoints do not return all records, but only a limited amount. This amount is specified using the limit
parameter, which has a certain maximum value. To fetch more records than the maximum value, use the URL in the links.next
attribute in the response.
Toggl Hire API uses seek pagination, where each page is identified by the ID of the record from the previous page. For example, if an endpoint returns 3 records with IDs 100, 101 and 102 for the URL /example-endpoint?limit=3
, you can get the next 3 endpoints using the ID of the last record: /example-endpoint?limit=3&after_id=102
.
Job openings ¶
Job openings collection ¶
List all job openingsGET/openings
Example URI
Headers
Authorization: Bearer xyz
200
Headers
Content-Type: application/json
Body
{
"data": [
{
"id": "100",
"name": "Senior JavaScript Developer",
"slug": "JFHSAK2879FLKJE",
"created_at": "2020-02-10T10:00:00",
"published_at": "2020-02-10T10:00:00",
"closed_at": "2020-02-10T10:00:00"
}
]
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the job opening"
},
"name": {
"type": "string",
"description": "Name of the job opening"
},
"slug": {
"type": "string",
"description": "Public unique identifier for the job opening\n\nThe job opening link can be constructed by appending the slug to `https://apply.hire.toggl.com/`, for example `https://apply.hire.toggl.com/KLJFD9283FLKDJ`."
},
"created_at": {
"type": "string",
"description": "Date and time when the job opening was created"
},
"published_at": {
"type": [
"string",
"null"
],
"description": "Date and time when the job opening was published\n\nThis is usually the same as when the job opening was created, except for some older job openings."
},
"closed_at": {
"type": [
"string",
"null"
],
"description": "Date and time when the job opening was closed\n\nIf this value is not `null` the job opening is closed and candidates cannot take the test anymore"
}
}
}
}
}
}
Job opening ¶
Get a single job openingGET/openings/{id}
Example URI
- id
string
(required) Example: 100ID of the requested job opening
Headers
Authorization: Bearer xyz
200
Headers
Content-Type: application/json
Body
{
"id": "100",
"name": "Senior JavaScript Developer",
"slug": "JFHSAK2879FLKJE",
"created_at": "2020-02-10T10:00:00",
"published_at": "2020-02-10T10:00:00",
"closed_at": "2020-02-10T10:00:00"
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the job opening"
},
"name": {
"type": "string",
"description": "Name of the job opening"
},
"slug": {
"type": "string",
"description": "Public unique identifier for the job opening\n\nThe job opening link can be constructed by appending the slug to `https://apply.hire.toggl.com/`, for example `https://apply.hire.toggl.com/KLJFD9283FLKDJ`."
},
"created_at": {
"type": "string",
"description": "Date and time when the job opening was created"
},
"published_at": {
"type": [
"string",
"null"
],
"description": "Date and time when the job opening was published\n\nThis is usually the same as when the job opening was created, except for some older job openings."
},
"closed_at": {
"type": [
"string",
"null"
],
"description": "Date and time when the job opening was closed\n\nIf this value is not `null` the job opening is closed and candidates cannot take the test anymore"
}
}
}
Candidates ¶
Candidates collection ¶
Note that the candidates collection will return only candidates who have submitted the test and it will not return any demo candidates.
The parameters are combined using the AND
operator, meaning that the candidate must match every parameter to be included in the result.
List candidatesGET/candidates{?job_opening_id,category_id,tag_ids,hire_state,min_score,max_score,min_rating,max_rating,email,after_id,limit,order}
Example URI
- job_opening_id
string
(optional) Example: 100Returns candidates from the specified job opening
- category_id
string
(optional) Example: 200Returns candidates from the specified category
- tag_ids
string
(optional) Example: 300,301,302Returns candidates that have all of the specified tags
To specify multiple tags, separate the IDs with a comma, for example:
100,200,300
- hire_state
string
(optional) Example: possible-hireReturns candidates with the specified hire state
Choices:
possible-hire
rejected
- min_score
number
(optional) Example: 40Returns candidates with at least the specified score
- max_score
number
(optional) Example: 70Returns candidates with at most the specified score
- min_rating
number
(optional) Example: 1Returns candidates with at least the specified rating
Rating corresponds to the stars in the application, so 1 star = rating value
1
, 3 stars = rating value3
.- max_rating
number
(optional) Example: 3Returns candidates with at most the specified rating
string
(optional) Example: john@example.comReturns candidates with the specified email address
- after_id
string
(optional) Example: 200Used for pagination; returns candidates after the candidate with the specified ID
- limit
number
(optional) Default: 100 Example: 30Returns only at most the specified number of candidates
- order
string
(optional) Default: asc Example: ascSorts the candidates based on the
started_at
attribute in ascending or descending orderChoices:
asc
desc
Headers
Authorization: Bearer xyz
200
Headers
Content-Type: application/json
Body
{
"data": [
{
"id": "100",
"name": "Cord Briemer",
"email": "rosario84@real.com",
"profile_url": "https://github.com/debitis",
"contact_info": {
"full_name": "Cord Briemer",
"contact_email": "acarmona@duran-gomez.info",
"linkedin": "https://linkedin.com/in/debitis",
"phone": "+49(0)9859 103312",
"city": "Lake Justinville",
"country": "Gibraltar"
},
"points": 12,
"score": 85.714286,
"rating": 0,
"hire_state": "possible-hire",
"category_id": "100",
"job_opening_id": "100",
"utm_source": "facebook",
"utm_medium": "social_media",
"utm_campaign": "our_facebook_ad",
"referrer_url": "http://facebook.com",
"ip_address": "192.168.0.1",
"tests": [
{
"type": "quiz",
"started_at": "2019-03-10T02:39:32.59275",
"finished_at": "2019-03-10T02:53:29.05823",
"points": 12,
"score": 85.714286
}
]
}
],
"links": {
"next": "Hello, world!"
},
"total": 1
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the candidate"
},
"name": {
"type": "string",
"description": "Name of the candidate retrieved from their third party login provider\n\nNote that this can be an empty string, for example if the candidate has no name set in their GitHub profile."
},
"email": {
"type": "string",
"description": "Email of the candidate retrieved from their third party login provider"
},
"profile_url": {
"type": "string",
"description": "Profile URL retrieved from the candidate's third party login provider\n\nNote that the profile URL is available only if the candidate uses GitHub to log in."
},
"contact_info": {
"type": "object",
"properties": {
"full_name": {
"type": "string",
"description": "Candidate's full name"
},
"contact_email": {
"type": "string",
"description": "Candidate's preferred contact email address"
},
"linkedin": {
"type": "string",
"description": "Candidate's LinkedIn profile URL"
},
"phone": {
"type": "string",
"description": "Candidate's phone number"
},
"city": {
"type": "string",
"description": "Candidate's city"
},
"country": {
"type": "string",
"description": "Candidate's country"
}
},
"description": "Contact info submitted by the candidate after they have finished the test"
},
"points": {
"type": "number",
"description": "Total number of points that the candidate scored for all answers on their first test"
},
"score": {
"type": "number",
"description": "Percentage score calculated as `(actual points) / (maximum points)` on candidate's first test"
},
"rating": {
"type": "number",
"enum": [
0,
1,
2,
3
],
"description": "Candidate's star rating"
},
"hire_state": {
"type": "string",
"enum": [
"possible-hire",
"rejected",
"(empty string)"
],
"description": "Candidate's hire state"
},
"category_id": {
"type": [
"string",
"null"
],
"description": "ID of the candidate's category"
},
"job_opening_id": {
"type": "string",
"description": "ID of the candidate's job opening"
},
"utm_source": {
"type": "string",
"description": "The utm_source query param the candidate visited the test with"
},
"utm_medium": {
"type": "string",
"description": "The utm_medium query param the candidate visited the test with"
},
"utm_campaign": {
"type": "string",
"description": "The utm_campaign query param the candidate visited the test with"
},
"referrer_url": {
"type": "string",
"description": "The referer the candidate navigated to the test from"
},
"ip_address": {
"type": "string",
"description": "Candidate's IP address"
},
"tests": {
"type": "array",
"description": "Tests the candidate partticipated in"
}
}
}
},
"links": {
"type": "object",
"properties": {
"next": {
"type": "string",
"description": "URL that can be used to fetch the next page"
}
}
},
"total": {
"type": "number",
"description": "Total number of candidates matching the parameters"
}
}
}
Candidate ¶
Fetch a candidateGET/candidates/{id}
Example URI
- id
string
(required)ID of the requested candidate
Headers
Authorization: Bearer xyz
200
Headers
Content-Type: application/json
Body
{
"id": "100",
"name": "Cord Briemer",
"email": "rosario84@real.com",
"profile_url": "https://github.com/debitis",
"contact_info": {
"full_name": "Cord Briemer",
"contact_email": "acarmona@duran-gomez.info",
"linkedin": "https://linkedin.com/in/debitis",
"phone": "+49(0)9859 103312",
"city": "Lake Justinville",
"country": "Gibraltar"
},
"points": 3,
"score": 100,
"rating": 1,
"hire_state": "possible-hire",
"category_id": "100",
"job_opening_id": "100",
"tag_ids": [
"100",
"200",
"300"
],
"utm_source": "facebook",
"utm_medium": "social_media",
"utm_campaign": "our_facebook_ad",
"referrer_url": "http://facebook.com",
"ip_address": "192.168.0.1",
"tests": [
{
"type": "quiz",
"started_at": "2019-03-10T02:39:32.59275",
"finished_at": "2019-03-10T02:53:29.05823",
"points": 1,
"score": 100,
"questions": [
{
"id": "400",
"question_type": "single-choice",
"content": "Which one describes **you** better?",
"points": 3,
"options": [
{
"id": "500",
"content": "Done is better than perfect",
"correct": true
},
{
"id": "501",
"content": "I'm a perfectionist in everything I do",
"correct": false
}
]
},
{
"id": "401",
"question_type": "free-text",
"content": "What is your professional experience?",
"points": 0,
"options": []
}
],
"answers": [
{
"question_id": "400",
"text_answer": "",
"points": 3,
"chosen_option_ids": [
"500"
]
},
{
"question_id": "401",
"text_answer": "I am the best in the world at everything I do.",
"points": 0,
"chosen_option_ids": []
}
],
"skills": [
{
"skill": "Golang",
"score": 75.5
}
]
},
{
"type": "video",
"started_at": "2019-03-10T03:39:32.59275",
"finished_at": "2019-03-10T03:53:29.05823",
"points": 0,
"questions": [
{
"id": "702",
"skill": null,
"content": "What was the best thing that happened to you this week?",
"points": 1,
"options": []
}
],
"answers": [
{
"question_id": "702",
"text_answer": "",
"recording_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
"points": null,
"chosen_option_ids": []
}
],
"skills": []
}
]
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the candidate"
},
"name": {
"type": "string",
"description": "Name of the candidate retrieved from their third party login provider\n\nNote that this can be an empty string, for example if the candidate has no name set in their GitHub profile."
},
"email": {
"type": "string",
"description": "Email of the candidate retrieved from their third party login provider"
},
"profile_url": {
"type": "string",
"description": "Profile URL retrieved from the candidate's third party login provider\n\nNote that the profile URL is available only if the candidate uses GitHub to log in."
},
"contact_info": {
"type": "object",
"properties": {
"full_name": {
"type": "string",
"description": "Candidate's full name"
},
"contact_email": {
"type": "string",
"description": "Candidate's preferred contact email address"
},
"linkedin": {
"type": "string",
"description": "Candidate's LinkedIn profile URL"
},
"phone": {
"type": "string",
"description": "Candidate's phone number"
},
"city": {
"type": "string",
"description": "Candidate's city"
},
"country": {
"type": "string",
"description": "Candidate's country"
}
},
"description": "Contact info submitted by the candidate after they have finished the test"
},
"points": {
"type": "number",
"description": "Total number of points that the candidate scored for all answers on their first test"
},
"score": {
"type": "number",
"description": "Percentage score calculated as `(actual points) / (maximum points)` on candidate's first test"
},
"rating": {
"type": "number",
"enum": [
0,
1,
2,
3
],
"description": "Candidate's star rating"
},
"hire_state": {
"type": "string",
"enum": [
"possible-hire",
"rejected",
"(empty string)"
],
"description": "Candidate's hire state"
},
"category_id": {
"type": [
"string",
"null"
],
"description": "ID of the candidate's category"
},
"job_opening_id": {
"type": "string",
"description": "ID of the candidate's job opening"
},
"utm_source": {
"type": "string",
"description": "The utm_source query param the candidate visited the test with"
},
"utm_medium": {
"type": "string",
"description": "The utm_medium query param the candidate visited the test with"
},
"utm_campaign": {
"type": "string",
"description": "The utm_campaign query param the candidate visited the test with"
},
"referrer_url": {
"type": "string",
"description": "The referer the candidate navigated to the test from"
},
"ip_address": {
"type": "string",
"description": "Candidate's IP address"
},
"tests": {
"type": "array",
"description": "Tests the candidate partticipated in"
},
"tag_ids": {
"type": "array",
"description": "IDs of tags assigned to the candidate"
}
}
}
Categories ¶
Categories collection ¶
List all categoriesGET/categories{?job_opening_id}
Example URI
- job_opening_id
string
(optional)Returns only categories from the specified job opening
Headers
Authorization: Bearer xyz
200
Headers
Content-Type: application/json
Body
{
"data": [
{
"id": "100",
"name": "Interview",
"job_opening_id": "200"
}
]
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the category"
},
"name": {
"type": "string",
"description": "Name of the category"
},
"job_opening_id": {
"type": "string",
"description": "ID of the job opening the category belongs to"
}
}
}
}
}
}
Webhooks ¶
Webhook settings can be found on the integrations tab under workspace settings.
Overview
Webhooks serve as alerts to ensure synchronization between your systems and Toggl Hire with actions performed within Toggl Hire. However, it is important to note that webhooks themselves should not be considered actionable items.
Toggl Hire has the capability to send webhooks to any publicly accessible server. Whenever an event in Toggl Hire triggers a webhook (such as a candidate submitting their answers), Toggl Hire will make an attempt to deliver this notification to the specified endpoint(s) you have provided.
For Toggl Hire to confirm successful delivery of a notification, it must receive a timely response with a valid status code. In other words:
-
Your endpoint should be reachable through ports 80 (HTTP) or 443 (HTTPS) since Toggl Hire does not support other ports.
-
Your endpoint should respond within 5 seconds.
-
Your endpoint should respond with a 2XX status code (e.g., 200, 201, 204, etc.). Toggl Hire does not follow redirects or consider them as successful responses.
Automatic retries
In the event that Toggl Hire encounters an error response when sending a webhook to your specified URL, the system will automatically attempt to retry the delivery. After ten consecutive failed attempts, Toggl Hire will cease further delivery attempts for that particular notification.
Notifications are sent in the order they were created, and the interval between retries follows an approximate formula of 10 + x^4
seconds, where x represents the current number of failed attempts. As a result, the intervals between the initial retries will be relatively short, but will progressively increase exponentially as the number of retries rises.
Payload
The webhooks provide light weight payloads containing information about the type of event (e.g. updated, created, etc.), context regarding the object (e.g. candidate) and object identifiers that can be used to obtain the most up to date information via Toggl Hire API.
{
"id": "2000",
"object_type": "candidate",
"event_type": "test.finished",
"event_time": "2023-07-17T12:41:02.032859-06:00",
"workspace_id": "100"
}
Candidate notifications
Test finished
Sent when a candidate submits their answers.
{
"id": "2000",
"object_type": "candidate",
"event_type": "test.finished",
"event_time": "2023-07-17T12:41:02.032859-06:00",
"workspace_id": "100"
}
Coming soon
Additional notifications are coming soon. Help us make our webhooks better, contact customer support for requesting additional notification type.