points_manage, budget_read, surveys_manage, etc. — so a client only gets the permissions it actually needs. There’s no admin UI for client registration today; it’s configured via Empuls support. This page documents the model.
Before you start
- You must be a Super Admin to authorize new clients.
- Confirm with the third-party integration owner exactly which scopes they need; over-broad scopes are a common security finding in audits.
- For internal-only integrations, consider webhook & APIs instead — simpler, scoped at the event level.
How OAuth in Empuls works
1
Register a client
Provide a name, callback URL, and the allowed scopes. Empuls returns a client ID and a client secret.
2
Restrict client by company
Optionally limit the client to a specific company ID (multi-tenant scenarios) or set of company IDs.
3
User authorization flow
A user redirects from the client to Empuls’s
/authorize endpoint. Empuls authenticates the user, shows the requested scopes, and on consent issues an authorization code.4
Client exchanges code for tokens
The client’s backend exchanges the authorization code at
/token for an access token and refresh token.5
Client calls GraphQL
The access token is passed in the
Authorization: Bearer ... header. Scope enforcement happens server-side — calls outside the granted scopes are rejected.Scope catalog
A non-exhaustive list of scopes the API supports:
Empuls’s full scope list is available via the
oauth_scopes config — request it from Empuls support when registering.
Company OAuth tokens vs user OAuth tokens
Pick the right token type for the integration. Most HRIS-style integrations use company OAuth tokens.
Limited-access tokens
For sensitive operations — e.g., a one-time bulk import that needs admin scope — generate a limited-access token instead of granting permanent admin scope:- The client makes a request to the
generateLimitedAccessTokenmutation with the desired scopes. - Empuls returns a short-lived token (15 minutes default).
- The client uses the token for the operation, then it expires.
CSRF protection
All write mutations require a CSRF token. Clients fetch the CSRF token via a separate@csrf directive flow and pass it on every state-changing call. Empuls validates the CSRF on every mutation. Reads (queries) are CSRF-exempt.
Rate limiting
Per-IP rate limits apply to the GraphQL endpoint:- Default: 60 requests per minute per IP.
- Authenticated requests: 120 per minute per token.
- Limits configurable per-tenant via support.
Retry-After header.
Register a client
Until a self-service UI exists, register clients by contacting cs@xoxoday.com with:- Client name and description
- Callback URL(s)
- Required scopes (justification helpful)
- Company restriction (if applicable)
- Contact owner
Revoke a client
To revoke a client (e.g., the partner relationship ends or credentials leaked):- Contact Empuls support with the client ID.
- Empuls revokes the client immediately. All existing tokens become invalid; any in-flight session ends.
Limits and gotchas
- Client secrets cannot be retrieved after registration. If lost, rotate by contacting support.
- Refresh tokens are single-use — using a refresh token returns a new access + new refresh token. Reuse of an already-used refresh token is rejected.
- Scope grants are sticky — once a user consents to a scope, subsequent token issuances inherit the consent. Revoke and re-consent to change scopes.
- The OAuth surface is part of the auth microservice (
etpauth). Service availability is independent of Empuls’s main app.
Related
Webhook & APIs
Simpler event-driven integration alternative.
SSO overview
User-facing identity federation (different from API access).
Access control
In-Empuls RBAC, which OAuth scopes also respect.