Your First Clocking Integration

Your First Clocking Integration

What you’ll learn: How to authenticate with read and write scopes, create a clocking via the API, retrieve it back, and set up delta tracking to detect changes incrementally.

Prerequisites

Before we begin, make sure you have the following:

  • A tenant name for your Protime environment (e.g. acme from https://acme.myprotime.eu)
  • An OAuth2 client_id and client_secret provided by Protime
  • A tool for making HTTP requests (e.g. curl, Postman, or your programming language of choice)
  • The person ID of an employee in your Protime environment (we’ll use 1 in this tutorial)
  • Completed the Your first API call tutorial

Step 1: Authenticate with read and write scopes

We need both read and write permissions for clockings. Let’s request a token with both scopes.

Request

POST
https://authentication.<environmentURL>/tenants/<tenantName>/connect/token

POST /tenants/acme/connect/token HTTP/1.1
Host: authentication.myprotime.eu
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=your-client-id&client_secret=your-client-secret&scope=connector-protimeapi-clockings.read connector-protimeapi-clockings.write

Verify: The response contains an access_token with both scopes listed.

{
  "access_token": "eyJ...Uc",
  "expires_in": 1800,
  "token_type": "Bearer",
  "scope": "connector-protimeapi-clockings.read connector-protimeapi-clockings.write"
}

We’ll use this token for all remaining steps.

Step 2: Create a clocking

Let’s create an InOut clocking for person 1 at 08:30 (510 minutes since midnight) on 2026-01-15.

Request

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

POST /connector/protimeapi/api/v1/clockings HTTP/1.1
Host: acme.myprotime.eu
Authorization: Bearer eyJ...Uc
Content-Type: application/json
{
  "person": {
    "id": 1
  },
  "date": "2026-01-15",
  "timeOfDayInMinutes": 510,
  "kind": "InOut"
}

Verify: You should see a 201 Created response. The Location header contains the URL of the newly created clocking.

HTTP/1.1 201 Created
Location: /connector/protimeapi/api/v1/clockings/19250

Save the ID from the Location header (in this example, 19250). We’ll use it in the next step.

Step 3: Retrieve the created clocking

Let’s confirm the clocking was created correctly by fetching it using the ID from the Location header.

Request

GET
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/clockings/19250

GET /connector/protimeapi/api/v1/clockings/19250 HTTP/1.1
Host: acme.myprotime.eu
Authorization: Bearer eyJ...Uc

Verify: The response matches the clocking we created, with the person, date, time, and kind all reflecting our input.

{
  "changeVersion": "0000090200004CE0000A",
  "id": 19250,
  "calculatedTimeOfDayInMinutes": 510,
  "isGenerated": false,
  "status": "Active",
  "person": {
    "id": 1
  },
  "date": "2026-01-15",
  "timeOfDayInMinutes": 510,
  "kind": "InOut"
}

The changeVersion field is assigned by the system. We’ll see this value again when we use delta tracking.

Step 4: Set up delta tracking

Delta tracking lets us fetch only changes since our last request, rather than re-downloading all data. Let’s initialize a delta for clockings.

We start a delta by adding the delta query parameter to the GET list endpoint. A date filter is required.

Request

GET
https://<tenant>.myprotime.eu/connector/protimeapi/api/v1/clockings?filter=date ge '2026-01-01'&delta

GET /connector/protimeapi/api/v1/clockings?filter=date%20ge%20'2026-01-01'&delta HTTP/1.1
Host: acme.myprotime.eu
Authorization: Bearer eyJ...Uc

Verify: The response contains a value array with existing clockings. If there is a nextLink, we must follow it to page through all data.

{
  "value": [
    {
      "changeVersion": "0000090200004CE0000A",
      "id": 19250,
      "status": "Active",
      "person": { "id": 1 },
      "date": "2026-01-15",
      "timeOfDayInMinutes": 510,
      "kind": "InOut"
    }
  ],
  "nextLink": "/connector/protimeapi/api/v1/clockings?filter=date ge '2026-01-01'&continuationToken=eyJ2YW...&deltaToken=eyJkZW..."
}

We follow every nextLink until we reach a page that contains a deltaLink instead. This final page signals that we have consumed all initial data.

{
  "value": [],
  "deltaLink": "/connector/protimeapi/api/v1/delta/clockings?deltaToken=eyJkZWx0YUlkIjo2NzcsInN0YXJ0aW5nQ3Vyc29yIjowLCJ0aW1lU3RhbXAiOiIyMDI2LTAxLTE1VDEwOjAwOjAwLjAwMDAwMDBaIn0="
}

Verify: The response contains a deltaLink field. Save this URL – it is our bookmark for tracking future changes.

Step 5: Check for changes

Now let’s use the deltaLink to check for changes. Since we just created a clocking in Step 2 and then initialized the delta, we should see our clocking appear as an InsertOrUpdate change.

Request

GET
https://<tenant>.myprotime.eu{deltaLink}

GET /connector/protimeapi/api/v1/delta/clockings?deltaToken=eyJkZWx0YUlkIjo2NzcsInN0YXJ0aW5nQ3Vyc29yIjowLCJ0aW1lU3RhbXAiOiIyMDI2LTAxLTE1VDEwOjAwOjAwLjAwMDAwMDBaIn0= HTTP/1.1
Host: acme.myprotime.eu
Authorization: Bearer eyJ...Uc

Verify: The response contains a value array with change objects. Each change includes a changeType (InsertOrUpdate or Delete) and a data object with the clocking details. A new deltaLink is provided for the next request.

{
  "value": [
    {
      "changeType": "InsertOrUpdate",
      "data": {
        "changeVersion": "0000090200004CE0000A",
        "id": 19250,
        "calculatedTimeOfDayInMinutes": 510,
        "isGenerated": false,
        "status": "Active",
        "person": { "id": 1 },
        "date": "2026-01-15",
        "timeOfDayInMinutes": 510,
        "kind": "InOut"
      }
    }
  ],
  "deltaLink": "/connector/protimeapi/api/v1/delta/clockings?deltaToken=eyJkZWx0YUlkIjo2NzcsInN0YXJ0aW5nQ3Vyc29yIjoxMjM0LCJ0aW1lU3RhbXAiOiIyMDI2LTAxLTE1VDEwOjA1OjAwLjAwMDAwMDBaIn0="
}

Store the new deltaLink from this response for your next poll. Each delta response replaces the previous deltaLink.

Caution

A delta expires after 72 hours. You must call the deltaLink at least once within that window, even if you expect no changes, to keep it alive. If the delta expires, the API returns 410 Gone and you must reinitialize from Step 4.

What you’ve accomplished

  • Authenticated with both read and write scopes for clockings
  • Created an InOut clocking via the API and confirmed it with a GET request
  • Initialized delta tracking to receive only incremental changes
  • Retrieved delta changes and received the created clocking as an InsertOrUpdate event
  • Learned how to chain deltaLink values for ongoing synchronization

Next steps