OAuth2 scope model
Why scopes matter
When an external system authenticates with the Protime API, it receives a token that grants access to API resources. Without scopes, that token would be an all-or-nothing key: either full access to every collection and operation, or no access at all. This creates unnecessary risk – a payroll export service that only needs to read clockings should not hold a token capable of deleting activity definitions.
The OAuth2 scope model solves this by allowing integrators to request only the permissions they need. Each scope grants access to a specific collection and operation type, enabling fine-grained authorization that follows the principle of least privilege.
Scope naming convention
Every scope in the Protime API follows a predictable naming pattern:
connector-protimeapi-<collection>.<permission>Where:
<collection>is the kebab-cased name of the API collection (for example,clockings,activity-definitions,people-historical-data).<permission>is either.reador.write.
Permission types
| Permission | Grants access to | HTTP methods |
|---|---|---|
.read |
Retrieving resources from the collection | GET |
.write |
Creating, updating, and deleting resources | POST, PUT, DELETE |
Not every collection exposes both permission types. Many collections are read-only and define only a .read scope. For example, the absences collection has connector-protimeapi-absences.read but no corresponding .write scope. The Authentication reference lists which scopes exist for each collection.
A scope is per-collection, not per-endpoint. Holding connector-protimeapi-clockings.read grants access to all GET endpoints under the clockings collection – single resource, list, filtered list, delta, and webhooks for that collection.
Examples
| Scope | Grants |
|---|---|
connector-protimeapi-clockings.read |
Read clockings (including delta and webhook reads) |
connector-protimeapi-clockings.write |
Create clockings |
connector-protimeapi-activity-definitions.read |
Read activity definitions |
connector-protimeapi-people-historical-data.read |
Read historical field data for people |
connector-protimeapi-webhooks.write |
Create and delete webhook subscriptions |
Default behavior
When no scope parameter is included in the token request, the authorization server grants all available scopes that the client credentials are entitled to. While this simplifies initial development, it is not recommended for production use because it violates least-privilege principles and increases the blast radius if credentials are compromised.
Design principles
The scope model reflects several security design principles:
- Least privilege. Because each scope targets a single collection and operation type, an integration can obtain only the access it requires. A service that exports clockings holds
connector-protimeapi-clockings.readand nothing else, reducing the blast radius if its credentials are compromised. - Read/write separation. Separating read and write permissions allows an integration to use distinct tokens for retrieval and mutation paths, limiting the damage any single token can cause.
- Credential isolation. When multiple services integrate with the same tenant, each service can have its own client credentials with a tailored scope set. This prevents one service’s compromise from affecting another’s access.
Scope reference
For the complete list of all available scopes grouped by domain, see the Authentication reference.
How scopes are requested
Scopes are provided as a space-separated string in the scope field of a token request. The authorization server validates the requested scopes against the client’s entitlements and returns the granted set in the token response, making it explicit which permissions the token carries. For the mechanics of constructing a token request with specific scopes, see the Authenticate guide.
Further reading
- Authenticate – obtaining access tokens with specific scopes
- Authentication reference – token endpoint specification, OIDC discovery, and scope format details