Set up webhooks
This guide covers how to create, retrieve, and delete webhook subscriptions, validate HMAC signatures, and handle webhook expiration.
Before you begin
- Obtain a valid access token. See Authenticate.
- Required scopes:
connector-protimeapi-webhooks.readandconnector-protimeapi-webhooks.write. - Your destination endpoint must be reachable over HTTPS and able to return a success status code.
- See Webhook lifecycle for background on event delivery, retries, and expiration.
Create a webhook
Create a webhook by sending a request to the webhooks endpoint with the destination URL and collection name.
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks
Host: <tenant>.myprotime.eu
Authorization: Bearer eyJ...Uc
Content-Type: application/json
User-Agent: YourService/v1 (YourCompany){
"destinationUrl": "https://www.your-company.com/protime/clockings",
"collectionName": "clockings"
}A successful response returns 201 Created. The Location header contains the webhook URI and the response body includes a private webhook key.
Retrieve a list of webhooks
Retrieve your webhooks with optional filters on collection-name or status.
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks?filter=<filter-expression>
Host: <tenant>.myprotime.eu
Authorization: Bearer eyJ...Uc{
"value": [
{
"id": "a7d853ea-89eb-4735-83d1-b891c6fde398",
"validUntil": "2025-03-31T12:30:00+02:00",
"status": "Enabled",
"destinationUrl": "https://www.your-company.com/protime/clockings",
"collectionName": "clockings"
}
]
}Filter by status:
GET /connector/protimeapi/api/v1/webhooks?filter=status%20eq%20'Disabled' HTTP/1.1
Host: <tenant>.myprotime.euRetrieve a webhook by ID
GET /connector/protimeapi/api/v1/webhooks/{id} HTTP/1.1
Host: <tenant>.myprotime.eu
Authorization: Bearer eyJ...UcDelete a webhook
Soft-delete a webhook to stop receiving events. You can still query debugging endpoints after deletion.
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks/{id}
Host: <tenant>.myprotime.eu
Authorization: Bearer eyJ...UcValidate the HMAC signature
Every webhook event includes an Authorization header with an HMAC-SHA256 signature. Validate it to confirm the request came from Protime and that the payload was not tampered with.
The header format is: Authorization: HMAC-SHA256 {signature}
Example validation in C#:
private async Task<bool> ProtimeAuthHeaderIsValid(AuthenticationHeaderValue protimeAuthHeaderValue)
{
if (protimeAuthHeaderValue.Scheme == "HMAC-SHA256")
{
var requestBody = await GetJsonRequestBody();
const string webhookKey = "privateWebhookKey";
using var hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(webhookKey));
var bytes = Encoding.UTF8.GetBytes(requestBody);
var hash = hmacSha256.ComputeHash(bytes);
var calculatedHmacSignature = Convert.ToBase64String(hash);
return protimeAuthHeaderValue.Parameter == calculatedHmacSignature;
}
return false;
}Handle webhook expiration
Check the validUntil property to know when a webhook expires. When a webhook expires or is disabled due to prolonged unreachability, follow these steps:
- Re-initiate a full data sync using the standard GET list endpoints to ensure your data is current.
- Create a new webhook by calling the POST endpoint with the appropriate destination URL and collection name.
Add external references to webhooks
Include the externalReferences query parameter when creating the webhook. The webhook events will then include the specified external references in the payload.
Predefined external reference:
POST /connector/protimeapi/api/v1/webhooks?externalReferences=(people,@badge-number) HTTP/1.1
Host: <tenant>.myprotime.eu
Content-Type: application/json{
"destinationUrl": "https://www.your-company.com/protime/clockings",
"collectionName": "clockings"
}Custom external reference:
POST /connector/protimeapi/api/v1/webhooks?externalReferences=(activity-definitions,actDef) HTTP/1.1
Host: <tenant>.myprotime.eu
Content-Type: application/json{
"destinationUrl": "https://www.your-company.com/protime/clockings",
"collectionName": "clockings"
}Handle duplicate events
Some actions in Protime trigger multiple webhook events due to automatic calculations. Use the changeVersion property on each event to determine whether a received object is newer than one you already processed. If the changeVersion is older (string comparison), ignore it.
Related
- Webhooks reference – properties, retry schedule, supported collections
- Webhook lifecycle – event model, delivery guarantees, and retry strategy
- Use external references – predefined and custom external reference patterns