Webhooks

Webhooks

This page documents the webhook specification for the Protime API, including supported collections, properties, HMAC signature format, automatic retry intervals, expiration behavior, and management endpoints.

Supported collections

The following collections support webhooks:

Collection collectionName
Absences absences
Absence definitions absence-definitions
Absence groups absence-groups
Access clockings access-clockings
Activity durations activity-durations
Assignments assignments
Break definitions break-definitions
Breaks breaks
Calculated totals calculated-totals
Clockings clockings
Contracts contracts
Counters counters
Counter definitions counter-definitions
Counter groups counter-groups
Paid presences paid-presences
People people
Shift definitions shift-definitions
Work interruptions work-interruptions

Webhook properties

Property Type Description
id string Unique identifier for the webhook.
validUntil string Expiration date and time of the webhook (ISO 8601 format).
status string Status of the webhook: Enabled or Disabled.
externalReferences object External references used for the webhook (e.g., people, terminals).
destinationUrl string Destination URL for webhook events towards the client.
collectionName string Name of the collection subscribed to for webhook events.

Status values

Status Description
Enabled The webhook is active and delivering events. This is the initial status after creation.
Disabled The webhook has been disabled (e.g., due to expiration or prolonged unreachability).

Webhook expiration

  • Each webhook has a limited validity period, indicated by the validUntil property.
  • When a webhook expires or is disabled, a full reinitialization is required: perform a complete initial sync, then create a new webhook.
  • Reusing an expired or disabled webhook is not supported.

changeVersion field

Each object in a webhook event includes a changeVersion field. This field supports string comparison for determining relative ordering. If a newly received object has a changeVersion older than a previously received object with the same identifier, the newer receipt can be ignored.

Some actions in the Protime environment can trigger multiple webhook events due to automatic calculations. The changeVersion field is the mechanism for handling duplicates and ordering.

Event payload format

Each webhook event is delivered as a JSON object with two fields:

Field Type Description
changeType string The type of change: InsertOrUpdate or Delete.
data object The affected resource, serialized in the same shape as the corresponding collection endpoint.

Example:

{
    "changeType": "InsertOrUpdate",
    "data": {
        "id": "d4f7a5c1-0e82-4b3a-9c6f-1a2b3c4d5e6f",
        "changeVersion": "00000000000000012345"
    }
}

The data object contains all fields of the affected resource, matching the shape returned by the corresponding collection GET endpoint.

The data object includes a changeVersion field that supports ordering and deduplication (see changeVersion field).

HMAC-SHA256 signature

Every webhook request includes an HMAC signature in the Authorization header:

Authorization: HMAC-SHA256 {signature}

The signature is generated using:

  • Algorithm: HMAC-SHA256
  • Key: The private webhook key returned when the webhook is created
  • Input: The exact JSON request body
  • Encoding: The result is Base64-encoded

The Authorization header always indicates the authentication scheme used (HMAC-SHA256), allowing future scheme upgrades.

Validation example (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;
}
The signature must be calculated on the exact JSON request body as received. Binding the incoming request to a custom model and re-serializing it is not reliable, because serialization settings may differ.

Automatic retries

Webhooks contain a built-in retry mechanism. The default retry intervals are:

Retry Interval after previous attempt Approximate total elapsed time
1 ~1 hour ~1 hour
2 ~3 hours ~4 hours
3 ~8 hours ~12 hours
4 ~24 hours ~36 hours
5 ~36 hours ~72 hours

The total retry window is up to 72 hours.

If the webhook consumer fails to respond with a success status code after all retries, automatic retries stop and the webhook is disabled. All events still in a retry state at that moment are purged.

Occasional duplicate delivery is possible. Every event includes a changeVersion that enables idempotent processing.

Management endpoints

Create a webhook

POST
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks

Request body:

{
    "destinationUrl": "https://www.fictional-customer.com/protime/clockings",
    "collectionName": "{collectionName}"
}

On success, the response includes:

  • Status: 201 Created
  • Location header: /connector/protimeapi/api/v1/webhooks/{id}
  • Response body: Contains the private webhook key (store it for HMAC validation).

Retrieve a list of webhooks

GET
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks?filter=<filter-expression>

Response:

{
    "value": [
        {
            "id": "a7d853ea-89eb-4735-83d1-b891c6fde398",
            "validUntil": "2025-03-31T12:30:00+02:00",
            "status": "Enabled",
            "destinationUrl": "https://www.fictional-customer.com/protime/clockings",
            "collectionName": "clockings"
        }
    ]
}

Filters

Property Operator Example
collection-name in filter=collection-name in ('activity-durations','clockings')
status eq filter=status eq 'Disabled'

Retrieve a webhook by ID

GET
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks/{Id}

Delete a webhook

DELETE
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks/{Id}

Performs a soft delete. The webhook remains queryable via debugging endpoints after deletion.

External references with webhooks

Adding, updating, or deleting external references on an existing webhook is not possible. To change external references, delete the existing webhook and create a new one with the desired references.

Predefined external references

POST
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks?externalReferences=(people,@badge-number)

{
    "destinationUrl": "https://www.fictional-customer.com/protime/clockings",
    "collectionName": "clockings"
}

Custom external references

POST
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/webhooks?externalReferences=(activity-definitions,actDef)

{
    "destinationUrl": "https://www.fictional-customer.com/protime/clockings",
    "collectionName": "clockings"
}

See also