Authenticate

Authenticate

This guide walks you through obtaining an OAuth2 access token and using it to authorize requests against the Protime API.

Before you begin

  • Obtain your client_id and client_secret from Protime.
  • Know your tenant name (the subdomain of your myProtime environment, e.g. acme from https://acme.myprotime.eu).
  • Know your environment URL: myprotime.eu (production) or myprotimesandbox.eu (sandbox).
  • Identify the OAuth2 scopes your integration requires, and confirm which scopes your credentials are entitled to. See OAuth2 scope model for background.
Sending an explicit scope parameter is strongly recommended. It is not required, but a token carrying every entitled scope grows large and violates least-privilege principles.
All HTTP examples in these docs use standard request format. The full URL is https://{Host}{path} – for example, Host: acme.myprotime.eu with path /connector/protimeapi/api/v1/clockings produces https://acme.myprotime.eu/connector/protimeapi/api/v1/clockings.

OAuth2 client credentials flow

  sequenceDiagram
    participant Client as Your Application
    participant Auth as Authentication Server
    participant API as Protime API

    Client->>Auth: POST /connect/token
    Note over Client,Auth: grant_type=client_credentials<br/>client_id=xxx<br/>client_secret=xxx<br/>scope=xxx
    Auth-->>Auth: Validate credentials
    Auth-->>Client: Access Token (JWT)<br/>expires_in: XXXX seconds
    
    Client->>API: API Request
    Note over Client,API: Authorization: Bearer {token}
    API-->>API: Validate token
    API-->>Client: API Response (200 OK)
    
    Note over Client,API: Token valid for XX minutes

Get an access token

Request an access token from the token endpoint:

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

Host: authentication.<environmentURL>
Content-Type: application/x-www-form-urlencoded

Include the following form fields in the request body:

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

A successful response returns the token and its lifetime:

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

The expires_in value is in seconds. Tokens are issued per tenant.

Use the access token

Set the Authorization header on every API request:

GET /connector/protimeapi/api/v1/clockings?filter=person%20in%20(1,2,3) HTTP/1.1
Host: <tenant>.myprotime.eu
Authorization: Bearer eyJ...Uc
User-Agent: YourService/v1 (YourCompany)

Best practices

Reuse tokens

Reuse the same token for multiple requests instead of requesting a new token per call. Generating a token on every request may trigger rate limiting.

Fetch a new token just before the current one expires. This avoids failed requests caused by presenting an expired token.

If you receive a 401 Unauthorized response, your token has most likely expired. Request a fresh token and retry. If a fresh token is rejected as well, see Troubleshoot token requests.

Narrow your scopes

Request only the scopes your integration actually needs.

scope=connector-protimeapi-clockings.read connector-protimeapi-clockings.write

If your integration needs access to many collections and your credentials are entitled to them, use the general scopes connector-protimeapi-all.read and connector-protimeapi-all.write instead of listing every per-collection scope. See the OAuth2 scope model for details.

The general scopes are not available to every client. Credentials issued with a limited scope set – typical for third-party integrations – are not entitled to connector-protimeapi-all.read / connector-protimeapi-all.write and must list their per-collection scopes explicitly.

Available scopes are listed per endpoint in the Swagger UI.

Troubleshoot token requests

Response Meaning Resolution
400 Bad Requestinvalid_scope The request asked for at least one scope the client credentials are not entitled to, or a scope name is misspelled. Compare the requested scopes against the scopes your credentials were issued with, and check the spelling against the scope reference. Ask the issuer of your credentials which scopes they carry.
400 Bad Requestinvalid_client The client_id / client_secret combination is wrong, or the credentials belong to another tenant. Verify the credentials and the tenant in the token URL.
401 Unauthorized on an API call The token is missing, expired, invalid, or does not carry the scope the endpoint requires. Request a fresh token. If it still fails, add the endpoint’s scope to the token request – if your credentials are entitled to it.
403 Forbidden on an API call The token is valid but access to the resource is not granted. Check the scope the endpoint documents and the tenant the token was issued for.
invalid_scope rejects the whole token request. No token is issued, not even for the scopes that were valid. Remove the unentitled scope and request again.

Related