HR Sources
An HR source is an authoritative system of record (Paycom, Gusto, ADP, Workday, Rippling,
BambooHR, …) that drives nexusID's joiner/mover/leaver (JML) lifecycle. nexusID pulls the employee
directory, upserts identities (matched by employeeId), and fires joiner/mover/leaver into
provisioning, deprovisioning, access reviews, and the audit chain.
Configure in the database (recommended)
HR sources are DB-configured through the admin integrations console — no environment variables
or redeploys. Each source is an Integration row of type HR_SOURCE:
- Admin → Integrations → New, type HR Source, pick the provider (Paycom / Gusto / ADP / Workday / Rippling / BambooHR).
- Fill in the provider's config form (rendered from the provider's own schema). Where a vendor supports more than one auth method, an Auth method selector shows only the chosen method's fields. Secrets are encrypted at rest (AES-256-GCM).
- Test connection, then activate.
The form, the auth methods, and the credential storage are all schema-driven and DB-backed — adding or editing a source never touches environment variables or requires a redeploy (binding engineering rule C-27: integrations are DB- and Admin-UI-configurable).
Auth methods per vendor
The form shows only the methods a vendor actually supports — OAuth2 is not forced where it doesn't apply:
| Vendor | Auth method(s) in the UI |
|---|---|
| BambooHR | API key |
| Paycom | SFTP (key/password) · REST API (SID + token) |
| Gusto | OAuth 2.0 (refresh token) |
| ADP | OAuth 2.0 (client credentials) + mutual-TLS |
| Workday | Integration System User (Basic) · OAuth 2.0 |
| Rippling | API key · OAuth 2.0 |
Under the hood, ProviderFactory.createProvider(integration) decrypts the config and initializes
the matching HrDirectoryProvider; a single scheduled sweep (HrSourceSyncService) syncs every
active HR_SOURCE integration. Adding a vendor is a new row, not a deployment.
HR_SOURCE integrations (DB, encrypted)
→ HrSourceSyncService (one sweep, all sources)
→ ProviderFactory.createProvider() → <Vendor>Provider.fetchRecords()
→ shared upsert (match by employeeId)
→ LifecycleEventService onJoiner/onMover/onLeaver
→ provisioning / deprovisioning + HR source precedence + workflows
Tune the sweep cadence with hr.sync.cron (default every 6h) — that's an operational schedule,
not per-source config; the sources and their credentials live in the DB.
How OAuth2 tokens are generated (no SSO)
HR-source auth is machine-to-machine — not org-IdP SSO. For the OAuth2 vendors you don't paste a short-lived bearer token; nexusID mints and refreshes it itself. On a provider's form, leave the static Bearer Token blank and fill the OAuth fields instead:
client_credentials(Workday API client, ADP, …): set the token URL, client ID, and client secret. nexusID exchanges them for an access token before each sync and caches it until just before expiry. No human involved.refresh_token(Gusto, Rippling — authorization-code vendors): an admin authorizes the app once against the vendor (not your org IdP) to obtain a refresh token; store it with the client ID/secret and nexusID exchanges it for access tokens forever after.
Long-lived API keys (BambooHR, Paycom, a Rippling API key) need no OAuth — just the key/secret. Tokens and secrets are encrypted at rest.
ADP mutual-TLS: ADP requires a client certificate on both its token endpoint and its data API.
Paste your PKCS#12 keystore as base64 (.p12/.pfx) plus its password into the ADP form — it's
stored encrypted in the DB (no filesystem path), and nexusID presents the client cert on every ADP
call.
Why DB config (and when to use env)
DB config is the friendly default: self-service in the UI, encrypted secrets, hot add/disable, no
redeploy. The legacy environment-variable connectors (PAYCOM_SYNC_*, GUSTO_SYNC_*,
ADP_SYNC_*, WORKDAY_SYNC_*) still exist and are off by default — useful for GitOps /
air-gapped deployments that deliberately keep secrets out of the database. Use whichever fits; for
most operators the admin console is the way.
Supported sources
| Source | Transport | Auth | Page |
|---|---|---|---|
| Paycom | SFTP CSV · REST API | SFTP key/pwd · API SID/token | Paycom |
| Gusto | REST API | OAuth2 (token minted by nexusID) | Gusto |
| ADP | REST API | OAuth2 client-credentials + mutual-TLS | ADP |
| Workday | RaaS report · RTS push | Basic (ISU) / OAuth2 | Workday |
| Rippling | REST API | API key / OAuth2 | Rippling |
| BambooHR | REST API | Basic (API key) | BambooHR |
Matching, precedence & write-back
- Match key:
employeeId(the source's stable id). New → joiner; changed → mover; terminated status → leaver. - Precedence: when several sources feed the same identity, HR Source Precedence decides which wins per attribute.
- Outbound write-back: Paycom (terminate/update) and Gusto (terminate) can push nexusID-originated changes back; see each page.