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.
General scopes
While per-collection scopes provide fine-grained control, some integrations need broad access across many or all collections. For these cases, the API provides two general scopes:
connector-protimeapi-all.read— accepted by any endpoint that requires a.readscope.connector-protimeapi-all.write— accepted by any endpoint that requires a.writescope.
The authorization layer evaluates general scopes alongside per-collection scopes. When a request reaches an endpoint requiring connector-protimeapi-clockings.read, the API accepts either that specific scope or connector-protimeapi-all.read. This evaluation happens transparently — the integration does not need to change how it constructs requests.
General scopes trade granularity for convenience. They simplify token management when an integration legitimately needs access to many collections, but they reduce the blast radius benefit of least-privilege scoping. Use per-collection scopes when the integration only reads or writes a small number of collections.
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