Webhooks
Configuring a webhook
To receive near real-time updates when dataset operations finish:
-
Log into Timefold Platform and click on the dropdown at the top right next to your username.
-
Click on Tenant settings.
-
In the menu on the left hand side click Webhooks to access the webhooks configured for your tenant.
-
Click Add Webhook to create a new webhook.
-
Enter the URL to receive event updates from your tenant.
-
Accept the generated name or provide a name for the webhook.

Optionally, you can define http-headers that Timefold will send along with the webhook, for instance, to pass on an Authorization
header.
Enable or disable the webhook with the toggle.
When webhooks trigger
Webhooks trigger when a dataset reaches the following statuses:
-
Dataset computed
-
Dataset invalid
-
Solving completed (This includes when a dataset solve operation is cancelled.)
-
Solving incomplete
-
Solving failed
Read more about statuses: Dataset lifecycle.
If the webhook is always triggered, for each event we will send a POST
call to the specified URL.
In the configuration UI you can specify (optional) filters to only receive webhooks in certain cases:
-
Only when datasets reach certain statuses.
-
Only for datasets with a name that matches a specific regular expression.
-
Only for datasets that have the specified tags.
Webhook payload
Here is an example payload that will be sent to the webhook when a dataset has completed:
{
"id": "<the-id-of-the-dataset>",
"name": "<name of the dataset>",
"model": "field-service-routing",
"modelVersion": "v1",
"tags": [],
"status": "SOLVING_COMPLETED",
"runLink": "https://...", // Link to the API where you can fetch details about the dataset itself,
"outputLink": "https://..." // Link to the API where you can fetch the dataset's output
}
Retry strategy
Our platform expects the webhook URL to return HTTP Status Code 200. If the response code is different, we will try again 10 seconds later. We will retry up to 10 times.
HMAC authorization
Why HMAC authorization?
HMAC (Hash-based Message Authentication Code) authorization is used to verify that a webhook request actually comes from the Timefold Cloud Platform and hasn’t been tampered with in transit.
-
Security: Ensures that only requests signed with your secret HMAC key are accepted.
-
Integrity: Confirms that the webhook payload or request path hasn’t been altered.
-
Replay protection: By including a timestamp in the signed request, you can detect and reject replayed requests.
Using HMAC verification adds an extra layer of trust to your webhook integrations, and is especially useful when the webhook triggers important actions in your system.
How to enable HMAC
-
When setting up a webhook in the Timefold Platform, go to the Authorization dropdown in the webhook’s settings.
-
Select HMAC (default is None).
-
Provide a HMAC key. This secret key will be used to sign all webhook requests.
Once enabled, Timefold will automatically include the following headers in each webhook request:
-
X-Timefold-Signature
: the HMAC signature of the request. -
X-Timefold-Timestamp
: the time of the request, in ISO-8601 formatyyyy-mm-ddThh:mm:ssZ
.
We use HMAC_SHA_256
as the hashing algorithm and the values are base64
encoded.
Signature content options
By default, the HMAC signature is calculated over the webhook Body (= payload). You can also choose Path in the HMAC Method dropdown, if you want the signature to be based on the webhook URL path instead.
Custom headers
The HMAC signature: {hmac_signature}
and the time: {hmac_timestamp}
can also be used as
variables when configuring custom headers.
This allows you to:
-
Send the signature and timestamp under different header names.
-
Add prefixes or postfixes to the values of the headers.
Example configurations
Default HMAC setup
Sample request sent by Timefold
POST /path-to-receiving-endpoint HTTP/1.1
Host: example.org
Content-Type: application/json
X-Timefold-Signature: f2Ak8ODZo7...
X-Timefold-Timestamp: 2025-09-26T10:28:16Z
{"id":"8dbdce26-8b9a-45a2-9cb5-0a3dc2fc2cc7", "parentId": [...]}
Verification pseudocode
signature_header = request.headers["X-Timefold-Signature"]
timestamp_header = request.headers["X-Timefold-Timestamp"]
content = request.body // raw JSON string
expected_signature = base64encode(HMAC_SHA_256(secret_key, content))
if !secure_compare(signature_header, expected_signature):
reject_request("Invalid signature")
if abs(current_time - timestamp_header) > allowed_window:
reject_request("Stale request")
HMAC setup using method "Path" and custom headers
Webhook settings
-
Authorization: HMAC
-
HMAC method: Path
-
Headers:
-
X-My-Custom-Signature
:MYPREFIX:{hmac_signature}
-
X-My-Custom-Timestamp
:{hmac_timestamp}
-
Sample request sent by Timefold
POST /path-to-receiving-endpoint HTTP/1.1
Host: example.org
Content-Type: application/json
X-My-Custom-Signature: MYPREFIX:Qk1fpcu1oL...
X-My-Custom-Timestamp: 2025-09-26T10:28:16Z
{"id":"8dbdce26-8b9a-45a2-9cb5-0a3dc2fc2cc7", "parentId": [...]}
Verification pseudocode
signature_header = request.headers["X-My-Custom-Signature"]
timestamp_header = request.headers["X-My-Custom-Timestamp"]
// remove prefix before verification
raw_signature = signature_header.remove_prefix("MYPREFIX:")
content = "POST" + "+" + request.path + "+" + timestamp_header
expected_signature = base64encode(HMAC_SHA_256(secret_key, content))
if !secure_compare(raw_signature, expected_signature):
reject_request("Invalid signature")
if abs(current_time - timestamp_header) > allowed_window:
reject_request("Stale request")