Integrations
PurpletGo connects to identity providers, HRIS platforms, and collaboration tools to automate access revocation during offboarding. This page covers the generic integration record API at /api/integrations - it's session-authenticated (your dashboard login, not an API key) and restricted to superadmin users for anything that creates, changes, or removes a connection.
Most providers are actually connected through a dedicated OAuth or connect flow rather than this generic endpoint - see Provider-specific connections below. The generic endpoints exist mainly for simple, config-only integrations and for reading back what's connected.
For webhook-based event delivery, see Webhooks.
Supported integration categories
| Category | Providers |
|---|---|
| Identity / SSO | Google Workspace, Okta, Azure AD, JumpCloud, OneLogin, Ping Identity |
| Source control | GitHub |
| HRIS | BambooHR, Workday, Rippling, ADP (via a generic HRIS connector) |
| Collaboration | Slack, Microsoft Teams |
| Calendar / scheduling | Google Calendar, Calendly |
| E-signature | DocuSign, Adobe Sign |
| SIEM | Splunk, Datadog |
| SMS | Twilio |
| IT ticketing | via a generic ticketing connector |
Integration record
Records are stored per-org, one per service_name. GET/list responses always strip secret fields from config before returning it:
{
"id": "3f1b2c4a-9e2b-4a3f-8c1d-2b7e9f0a1c3d",
"org_id": "...",
"service_name": "Okta",
"connection_status": true,
"config": { "domain": "acme.okta.com", "apiToken": "••••••••" },
"last_sync": "2025-06-26T06:00:00.000Z",
"created_at": "2025-01-10T09:00:00.000Z"
}There's no status enum (connected/degraded/pending), capabilities list, or health-check object - connection_status is a plain boolean, and whether the integration is actually working is inferred from last_sync and whether recent syncs have errored, not exposed as a structured field.
Endpoints
List integrations
GET /api/integrations
Returns every integration record configured for the org. Available to any authenticated user in the org.
Response 200 OK
[
{ "id": "3f1b2c4a-...", "service_name": "Okta", "connection_status": true, "config": { "domain": "acme.okta.com" }, "last_sync": "2025-06-26T06:00:00.000Z" },
{ "id": "9e1c2f3a-...", "service_name": "GitHub", "connection_status": true, "config": {}, "last_sync": "2025-06-26T06:00:00.000Z" }
]Create or update a generic integration
POST /api/integrations
Superadmin only. Upserts on (org_id, service_name) - posting the same service_name twice updates the existing record rather than creating a duplicate.
{
"service_name": "Splunk",
"connection_status": true,
"config": { "hecUrl": "https://splunk.acme.com:8088", "hecToken": "..." }
}Response 201 Created - the saved record, with config stripped from the response entirely (not just masked).
Update an integration
PATCH /api/integrations/:id
Superadmin only. Accepts config and/or connection_status; both are optional and merge-replace rather than partially patch nested config keys.
Disconnect an integration
DELETE /api/integrations/:id
Superadmin only. Deletes the record. For GitHub and Google Workspace, PurpletGo also makes a best-effort attempt to revoke the stored OAuth token upstream before deleting - if that call fails, the local disconnect still succeeds. Every disconnect is written to the audit log as integration_disconnected.
Provider-specific connections
These providers use their own OAuth or connect flow instead of the generic POST /api/integrations above - each writes into the same integration record once connected, but the handshake differs per provider:
| Provider | Flow |
|---|---|
| GitHub | GET /api/integrations/github/oauth/start → OAuth redirect → GET /api/integrations/github/oauth/callback |
| Google Workspace | GET /api/integrations/google-workspace/oauth/start → OAuth redirect → callback |
| Google Calendar | GET /api/integrations/google-calendar/oauth/start → OAuth redirect → callback |
| Okta | POST /api/integrations/okta/connect (requires SSO/directory-sync feature) |
| Azure AD | POST /api/integrations/azure-ad/connect, POST /api/integrations/azure-ad/sync |
| JumpCloud / OneLogin / Ping Identity | POST /api/integrations/{provider}/connect |
| Slack | POST /api/integrations/slack/connect |
| Microsoft Teams | POST /api/integrations/teams/connect, POST /api/integrations/teams/test |
| HRIS (BambooHR/Workday/Rippling/ADP) | POST /api/integrations/hris/connect, POST /api/integrations/hris/sync |
| IT ticketing | POST /api/integrations/it-tickets/connect, inbound POST /api/integrations/it-tickets/webhook |
| DocuSign / Adobe Sign | POST /api/integrations/docusign/connect, POST /api/integrations/adobe-sign/connect |
| Calendly | POST /api/integrations/calendly/connect |
| SIEM (Splunk/Datadog) | POST /api/integrations/siem/connect |
| SMS (Twilio) | POST /api/integrations/sms/connect |
| SCIM | POST /api/integrations/scim/setup, GET /api/integrations/scim/config - see SCIM 2.0 |
Each of these is gated behind its own plan feature and requires superadmin, and most are only reachable from the PurpletGo dashboard's OAuth redirect flow rather than being callable as a standalone API for third-party integrators.
There is no per-employee "trigger revocation on this integration" API and no async revocation job to poll. Access revocation happens as part of the offboarding workflow itself - when an offboarding reaches the relevant stage, PurpletGo acts on the connected integrations directly. If you need to know when that happened, check the audit log or subscribe to checklist.completed/audit.created via webhooks.
Related
- Offboarding Initiations - the workflow that actually triggers revocation
- Webhooks - event notifications for offboarding and checklist activity
- Audit Log - integration connect/disconnect and revocation history