Integrate Hireflix with your ATS/system through our API
Our GraphQL API is open and allows you to do everything. You can build an integration as deep or as quick as needed. The GraphQL API self-describes and is very easy to understand.
API Information
To see all the methods of our API, load https://api.hireflix.com in your browser. This will open a GraphQL Playground, where you can discover the different endpoints available and their documentation. The Playground will open 3 tabs, each describing our APIs and what they do, and how to authenticate them.
https://api.hireflix.com/me - This is the most important endpoint the one you will use 99% of times: This API contains authenticated queries and mutations that deal with company, position interviews, candidates... To authenticate requests you can either include a previously generated Hireflix API key in a header named [X-API-KEY], or include a header with the auto generated user JWT as a bearer token. You can use this endpopint to invite candidates to interviews, to fetch information about interview status, positions, to create shareable links and pretty much everything you need as if you were "using" Hireflix as a company. |
https://api.hireflix.com/ - This API contains non authenticated queries and mutations that deal with user registration, invitation and login as well as information about Hireflix subscrition plans |
https://api.hireflix.com/interview - Used to utilize Hireflix from the point of view of the candidate (to answer an interview for instance) [This is public-facing so GraphQLBin can instrospect it without authentication] |
Q0.1 Steps to access the /me API (needs API key):
- Register for free in hireflix.com. Once logged into your Hireflix account, create an API Key https://admin.hireflix.com/en/my-account/api-keys
- The go back to the playground (https://api.hireflix.com/) and go to the Administration API /me tab. At the bottom of the page you will see it says "HTTP Headers". Click on it, and then paste {"x-api-key":"here-goes-the-api-key"} on that section, substituting the "here-goes-the-api-key" string with the API key you created in Hireflix:
{"x-api-key":"here-goes-the-api-key"}
- If the API Key has been introduced correctly, the GraphQL documentation should appear like on the right hand side when you click on "Docs" like below
Q0.2 How do I send a GraphQL Request programmatically to our API?
Regardless of the programming language you use, in order to make a GraphQL Request to our API, you have to issue an HTTP POST request with a JSON payload to the endpoint (for example https://api.hireflix.com/me)
Here you can find useful information on how to do this
The content of the JSON payload must be the following:
{
"query": “the GraphQL query or mutation goes here as an inlined string"
}
#As an example see below a mutation to invite a candidate "Daniela Smith" with email "daniela@hireflix.com" to the interview with interview ID (623c66b61df8a64c6648f702a). First as you would put it on the playground, and second, as the inline string which is the payload you send:
mutation {
Position(id: "623c66b61df8a64c6648f702a") {
invite(candidate: { name: "Daniela", email: "daniela@hireflix.com" }) {
id
url {
public
short
}
}
}
}
#and here the actual payload that needs to be sent:
{
"query": "mutation {\n Position(id: \"623c66b61df8a64c6648f702a\") {\n invite(candidate: { name: \"Daniela\", email: \"daniela@hireflix.com\" }) {\n id\n url {\n public\n short\n }\n }\n }\n}"
}
Q0.3 How can I convert my query from the playground format, to the one line format?
Just go to jsonblob.com and clicn CLEAR to clear the view. Then on the left box put the below:
{
"query": ""
}
Then on the right you will see there's a section that appears that says "Value" as below.
Then just paste your code where it says value, and you will see it converts it to the right format on the left box.
FAQS
Q1: I want to integrate Hireflix on my ATS so that invites can be triggered from my ATS and the completed interview is also shown on my ATS. What are the steps I need to follow?
This API docs you are looking at has all the information you need to make that happen. Please check it carefully since we explain here how to connect to our API, how to query it, what are the best ways to approach an integration, and even we share common queries and mutations used to make it happen.
Q2: How do usual integrations work? What is needed? 😊🙏
Step 1: your user will trigger invitations to the Hireflix interview from your ATS/system
- This is usually done by selecting the candidate/s then clicking "Send Assessment" then a popup appears where the user can select which interview to send to those candidates. The list displays all open interviews (we call them positions) in Hireflix which you can fetch by calling our API. You then click send and that's when you call our API to trigger the interview and invites.
- An alternative is to automatically trigger the invite when a candidate in a job Y is moved to a stage X. For this method you need to first have a way to assign a particular interview to a particular stage in that particular job, so that when candidates are put on that stage in that job, then the API call happens to trigger the interview/invite. This approach allows for more automation but is usually more complex to implement unless your ATS/system supports this type of flow already.
Step 2: Your user can track the status pending/completed from your ATS/system (This is usually done with automated status updates, tags or trigger/progression stages. It is essential that as a user I can easily see on a list who I have invited, who not etc.)
Step 3: Retrieving the interview response on your ATS. once the candidate has completed their interview you can then send a link back to your ATS/system with the full recorded interview so that it is copied on your candidate's profile. Your user will then be able to click the link and watch the interview without the need of logging anywhere. Instead of a link, you could even show the actual videos on your platform if you want to. It takes more work but it is also possible.
Q3: How do I send/invite a candidate to an interview?
Using the API, you can invite a candidate to a Hireflix Interview using the "Position => invite" mutation (Which you will send to the https://api.hireflix.com/me endpoint)
In our API the concept of "Position" is a set of interview questions. For instance below you have two positions, the position Analyst, and the position New Business Sales Rep. Each one may have different questions, settings, branding etc.
The concept "Interview" however, relates to specific candidates. An interview is created once someone is invited to an interview, and it contains the candidate info and the interview answers once the interview is completed. For example, below you can that the analyst position has 1 interview inside, and it is a completed interview. The New Business Sales Rep position has 5 interviews inside (4 are pending to be answered, one has been answered)
The returning payload of the "Position => invite" mutation will give you the URL ("public") that you can share with the candidate so that she can take her interview. You also have another URL called the "short URL" which is exactly the same but abbreviated in case you need to send it through SMS.
mutation {
Position(id: "623c66b61df8a64c6648f702") {
invite(candidate: { name: "Daniel", email: "daniel@hireflix.com" }) {
id
url {
public
short
}
}
}
}
#The returned payload is something like this:
{
"data": {
"Position": {
"invite": {
"id": "6245f73243204affdfe27774",
"url": {
"public": "https://app.hireflix.com/_mpmxxxxxk",
"short": "hflx.io/c/_mpmIW5k"
}
}
}
}
}
Q4: Once an interview is completed by a candidate, how do I send back a link with the interview response to my ATS/system? I can't find the URL in the wehbook payload!
The link you are refering to is called a "shareable link" (in our API it is called externalLink). It needs to be created for each interview using the "share" mutation.
mutation {
Interview(id:"your-interview-id") {
share(durationInDays: 100) { #Sets for how many days the link will be valid
externalLink {
url #This is the URL of the newly created Shareable link. Prompt this URL to your users on your system so they can easily watch an interview without having to log in into hireflix or anything.
}
}
}
}
#And this below is an example of the payload you will receive
{
"data": {
"Interview": {
"share": {
"externalLink": {
"url": "https://shared.hireflix.com/interview/64790100-17c1-4eee-b016-b366d2abcb18"
}
}
}
}
}
(Preferred approach) Generate a moderately long lived link dynamically every time someone in your ATS/system clicks on the "View Interview" button. This is safe because the links will eventually expire, but it is also user friendly enough because if you wanna share the candidate response with someone by sharing the link, you will be able to do so for some days without any issues.
Generate a moderately long lived link once, and also provide the admin link which never expires: Some platforms that can't change the link dynamically what they do is they paste on the candidate profile both the shareable link that expires in 75 days for easy access without login... and ALSO show the admin link which never expires but does require the user to be logged in in Hireflix to view the interview.
We do not suggest creating an extremely long lasting link... because it could pose a privacy risk if it gets leaked.
Q5: Can there be more than one interview per position? It seems like that's possible but I can't figure how to create that setup in the Hireflix UI
You are confusing the terms 😊🙏 A position is actually the set of questions the employer is asking and its configurations. An interview is actually each individual object that represents a candidate being invited to and taking the interview/questions for the position. Hence you can have for instance the position "Sales Manager" and then create N invitations for N candidates to that position yes.
In order to invite a candidate you use the position. In GraphQL there is a mutation called "invite" under the "Position" object (Position => invite) as explained previously.
Q6: For webhooks, do you have documentation somewhere that outlines how webhook payloads back to the ATS/system (to notify us about interview events) works?
Yes, I will put some examples below, although you can do it yourself > Go to admin.hireflix.com => Account => Webhooks, create a webhook with all the events available (see picture below) and as the URL, then go to webhook.site, create a temporary URL and set it on Hireflix as the URL where the wehbook will send the information. Save the webhook and then create an interview, complete it, move it between funnels using our frontend, and finally delete it. This way when you go back to webhook.site you will see the payload of each webhook.
If you want to validate if a webhook comes from Hireflix, I have put together documentation here on how to do so.
- interview.finish > triggers as soon as an interview is completed by a candidate
- interview.status-change > triggers as soon as the status of the interview changes, this could be because an interview has been completed, or it has been moved to Preselected or Discarded
- interview.create > triggers when a candidate is invited to an interview
- interview.delete > triggers when an interview is deleted
- interview.score-updated > triggers when the global score of a candidate is updated (Commenting on the candidate doesn't actually trigger this)
EXAMPLES
#THIS IS AN EXAMPLE OF THE INTERVIEW.FINISH RESPONSE. THIS EVENT TRIGGERS ONCE AN INTERVIEW IS FINALIZED
{
"event": "interview.finish",
"data": {
"id": "643e972db7d39e63cf468844", #this is the ID of the interview
"position": {
"id": "63d00b73df403de202d97e73", #this is the ID of the position
"name": "Graduate Program NYU"
},
"externalId": "eyJwYXJ0bmVySWQiOiI4YzRkZGY3NC0xZGI0LTRkNzktYTBmOC0xZWUzYWE3MzRsdLCJvcmdhbml6YXRpb25JZCI6IjY4MTEyYTMzLTViMGEtNDc0Zi05NTY5LTUxZGJiMWUwZTA4YiIsInVuaXF1ZUlkIjoiMjU5NTU1ZTItOWNmZi00OGRjLWJjODQtYTFlZDA5NTE0ZjIxIn0=",
"status": "completed",
"hash": "TgTZ88Fe",
"createdAt": 1681823533373,
"candidate": {
"name": "Wayne Knight",
"email": "wayne.knight@example.com",
"phone": null
},
"score": {
"value": null
},
"completed": 1683705149534,
"deleted": null,
"archived": null,
"finalist": null,
"answered": true,
"thumbnail": "https://media.hireflix.com/5f3245ab1008ea4e503b49ff/answer/643e972db7d39e6a21468847/00001-thumbnail.png?Expires=1683705234384&Key-Pair-Id=APKAWC67OMKLN2YILG76&Signature=OoT4Mdi9TaFufnHylZYcxDyqR-ezzGuEt~C1XQzBSxj4Y2e-i-B-WnnzQb3jjnGdrnyNLvs7Pit-76M44KL~XKJe4CaZfy0HvbTGmMOVw6adESuQD5qJ5nucypd7tiisdggyB0Q6YyfYTUL179M5C3cxPdFcYOblSQzK-3d3YQorp~h4nU1zhz9yt5S7IjV1zDYqIVJFy3kThs596LiSD7Vx20CFi7is1NUFofI0Hp78onfbnqedIsEd8rLm4NdsFh0BcFqOHzym1qi1fsctwnRkA2iOAcBZrww3ZMkyhOIDGPk9NP1-1igvERCzYgvETJuj2HYZq7YDasVkxG5tA__",
"url": {
"public": "https://app.hireflix.com/TgTZ88Fe", #this is basically the link to take the interview as a candidate
"short": "hflx.io/c/TgTZ88Fe",
"private": "https://admin.hireflix.com/jobs/63d00b73df403de202d97e73/interview/643e972db7d39e63cf468844" #This is the link to access the candidate response in the hireflix admin. It needs autentication. Keep in mind this is not the shareable URL that is an open link... that shareable link you need to create using a mutation.
}
},
"date": 1683705149611
}
#THIS IS AN EXAMPLE OF THE INTERVIEW.CREATE PAYLOAD. IT IS WHAT GETS RETURNED AFTER AN INVITATION TO AN INTERVIEW IS MADE
{
"event": "interview.create",
"data": {
"id": "645b4dbceasas62c007dcbdb6",
"position": {
"id": "63d00b73df4asasase202d97e74",
"name": "Chief Technology Officer"
},
"externalId": null,
"status": "pending",
"hash": "ItZ9V0pK",
"createdAt": 1683705276776,
"candidate": {
"name": "Antonio Webhook ",
"email": "antonio+webhook@hireflix.com",
"phone": null
},
"score": {
"value": null
},
"completed": null,
"deleted": null,
"archived": null,
"finalist": null,
"answered": false,
"thumbnail": null,
"url": {
"public": "https://app.hireflix.com/ItZ9V0pK", #this is basically the link to take the interview as a candidate
"short": "hflx.io/c/ItZ9V0pK",
"private": "https://admin.hireflix.com/jobs/63d00b73df4asasase202d97e74/interview/645b4dbcea4462c007dcbdb6" #This is the link to access the candidate response in the hireflix admin. It needs autentication. Keep in mind this is not the shareable URL that is an open link... that shareable link you need to create using a mutation.
}
},
"date": 1683705276846
}
Q7: What are the statuses that come through in the interview.status-change webhook?
The status that come are:
- "archived" - this is the same as "discarded" an interview through our UI
- "finalist" - this is the same as "preselected" an interview through our UI
- "completed" - this is the same as the "to evaluate" stage which is the default stage where interviews go as soon as they are completed
Q8: Can I embed Hireflix on my website/app etc?
If you're integrating Hireflix into your own software and want candidates to never leave the screen to take a Hireflix Interview and have a smooth experience, embedding can be ideal to accomplish this.
Using an iFrame, you can embed a Hireflix Interview in your HTML5 document in an easy and seamless way.
We've prepared a demo with code, that showcases how you can embed a Hireflix Interview in your software and listen for interview events as they come.
- Use an iFrame to embed a Hireflix Interview Link
<iframe src="the-hireflix-interview-link-goes-here" allow="camera;microphone" />
allow="camera;microphone"
so users can use their camera and microphone in order to take the interview- Listen to postMessage events sent by the Hireflix iFrame
Hireflix uses the postMessage API to send events that you can then receive.
To listen for events is as simple as doing:
window.addEventListener('message', onEventReceived);
An event always has the following format:
{
"type": "event-type", // interview.loaded, interview.finished, etc
"payload": {
...
},
"description": "the event description"
}
This is the list of events currently supported:
Type | Payload | Description |
interview.loaded | The payload is a JSON object containing the interview ID and other metadata | This event is fired when the interview is loaded and the first screen is presented |
interview.finished | This event is fired when the user finishes the interview and the finish screen is presented |
Q9: For embedding-iframe use cases, can I customize the look of the interview UI?
One you have created the interview link through the API, you can use some parameters to modify how the interview looks. Removing borders etc will allow you to more easily embed it on your app.
- primaryColor: (hex color, without #) changes the color of the primary button
- buttonRadius: (hex color, without #) changes the curvature radius of the buttons
- backgroundColor: (hex color, without #) changes the background color
- simple: (true o false). True eliminates the background etc... making it easier to embed without changing the design etc.
E.g: https://app.hireflix.com/(HERE is the interview ID)?buttonRadius=5&simple=true&primaryColor=5dbfd1&backgroundColor=ffffff
Q10: For embedding-iframe use cases, can I automatically close the interview once the candidate has answered?
Yes, as explained in Q8 the Hireflix iframe sends postMessage events, one of which is interview.finished which is fired when the user finishes the interview and the finish screen is presented. You can use that to do what you need.
Q11: For embedding-iframe use cases, can I skip the intro and send candidates straight to the first question?
Yes, to accomplish this, add /preview behind your interview link. So instead of https://app.hireflix.com/njPUaRad do https://app.hireflix.com/njPUaRad/preview
Q12: Can an interview be deleted in case I need to invite the same candidate with same email again?
In Hireflix you can only invite one email to 1 position once. However if you delete the interview then you can of course invite that same email to the same position again. The "delete" mutation under "InterviewNestedMutation" deletes an Interview and this will allow you to invite the candidate again to the same position
Q13: What if I want to show the actual videos of the candidate responses on my ATS/system instead of a link? How do I do that?
The interview object that you can query using our API, returns a list of questions, each one with an answer. The answer object includes the URL of the video answer. For security reasons, this URL is a pre-signed URL, which means that it is short lived and after a while, it will expire and the video will not be able available anymore. For this reason is it advised to NOT save the URL on a database or other persistence mechanism, and instead, always query our API to retrieve the URL. Our system will always return a non-expired and ready-to-use URL for you.
For example, if you want to display interview videos on your frontend, every time a user loads the interview videos screen, your software will have to call our API to retrieve a fresh URL for each answer.
Q14: I am actually showing the video URL directly on my ATS once an interview is completed. How can I make it so that the video is playable directly from my system?
You just need to put the URL of the video in a HTML video tag <video src=heretheURL />.
Q15: Can I allow my users to build interviews in my ATS/system instead of having to build them in Hireflix?
Answer here is yes, it can be done however it is not suggested since it makes the integration more complex. It is better for interviews to be created in Hireflix since our whole UX/UI is optimized already for that. Having said that if you did wanted to build this capability, please contact us.
Q16: What if I want to automatically store the candidate responses in my own server? How do I do that? How do I donwload the answers?
The interview object that you can query using our API, returns a list of questions, each one with an answer. The answer object includes the URL of the video answer. You can use that URL to download the video answer to your system.
You can read the presigned URL of the candidates' video answers by executing the below GraphQL Query. You can then grab the media url field.
The __typename and ... on syntax is called Graphql Union Types, here you can read more about them. They're very powerful and pair very well with programming switch statements over the __typename property when parsing the GraphQL response.
query GetInterview {
interview(id: "interview-id") {
id
steps(input: {}) {
__typename
... on InterviewStepTextQuestionWithVideoAnswer {
id
answers(input: {
onlyMostRecent: true
}) {
__typename
... on InterviewStepTextQuestionWithVideoAnswerAnswer {
id
video {
__typename
... on media {
id
url
}
}
}
}
}
... on InterviewStepVideoQuestionWithVideoAnswer {
id
answers(input: {
onlyMostRecent: true
}) {
__typename
... on InterviewStepVideoQuestionWithVideoAnswerAnswer{
id
video {
__typename
... on media {
id
url
}
}
}
}
}
}
}
}
Q17: Do you have examples of how the integration works already in some of the ATS's you integrated with? Also some general info about what Hireflix does?
Overall video explaining the value of Hireflix: https://www.loom.com/share/5560eeb24c03495bae651382852d060f
Overall video explaining how to create a Hireflix account and the platform features: https://www.loom.com/share/405f2a0f9de845798ab860b791939be3
Integrations where JOB <> INTERVIEW matching happens on ATS side (This is the recommended approach)
- Teamtailor: https://www.loom.com/share/3d120ca9dca04745b300c4045c470121
- Recruitee: https://www.loom.com/share/f6bd54a8df5c43e0abf3943171ea91c3
- SmartRecruiters: https://www.loom.com/share/514e87338334445db21226a2cc81c815
- Greenhouse: https://www.loom.com/share/9b221352873245a7a1e369bee254709c
- Workable: https://www.loom.com/share/8e7091f1d172417c8f846ea318a1b155
- JazzHR: https://www.loom.com/share/4d1aa981eae64db186122385cfffb48f
Integrations where JOB <> INTERVIEW matching happens on Hireflix side
- BambooHR: https://www.loom.com/share/a7f8c9a787fa406eb2e2f6913ebb5048
- Lever: https://www.loom.com/share/c2a6b4beb34c47c593437698cd27ec9b
Q18: Can I know the length of an interview response through the API?
Our API currently reports duration for individual videos of each interview. See the following GraphQL query:
query {
position(id: "position-id") {
id
paginatedInterviews(pagination: { limit: 1 }, status: completed) {
count
total
lastCursor
results {
questions {
answer {
meta {
duration #Here the duration of the answer
}
}
}
}
}
}
}
Q19: Can I fetch the answer transcriptions from the API?
Yes you can. See below a query that fetches the transcription for a specific interview. Keep in mind that if the interview has 3 questions for instance, the transcript for each answer will come separately.
query {
interview(id: "#HERE THE INTERVIEW ID") {
questions {
answer {
transcription {
languageCode
text
}
}
}
}
}
Q20: How can I fetch the completed interviews from a specific position?
First of all, in Hireflix interviews can be in one of 4 stages.
- invited (means they have not answered yet). This is called "pending" on the API
- to evaluate (they answered). This is called "completed" on the API
- shortlisted (they answered). This is called "finalist" on the API
- discarded (they answered). This is called "archived" on the API
If you want to fetch the ones that have completed the interview, then you will have to fetch the ones in completed, finalist and archived stages.
See below a query that fetches the interview ID's of all interviews in the shortlisted stage (called "finalist" in the API). You can do the same for the rest of the stages.
query{
position(id:"#HERE YOUR POSITION ID"){
paginatedInterviews(
pagination:{limit:50} #you could put any other limit here
status:finalist
)
{
results{
id
status
}
}
}
}
Q21: How can I fetch a list of all my candidate notification templates and their ID's?
You can fetch the list of templates and their ID by using the query below 😊🙏. In the query below we are fetching the email ones.
query {
Template(type: "email") {
list {
id
name
}
}
}
Q22: What query can I use to fetch my account logs?
You can use the below query to fetch the logs 😊🙏 Pagination will be required to fetch all data. Remember logs are provided for the last 3 months. If you want to keep all logs, you would need to call the API periodically to fetch them.
query getBasicInfo {
# This query returns basic info for your account.
info {
company {
logs {
# Simple standard skip and limit pagination
audit(pagination: { skip: 0, limit: 10 }) {
count
total
results {
actor {
id
}
timestamp
object
ip
action
host
referer
medium
}
}
}
}
}
}
Q23 Useful queries and mutations you will need in order to allow your users to invite candidates to a Hireflix Interview from your ATS and then see the responses once the interview is finalized.
The approach below uses webhooks. There is a different approach you can follow where, everytime a user goes to the interview list on your ATS, you actually call our API to check if there's any new interview finished etc... to add it to the list. Both are valid approaches.
Q23.1 Create an interview.finish webhook for your client so your system can receive interview.finish events whenever a candidate completes an interview
I suggest you doing this right after the client gives you their API KEY as part of the setup process.
For development purposes you can use the URL generated after loading https://webhook.site on your browser. It will let you see the full payload of the webhook.
mutation {
Webhooks {
create(url: "https://your-callback-url", events: ["interview.finish"])
}
}
Q23.2 Fetch a list of positions:
query {
positions {
id
name
#Here you can add any other property you are interested in. Remember to check the available fields in the Docs tab in the GraphQL Playground
}
}
#You can then, present your users with a list of positions to choose from. Usually only positions that are OPEN are the ones that makes sense to be displayed on the ATS.
Q23.3 Invite a candidate to a Hireflix Interview
mutation {
Position(id: "the-position-id") {
invite(candidate: { email: "the-candidate-email", name: "the-candidate-name" }) {
url {
public
}
}
}
}
Q23.4 Once you have received the interview.finish webhook, create a Shareable link for the interview so you can include it in your system
mutation {
Interview(id:"your-interview-id") {
share(durationInDays: 75) { #Remember you can change the duration in days a Shareable link is valid
externalLink {
url #This is the URL of the newly created Shareable link. Prompt this URL to your users on your system so they can easily watch an interview without having to log in
}
}
}
}
Q24 I am getting an error "Field X of type Y must have a selection of subfields". How can I fix it?
In GraphQL some mutations-queries expect a return always. For example the code below won't work.. because the mutation "invite" always expects a return and you are not specifying below what you want returned.
#this code won't work... it will give you the "must have a selection of subfields" error
mutation {
Position(id: "the-position-id") {
invite(candidate: { email: "the-candidate-email", name: "the-candidate-name" })
}
}
For the code to work you would have to specify a return for example... I want the mutation to return the interview link for the candidate I am inviting as below. That {url{public}} is telling the mutation what to return and hence now, it will work. 😊🙏
mutation {
Position(id: "the-position-id") {
invite(candidate: { email: "the-candidate-email", name: "the-candidate-name" }) {
url {
public
}
}
}
}
Q25: "I'm taking note of the possible errors that the API is returning to me (so far I have a 409, a 500). Is there any document that has the possible errors?
Being a GraphQL API, the errors are returned in an array of errors categorized by the field that has returned the error. For example:
{
"errors": [
{
"message": "invalid candidate email",
"code": 400,
"path": [
"Position",
"invite"
],
"requestId": "9ef6782e79f05876a3c222806d259910"
}
],
"data": {
"Position": {
"invite": null
}
}
}
The API should always return OK 200 in the HTTP protocol. This requires that whenever you make a call to a GraphQL API you inspect the 'errors' array. In the example above, you can see how it categorizes errors according to their 'path,' in this case, 'Position => invite'.
In the case of the 'mutation' to invite a candidate to an 'invite' interview, the possible errors that may occur are 409, 400, and 500.
500: If it is an unknown error that we do not control (In this case, we are aware of this type of errors to solve them)
409: If the candidate has already been invited to the interview for that position
400: This error occurs if the indicated phone or email is incorrect (the example above)
Q26: Can I do custom API calls using Zapier or Make.com?
Yes of course! Below you can see examples for both.
First with Zapier you can use a "Custom Request" using Webhooks by Zapier. See below an example. Make sure to add both headers, the one with the API key, and the one for Content-Type as below. Method will be POST, and URL is the API endpoint as you can see below. Data is the body of the request, which is your query, written in the format we discussed at the beginning of this article on "Q0.2 How do I send a GraphQL Request programmatically to our API?" and Q0.3 which shows you how to format the text properly.
The below query you see is actually that same mutation that invites a candidate to an interview.
{
"query": "mutation {\n Position(id: \"YOUR INTERVIEW ID HERE\") {\n invite(candidate: { name: \"CANDIDATENAME\", email: \"CANDIDATE_EMAIL\" }) {\n id\n url {\n public\n short\n }\n }\n }\n}"
}
For Make.com you do the same by using "Execute a GraphQL query" on the Hireflix Module. On Make.com the headers are automatically added so you just have to chose POST on the method, and then on the Query field you have to paste the query. Below an example. In the case of make you can paste it direclty like below without formating the query on a single line. The below example is a query that fetches each interview's video URL and transcription as well as question title and description...
query MakeGetInterview {
interview(id: "YOUR INTERVIEW ID HERE") {
id
questions {
id
title
description
answer {
id
url
transcription {
languageCode
text
words {
text
start
end
}
}
}
}
}
}
Q27: Can I pass email, first name, last name and phone parameters through the URL for public links?
Yes most certainly. You can see an example below 😊🙏. Just append the below to the public link to populate it with all of that data automatically:
?firstName={first name}&lastName={last name}&email={email}&phoneNumber={number with country code in front}
This way the public link appears with pre-populated data:
- https://interview.thebusinessmarathon.com/public-application/653fc20f6c288d8e26bb7afb
- https://interview.thebusinessmarathon.com/public-application/653fc20f6c288d8e26bb7afb?firstName=Charlie&lastName=Gonzalez&email=charlie@hireflix.com&phoneNumber=%2B34646003003
Q28: I heard the mutation to invite candidates to the interview has been updated. What is the new mutation do you suggest me to use?
We will indeed be deprecating the current invite mutation at some point (no clear date yet). We updated everything to be more aligned with graphql and also to allow first name and last name.
This new mutation uses GraphQL union return types. This way it's much much easier to discover errors, since they're directly specified as part of the return type of the Mutation. It's much more dev friendly.
On your client code you can simply match against the __typename property.
The new future proof mutation is the below:
mutation InviteCandidateToInterview {
inviteCandidateToInterview(
input: {
candidate: {
email: "antonio@hireflix.com"
firstName: "Antonio"
lastName: "Test"
}
positionId: "65afda7ad66b25c281f30a01"
}
) {
__typename
... on InterviewType {
id
}
... on InterviewAlreadyExistsInPositionError {
code
message
}
... on ExceededInvitesThisPeriodError {
code
message
}
# Use the "... on" syntax to discover union types. On your frontend code, you can make use of the __typename property to parse
# a return type or another
}
}
The above is the inline version of the query. Another alternative is to do the below:
mutation InviteCandidateToInterview($input: InviteCandidateToInterviewInput!) {
inviteCandidateToInterview(input: $input) {
__typename
... on InterviewType {
id
}
... on InterviewAlreadyExistsInPositionError {
code
message
}
... on ExceededInvitesThisPeriodError {
code
message
}
# Use the "... on" syntax to discover union types. On your frontend code, you can make use of the __typename property to parse
# a return type or another
}
}
# AND THEN you put the actual query info on the box "query variables" as such
{
"input": {
"candidate": {
"email": "antonio@hireflix.com",
"firstName": "Antonio",
"lastName": "Test"
},
"positionId": "65afda7ad66b25c281fe0a01"
}
}
Q29 How can I delete a position through the API?
Very easy! With the mutation below 😊🙏
mutation DeletePosition {
Position(id: "here-theposition-id") {
delete
}
}