{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"bf903a19-0b74-4537-a863-6dc3131510c2","name":"Willo Integration API V2","description":"# Welcome to the Willo API documentation\n\n## Authentication\n\n**The Willo API uses API keys to authenticate requests** - you can view and manage your API keys on your [Willo Integrations page](https://app.willotalent.com/integrations).\n\nEach user has their own API key. This API key carries the same permissions as this user and will dictate the permissions of any requests made using this API key.\n\nYour API keys carry many privileges, so be sure to keep them secure. Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code etc.\n\nAll API requests must be made over [HTTPS](http://en.wikipedia.org/wiki/HTTP_Secure). Calls made over plain HTTP will fail. API requests without authentication will also fail.\n\n**Cycle your API key at any time** - important if you think someone else has obtained it without your permission. [Issue new key](https://app.willotalent.com/integrations).\n\n## Rate Limits\n\nWillo has API throttling to allow more consistent performance within a time span for customers calling our APIs. Throttling limits the number of requests to a service in a time span to prevent the overuse of resources. While Willo is designed to handle a very high volume of requests, if an overwhelming number of requests occur by few customers, throttling helps maintain optimal performance and reliability for all customers and candidates.\n\n## Webhook Delivery & Retries\n\nWillo delivers webhooks with automatic retries. As long as your endpoint is healthy most of the time, you do not need to build a polling fallback - transient failures are retried for roughly 23 hours per event.\n\n#### Successful delivery\n\nAny 2xx response from your endpoint is treated as a successful delivery. The delivery is logged and no further attempts are made for that event.\n\nRespond within 5 seconds. Return your 2xx as soon as you have accepted and persisted the payload, and do any real processing asynchronously. If your endpoint does not respond within 5 seconds, the delivery times out and is treated as a failure - even if your handler eventually finishes the work.\n\n#### What we retry\n\nWe retry deliveries that fail for reasons likely to be temporary:\n\n- Any 5xx response\n    \n- 429 Too Many Requests\n    \n- Timeouts, DNS failures, TLS errors and other network-level failures. Retries follow the standard schedule below in all cases.\n    \n\n#### What we do not retry\n\nAll other 4xx responses (400, 401, 403, 404, …) are treated as permanent failures for that event. These indicate  \na problem with the endpoint URL, its authentication, or the way it handles the payload - none of which a retry  \nwill resolve. The delivery is marked as failed immediately and no retries are attempted.\n\nIf your service is temporarily broken (for example, a dependency is down), return a 5xx rather than a 4xx. A 4xx  \ntells us to give up on the event - and repeated 4xx responses count against your endpoint's health (see below).\n\n#### Retry schedule\n\n| Setting | Value |\n| --- | --- |\n| Initial backoff | 1 minute |\n| Multiplier | 2 |\n| Maximum backoff | 60 minutes |\n| Maximum retries | 28 |\n\nBackoff intervals grow as 1, 2, 4, 8, 16, 32 minutes, then hold at the 60-minute maximum for all remaining  \nattempts - approximately 23 hours of retries per event in total. If all retries fail, the delivery is marked as  \nfailed and the event is not sent again.\n\n#### Endpoint health and automatic disabling\n\nWebhooks that fail persistently are automatically disabled:\n\n- Repeated failures. If the large majority of deliveries to your endpoint fail over a sustained period (on the  \n    order of a week), the webhook is disabled and its owner is notified by email. Both retryable failures (5xx,  \n    network errors) and permanent ones (non-429 4xx) count toward this; 429 responses do not.\n    \n- Inactivity. A webhook that has not received any deliveries for 180 days expires automatically. Warning emails  \n    are sent to the owner ahead of expiry.\n    \n\nA disabled or expired webhook receives no further deliveries. Once your endpoint is healthy, register a new  \nwebhook subscription - and contact support if you need events replayed to cover the gap.\n\n#### Building a resilient endpoint\n\n- Be idempotent. The same event can be delivered more than once - for example, if your handler exceeds the  \n    5-second window, we treat the delivery as failed and retry even though you may have processed it. Deduplicate on  \n    the identifiers in the payload rather than assuming exactly-once delivery.\n    \n- Do not rely on ordering. A retried event may arrive after events that were triggered later. Reconcile using the  \n    timestamps and object state in the payload, not the order of arrival.\n    \n- Acknowledge first, process second. Persist the payload, return 2xx, then do the real work asynchronously.\n    \n- Handle bursts. High-volume activity in Willo (for example, a large invite batch) generates a corresponding burstof webhooks.\n    \n\n### Best practice to avoid rate limiting\n\nProgramming practices such as continuously polling an endpoint to check for updates and regularly scanning jobs to check for new or deleted responses are more likely to lead to throttling and will degrade overall performance. Concurrent API calls may lead to high number of requests per unit time, which will also cause requests to be throttled. You should instead use **webhooks** for change tracking and change notifications.\n\nIf you are regularly hitting your limit with higher volume demands, please contact us to discuss an increased rate limit.\n\n## Data Privacy and Security\n\nBusinesses that use Willo can be confident that the company takes security seriously and employs best practices to ensure that privacy and security are not compromised.\n\nThe nature of the data that Willo handles on behalf of its customers requires that security is a core part of the approach to building, scaling, and managing the service.\n\n### **Highlights**\n\n- Our AWS hosted data centres are ISO/IEC 27001:2013 certified\n    \n- Encryption In-Transit (TLS 1.2)\n    \n- Encryption At-Rest (AES-256)\n    \n- Web Application Firewall (WAF)\n    \n- Distributed Denial of Service (DDoS) Protection\n    \n- Regular Vulnerability Scanning\n    \n- 24/7 Monitoring and Incident Response\n    \n- GDPR Compliance\n    \n- ISMS Certified to ISO 27001:2022\n    \n- WCAG 2.1 AA aligned\n    \n\n## **Changelog and System Status**\n\nWe work hard to keep our developer community updated with the latest changes and enhancements to the platform.\n\nView our [weekly changelog here](https://feedback.willo.video/changelog).\n\nSubscribe to our [system status here](https://status.willo.video/).\n\n## Developer Support\n\n**30 minute quick start guide** - view our getting [started guide here](https://support.willo.video/article/234-build-an-ats-integration-with-willo-in-30-minutes).\n\n**Save time and hassle** - schedule premium 1-to-1 time with an expert in our integrations team and we'll help you go live asap. [Book developer support now](https://book.stripe.com/00gbKJetrcefeFW9AT).\n\n## Status Codes\n\n| Status Code | Description |\n| --- | --- |\n| 200 - OK | Everything worked as expected. |\n| 201 - Created | The object in the request was successfully created. |\n| 400 - Bad Request | The request was unacceptable, often due to missing a required parameter. |\n| 401 - Unauthorised | No valid API key provided. |\n| 403 - Forbidden | The API key doesn't have permissions to perform the request. |\n| 404 - Not Found | The requested resource doesn't exist. |\n| 429 - Too Many Requests | The client has sent too many requests in a given time frame |\n\n## Glossary\n\n| **Term** | **Description** |\n| --- | --- |\n| **Department** | A department is a sub-division of the account. In the UI, a department is referred to as a **Company**. Typically, departments are used to represent divisions of a business (eg brand, geography etc).  <br>  <br>Each department can be configured to have different branding via API or using the UI.  <br>  <br>Users must be granted permissions to view departments unless they are set to 'Global' in which case all users will have access to this department by default. |\n| **Interview** | An interview contains a list of pre-defined questions that the participant must answer.  <br>  <br>In the use case of recruitment, 'interviews' typically correspond to 'jobs' within an ATS. |\n| **Message Template (Template)** | Message Templates are used to manage the email and SMS communication that is sent to Participants from Willo.  <br>  <br>Each type of Message Template has a system default. Additional Message Templates can be added and customized. Once added, Message Templates can be configured to be used for Interviews.  <br>  <br>When inviting a Participant to participate in an Interview, Message Templates can be configured to be On or Off.  <br>  <br>There are 3 types of Message Template:  <br>**1\\. Invite** (Email & SMS) - this is triggered when a Participant is invited to participate in an Interview. SMS will only be triggered if a valid phone number is provided.  <br>  <br>**2\\. Reminder** (Email & SMS) - this is triggered in the event that a Participant has not completed their Interview within 48 & 72 hours of receiving an invitation. SMS will only be triggered if a valid E.164 formatted phone number is provided.  <br>  <br>**3\\. Success Email** (Email only) - this is a transactional email sent to the Participant to confirm once they have successfully completed their interview. It is useful to avoid candidates reaching out to query if their interview has been recevied. |\n| **Participant** | A Participant is a user who participates in an Interview. Refered to as a 'candidate' in recruitment use cases.  <br>  <br>Participants are **not** required to download, log in or authenticate to complete an interview. All [major browsers and devices are supported](https://support.willo.video/article/56-required-equipment). |\n| **Users** | Users are authenticated users with access to Interviews and Participants. There are Three roles:  <br>  <br>**1\\. Owner** - this is the account owner with the highest level of access. By default they will receive invoices and receipts.  <br>  <br>**2\\. Admin** - this is the highest level of permissions that can be granted to a user who is not the account owner. Admins have permission to Create, Read, Update & Delete ALL Departments, Interviews and Participants.  <br>  <br>**3\\. Standard** - this is the lowest level of permissions. Standard users only have permission to Create, Read, Update & Delete Departments, Interviews and Participants that belong to their account by default. Standard users can be invited by other users to view other Interviews. |\n| **Webhooks** | Webhooks can be configured to trigger notifications to a 3rd party system's endpoints.  <br>  <br>There are four types of triggers:  <br>**1\\. New Response** - when a new Interview response is received by a Participant.  <br>  <br>**2\\. Status Change** - when a Participant is moved to a different status within the Willo Kanban board.  <br>  <br>**3\\. New Comment** - when a Participant receives a comment from any member of the hiring team  <br>  <br>**4\\. New Score** - when a Participant receives a score from a member of the hiring team. |\n| Child Organisation | An organisation created under a parent organisation. Child organisations operate within the parent’s umbrella and inherit its properties, but can be managed independently. |","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"7798010","team":22755771,"collectionId":"bf903a19-0b74-4537-a863-6dc3131510c2","publishedId":"VUjSEiSn","public":true,"publicUrl":"https://documenter-api.postman.tech/view/7798010/VUjSEiSn","privateUrl":"https://go.postman.co/documentation/7798010-bf903a19-0b74-4537-a863-6dc3131510c2","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"EF5B25"},"documentationLayout":"classic-double-column","customisation":null,"version":"8.12.8","publishDate":"2022-11-24T11:52:45.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{},"logos":{}},"statusCode":200},"environments":[{"name":"Integration API V2 Production","id":"e01f648c-9d90-4eed-ba9b-ba1c2a3d0ee2","owner":"7798010","values":[{"key":"base_url","value":"https://api.willotalent.com/api/integrations/v2","enabled":true,"type":"default"}],"published":true}],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/6deb204c61403452c5ae312b7b1847ff1c30f8c56a406fbce8d6a1bbc3229a46","favicon":""},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"},{"label":"Integration API V2 Production","value":"7798010-e01f648c-9d90-4eed-ba9b-ba1c2a3d0ee2"}],"canonicalUrl":"https://documenter.gw.postman.com/view/metadata/VUjSEiSn"}