Getting started
Guides
Concepts
Resources
Asynchronous updates from October API
<aside> ✅ If you do not have an account yet, contact your October representative who will create one for you.
</aside>
Webhooks are HTTP POST requests sent to a given URL each time certain events happen on the platform. They allow you to build deep integrations of our API into your organization system, track events or/and automatically trigger actions, without having to pull updates from our API on your side.
When configuring a webhook you can use the October App to subscribe to some events (one or many). Each event is linked to a certain action that happened on the October platform, related to your organization.
The list of available events is:
| Type | Description |
|---|---|
new_report |
Triggered when a new report has been created |
Sign in to your October account.
Click on the “Organization Settings” tab, then “Webhooks”
Click on the “Add Webhook” button, add your url, and select the events that will trigger it.
new_report)
Once the webhook is created, do a GET /businesses/[business id] HTTP request to list all your webhook configurations at the path business.settings.webhooks
In the webhook configuration, you will find the keys needed to validate the webhooks you will receive
In the webhooks configuration tab of the app, add a new webhook with the events you want to subscribe to, and your endpoint URL. The secret key will be generated by October.
You can see all your added URLs in the webhooks configuration page:

The endpoint we will use is POST /businesses/:id for this setup. These calls will create / update / delete webhook settings for your business.
A webhook setting is composed of a url (where the callback should be sent), a list of events and a key (automatically generated by the October Api).
Adding a new webhook setting consist of sending an Json object including a list of events and an url.
{
"events": ["update_request"],
"url": "<https://test.fr>",
}
This webhook setting is stored in the settings.webhooks array field of your business, with a generated key .
Here is a list of examples HTTP post requests bodies to create / add / delete webhooks settings for your business :
{
"settings": {
"webhooks":[
{
"events":["update_request"],
"url":"<https://test.fr>",
},
]
}
Example response sent by the api
{
"business": {
"code": {
"type": "siren",
"id": "123456789"
},
"id": "615ec1280906c5118dea77e6",
"name": "Borrower partner business",
"registrar": {},
"settings": {
"maxMonthlyRequests": 20,
"webhooks": [
{
"events": ["update_request"],
"url": "<https://test.fr>",
"key": "e4d1a4233b4cbe0473d44de1716e1065"
},
]
},
"creator": "615ec11a0906c5118dea77e4",
"meta": {},
"type": "partner"
}
}
{
"settings": {
"webhooks":[
{
"events":["update_request"],
"url":"<https://test.fr>",
"key":"4338b9437fb5c91aba507fff6a27b017"
},
{
"events":["new_offer", "update_offer"],
"url":"<https://test2.fr>",
"key":"9e60c8e60e6983b1c7626558bfceeb43"
}
]
}
}
{
"settings": {
"webhooks":[
{
"events":["new_offer", "update_offer"],
"url":"<https://test2.fr>",
"key":"9e60c8e60e6983b1c7626558bfceeb43"
}
]
}
}
The webhook is a JSON object sent to you with an HTTP POST request.
The HTTP headers contain:
The body of the webhook contains:
event, the type of the event,diff object, if the event is related to an update with:
propertyafterIn case of a newly created resource, the webhook contains only the resource ID.
In case of a resource update, the after field contains the new value, following the formats defined in the Models part of the API documentation.
"headers": {
"Content-Type": "application/json",
"X-O5R-HASH": "xxx", // (timestamp + body) hashed with the webhook **key**
"X-O5R-TIMESTAMP": "1632996186011" // webhook sending timestamp
},
"body": {
"event": "update_request" | "new_offer" | "update_offer",
"requestId": String | undefined,
"offerId": String | undefined,
"diff": {
"property": "status" | "stage" | "requirements",
"after": Any // updated object
} | undefined
}
{
"event": "update_request",
"requestId": "1b9e20b6hexb81w0133ahe92",
"diff": {
"property": "status",
"after": "accepted"
}
}
To authenticate webhook requests and to make sure that October is actually sending the webhook, it is important to use the security headers provided with each notification.
The headers contain 2 security keys, X-O5R-HASH and X-O5R-TIMESTAMP:
X-O5R-HASH : timestamp + webhook body, hashed with the SHA256 algorithm, using the secret key (provided in the webhook settings).X-O5R-TIMESTAMP : Timestamp created when sending the message. You can use it to determine that the X-O5R-HASH hashed body contains a matching timestamp, and refuse all webhooks not checking this condition.Once the X-O5R-HASH is validated with the X-O5R-TIMESTAMP, you will be able to validate that the body of the webhook matches its hashed value.
This will prevent attackers from sending you fake notifications or content.
X-O5R-HASHHash (using the SHA256 Hmac algorithm) the timestamp and the body with the secret key (provided in the webhooks settings).
{
"event": "update_request",
"requestId": "1b9e20b6hexb81w0133ahe92",
"diff": {
"property": "status",
"after": "accepted"
}
}
Will be transformed into
'{"event":"update_request","requestId":"1b9e20b6hexb81w0133ahe92","diff":{"property":"status","after":"accepted"}}'
sha256Hmac(X-O5R-TIMESTAMP + strigifiedBody, secretKey)Here an example of how you can do it:
const crypto = require('crypto');
const receivedHash = '134e8169151948be2b3a35ae09405b56c29917b8a8371d349ef162b0b1976982';
const receivedBody = '{"event":"update_request","requestId":"1b9e20b6hexb81w0133ahe92","diff":{"property":"status","after":"accepted"}}';
const receivedTimestamp = '1647937499151';
const secretKey = 'c35d3a6f69d7dfb55c2b19364039aa14';
const hash = crypto.createHmac('sha256', secretKey).update(receivedTimestamp+receivedBody).digest('hex');
console.log(hash); // Prints 134e8169151948be2b3a35ae09405b56c29917b8a8371d349ef162b0b1976982
console.log(hash === receivedHash) // Prints true
Webhooks sent by October have a retry policy to handle transient failures when it tries to connect to your service.