Webhooks
topics to specify the events of interest and create
subscriptions to specify the endpoint to send the notifications to.Using Webhooks
Firstly create a topic to define the type and scope of the events of
interest.
POST https://example.tal.net/api/v1/notification_topics
{
"type": "POSTING_UPDATE",
"name": "Main job board postings update",
"description": "Updates to postings on main internal job board",
"expression": "posting.posting_loc_meth.post_loc_vac.job_board.id == 123"
}
The name and description should be whatever is meaningful for your
application, type should be one of the types of
notification that we support, expression is
a ‘datapath’ expression for limiting the set of events that are of interest.
The topic can now be subscribed to.
POST https://example.tal.net/api/v1/notification_topics/123/subscriptions
{
"start_dt": "2021-04-12T09:22:30.579Z",
"end_dt": "2022-04-12T09:22:30.579Z",
"destination_url": "https://myapp.example.com/webhooks"
}
The start_dt and end_dt cover the intended duration of the subscription and
destination_url is where notifications will be posted.
When the subscription starts notifications will be posted to the endpoint in a standard format:
{
"message_id": "51dd550c-6dda-4dd2-81f4-3309bb04d094",
"timestamp": "2021-01-15T16:50:12Z",
"details": {
"id": 2,
"url": "https://example.tal.net/vx/api/v1/postings/2",
"job_board": {
"id": 2,
"url": "https://example.tal.net/vx/api/v1/job_boards/2"
},
"vacancy": {
"id": 3,
"url": "https://example.tal.net/vx/api/v1/vacancies/3"
}
},
"user": {
"id": "36",
"url": "https://example.tal.net/vx/api/v1/recruiters/36"
},
"subscription": {
"id": 10,
"url": "https://example.tal.net/vx/api/v1/notification_topics/4/subscriptions/10",
"uuid": "c34db4e8-ffc0-40dc-9150-cce795cbf3c2",
"topic": {
"url": "https://example.tal.net/vx/api/v1/notification_topics/4",
"uuid": "218fc25b-9dd8-4793-be92-14a5d391da31",
"id": 4
}
}
}
Notification payloads contain 3 main elements:
- user has attributes about the user who initiated the event that caused the notification to be fired
- subscription has attributes about the subscription and topic
- details has specific details about the event, this varies according to the type (see below)
Note
Payloads do not contain actual data attributes,
instead they contain just IDs and URLs so that suitably privileged client applications can fetch the details if required.
Note
The notification payload should be authenticated to
avoid spoofing attacks, payloads are HMAC-SHA-256 signed and the signature is returned in a ‘x-oleeo-notify-signature’ header. See authentication below.
Types
The set of supported types of notification is being continually expanded as the tooling is added to the ATS. The types of event for the notification available, such as an application has changed status [STATE_CHANGE_APPLICATION] or a vacancy has been posted [POSTING_CREATE], are shown in the current set.
Job board postings
| Type | Description |
|-------------------|-------------|
| POSTING_CREATE | A posting has been created, a job has been posted |
| POSTING_UPDATE | Properties of the posting have been updated, e.g. closing date |
| POSTING_DELETE | A posting has been deleted |
details object in these payloads has URLs for the vacancy that was
posted and the job board it was posted to: "details": {
"id": 2,
"url": "https://example.tal.net/vx/api/v1/postings/2",
"job_board": {
"id": 2,
"url": "https://example.tal.net/vx/api/v1/job_boards/2"
},
"vacancy": {
"id": 3,
"url": "https://example.tal.net/vx/api/v1/vacancies/3"
}
}
Status updates
| Type | Description |
|----------------|-------------|
| STATE_CHANGE_APPLICATION | An application has changed status |
| STATE_CHANGE_OPPORTUNITY | An opportunity, e.g. a vacancy or an event, has changed status |
details object in these payloads has URLs for the subject that has
changed state and its history entries "details":
"id": 222,
"url": 'http://example.tal.net/vx/api/v1/applications/222'
"state_changes":
"url": 'http://example.tal.net/vx/api/v1/applications/222/history'
}
}
Expressions
Expressions are how to specify exactly which events of the specified type are
of interest. They can be arbitralily complex but require a bit of syntax
knowledge and internal IDs to construct correctly, contact your support
representive to get help contructing expressions to fit your requirements.
Examples
Any new postings to job board with ID: 123.
type: POSTING_CREATE
expression: posting.posting_loc_meth.post_loc_vac.job_board.id == 123
type: POSTING_UPDATE
expression: posting.posting_loc_meth.post_loc_vac.job_board.id == 123
AND (posting.closing_date <= (DATE("today") - DTDURATION(0,0,0,30)))
type: STATE_CHANGE_APPLICATION
expression: application.opportunity_id == 321
type: STATE_CHANGE_APPLICATION
expression: application.opportunity_id == 321
AND application.main_process_state.state.id == 111
AND application.user.firstname == "Dave"
Authentication
Notification payloads are signed by including a signature in an
x-oleeo-notify-signature HTTP header. This allows verification that the
notification was sent by Oleeo, not by a 3rd party.
A signing key is generated for each subscription and is required to check the signature. It will be returned in the response to the call to create the subscription and also can be retrieved by fetching the subscription object:
GET https://example.tal.net/api/v1/notification_topics/123/subscriptions/321
{
"topic": {
"id": 123,
"url": "http://example.tal.net/vx/api/v1/notification_topics/123",
"uuid": "ebc4863a-b82c-41c4-a91c-81d2acc17a90",
"created_dt": "2020-04-09T15:32:08Z"
"type": "POSTING_UPDATE",
"name": "Main job board postings update",
"description": "Updates to postings on main internal job board",
"expression": "posting.posting_loc_meth.post_loc_vac.job_board.id == 123"
},
"id": 12,
"url": "http://example.tal.net/vx/api/v1/notification_topics/123/subscriptions/12",
"destination_url": "https://myapp.example.com/webhooks",
"start_dt": "2021-05-07T10:50:11Z",
"end_dt": "2021-06-07T10:50:11Z",
"uuid": "d034529a-c03f-4885-9a47-d10a4d0a05cb",
"signing_key": "269e6cf13b612f027bf6c0b5b8e01ba707c66ccd"
}
Verifying signatures
- Extract the timestamp and signature. The
x-oleeo-notify-signatureheader contains a timestamp and a signature, comma separated.
X-Oleeo-Notify-Signature: 1618308159,14354f8dc6d6b203bad46833aa1ea9ea91f9114c0c602baa6c28635c828e78a9
Prepare a
signed_payloadstring by concatenating the timestamp and json payload with a.characterCompute the expected signature with the SHA256 function using the subscription
signing_keyas the key and thesigned_payloadas the messageCompare the signature from the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.