Scopes#

Every operation requires exactly one scope, named <resource>.<action>, for example:

shifts.read        locations.write        timesheets.read
  • GET requires .read.

  • POST, PATCH, DELETE require .write.

  • Write implies read — shifts.write also satisfies shifts.read, so you never need to request both.

Every operation in the API Reference declares the exact scope it requires, right on the operation. That requirement is derived from the same value the server’s permission check reads, so what is documented and what is enforced cannot drift apart.

Asking for the right ones#

Scopes are granted per integration client when we register it, so ask for what the integration actually does and nothing more. A payroll export that reads hours gets timesheets.read and nothing else.

A typo is caught at registration, not at runtime: shift.read is refused with a suggestion rather than registering a client that fails on every call.

To add a scope later, contact support — it does not require new credentials.

When a scope is missing#

A call with a valid token but without the required grant is:

{
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "…",
    "details": []
  }
}

with status 403. That is distinct from a 401 (the token itself is bad — see Authentication) and from a 404, which is also what you get for a record outside your company, so that existence never leaks.