Authentication
The Staff & Go API is an OAuth 2.0 resource server. Your application authenticates as itself with the client credentials grant — there is no end-user login, no redirect, no refresh token.
Getting a token
Credentials are issued per environment by Staff & Go. Exchange them at the authorization server:
curl -X POST "https://<authorization-server-host>/realms/staffngo-partners/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET"
Send the token on every call:
Authorization: Bearer <access_token>
Mint a new token shortly before the current one expires. Tokens are cheap; a wave of retries triggered by simultaneous expiry is not, and it counts against your rate limit.
Scopes
Each endpoint declares the scopes it requires; the API reference lists them per operation.
| Scope | Grants |
|---|---|
external-api |
Base access to the API. |
partner:read |
Read your own partner profile. |
leaves:read |
Read leave data. |
leaves:write |
Create or modify leave data. |
payroll:read |
Read payroll data. |
payroll:trigger |
Trigger payroll distribution. |
referentials:read |
Read the referentials, platform-wide ones as well as the company's — see Discovery. |
audit-entries:read |
Read your own audit trail — see Audit trail. |
beta:access |
Call endpoints marked Beta — none today, see Lifecycle. |
Do not add a scope parameter to the token request. The scopes granted to your application are attached
to your credentials and enter the token without being asked for.
Naming them is in fact risky: the authorization server refuses the whole request as soon as one
named scope is no longer granted — invalid_scope, no token at all, and a message listing every scope
you asked for rather than the one that went away.
⚠️ This bites hardest in the API reference on this site. Its "Authorize" panel builds its scope list
from the published contract, which names every scope this API knows — including the field sub-scopes
(employments:read:compensation, leaves:read:reason, payroll:read:amounts). They are listed so you
can discover what releases a field, not because you hold them: a sub-scope is granted only on a
stated need, and leaves:read:reason covers health data under Article 9. Ticking everything there
gets you no token at all. Leave the selection empty, or tick only what you know was granted to you.
A token that lacks a required scope gets 403 with type = scopes/insufficient, and the detail names
the missing scope.
After any change to your scopes, request a new token. When the client company's administrator withdraws
one, the tokens already issued are disowned: they get a 401, not a 403, because they were signed under a
grant that is no longer yours. Waiting does not bring them back, and granting the scope again does not
revive them either — only a token minted after the change carries your current rights. If your calls start
returning 401 with no explanation, that is the first thing to try.
Confirming what your token carries
GET /api/v1/client/partner/profile returns the identity the API resolved: your partner id, the customer
tenant your calls act on, and the scopes actually present on the token. It is the fastest way to diagnose a
403. Version 2 of that endpoint adds the plan, the requester and the module states — see
Discovery.
Legacy tokens — deprecated
Integrations predating OAuth issue a BearerClient token from /api/v1/token. It still works, and it is
deprecated: new integrations must not use it.
It is not merely older — it behaves differently in ways that will not be carried forward:
- it is exempt from quota enforcement, so it gives no
RateLimitheaders and no back-pressure signal; - it is exempt from idempotency, so a replayed write is not deduplicated;
- it cannot carry scopes, so any endpoint requiring one refuses it with
403.
To migrate, request partner credentials from Staff & Go, swap the token acquisition for the client credentials call above, and keep the rest of your integration unchanged — the endpoints and their contracts are identical.
Keeping the secret safe
The client secret authenticates your application on its own. Keep it server-side, out of browsers, mobile apps, repositories and logs. If it leaks, ask Staff & Go to rotate it — a rotated secret invalidates the old one immediately.