Wire SCIM provisioning
Connect your identity provider to Orbit so team seats follow your directory: assign someone to the Orbit application in your IdP and they get an Orbit account with a role you choose; unassign them and access is revoked — no one on the team manually maintains the member list. This guide walks the full setup for Okta, Microsoft Entra ID (formerly Azure AD), and OneLogin, plus the attribute and group mapping you’ll configure once. For the endpoint spec itself, see the SCIM 2.0 provisioning reference.What SCIM does in Orbit
SCIM manages the lifecycle of dashboard users inside one organization:- Provision — a person added to the Orbit app in your IdP appears in your Orbit organization, ready to sign in.
- Update — name and email changes in the directory flow through on the next sync.
- Deactivate — unassigning a person revokes their access and every active session.
- Role — synced users land in a role you control: a default role plus an optional group-to-role map.
Prerequisites
Before you start:- An owner role in the Orbit organization (token generation and SCIM settings are owner-only).
- Your organization slug — find it under Settings → Organization in the dashboard. Every SCIM call is keyed by it.
- An IdP with a SCIM 2.0 client:
- Okta — an application with Provisioning enabled.
- Microsoft Entra ID — an enterprise application with Provisioning set to Automatic.
- OneLogin — an app connector with provisioning turned on.
- Any other RFC 7643/7644-compliant client works the same way.
- Open Settings → SCIM.
- Click Generate Bearer Token. The token is shown once — only its hash is stored — so copy it into a password manager or directly into the IdP. Rotating later invalidates the previous token immediately.
- Copy the fully qualified Base URL shown on the same page:
https://api.orbit.devotel.io/scim/v2/{orgSlug}. These endpoints live at the API root, not under/api/v1. - Enable SCIM in the settings panel, then use Test connection on the page before pointing the IdP at it — the test verifies the token exists, the Base URL resolves, and the discovery documents build. An organization cannot be flipped into the enabled state without a token.
Set up the IdP
Okta
- In the Okta admin console, open your Orbit application (or add one with SCIM 2.0 provisioning).
- Go to Provisioning → Configure Connection and set:
- SCIM connector base URL:
https://api.orbit.devotel.io/scim/v2/{orgSlug} - Authorization: HTTP Header → Bearer token, with the token from Orbit.
- SCIM connector base URL:
- Click Test Connector Configuration. When it passes, enable Create Users, Update User Attributes, and Deactivate Users under To App.
- Assign people or groups, then check the health response (below) or the Settings → SCIM activity panel to confirm the first sync landed.
Microsoft Entra ID
- In the Entra admin center, open your enterprise application → Provisioning, and set Provisioning Mode to Automatic.
- Under Admin Credentials, set Tenant URL to
https://api.orbit.devotel.io/scim/v2/{orgSlug}and Secret Token to your Bearer token. - Click Test Connection, save, then scope the users and groups you want to sync.
- Start provisioning and confirm the cycle on the Orbit side.
OneLogin and generic clients
In OneLogin, paste the Base URL as the SCIM connecter endpoint and the token as the Bearer credential on the app’s Configuration tab, then enable provisioning. Any SCIM 2.0 client follows the same three inputs: Base URL, Bearer token, “users and groups” as the synced resources. The health check and error behavior in this guide apply to all of them.Attribute mapping
Orbit accepts the standard SCIM user schema. Anything your IdP sends outside the mapped fields — locale, timezone, addresses, phone numbers, enterprise extensions — is accepted and ignored, so stock Okta and Entra attribute templates provision without trimming.
Leave the IdP’s default attribute mappings in place — they already send these
fields.
Group → role mapping
Roles in Orbit areowner, admin, developer, billing, and viewer.
Synced users get a role from two knobs you set under Settings → SCIM (or
with PATCH /api/v1/settings/scim):
defaultRole— the role for anyone provisioned without a group mapping. Start withviewer; it’s the least-privilege floor and every flow still works from there.groupMapping— a map of IdP group name → Orbit role, for example{ "Orbit Admins": "admin", "Orbit Support": "viewer" }. On each sync, group membership re-applies the mapped role.
groupMapping (id role:{role}), and PATCHing members
into an IdP group re-maps those users to the mapped role. There is no
free-standing team entity on the SCIM side — the group-to-role map is the
teams model for provisioning. Map IdP groups to the Orbit roles you actually
use, and treat every mapping as a privilege assignment: a mapping like
"Orbit Admins" → "owner" makes every member of that IdP group an owner on
the next sync.
A role ceiling bounds what provisioning can assign (default admin). A push
that targets a role above the ceiling is refused with
SCIM_ROLE_CEILING_EXCEEDED — nothing is assigned. Keep owner assignment
to the dashboard, and raise the ceiling in settings only if a group genuinely
needs the higher role.
Provisioning lifecycle
Create — the IdP POSTs a user; Orbit creates (or resurrects a previously deactivated account matching the email) at the resolved role. If your IdP retries a push after a partial failure, the create is keyed on email, so a repeat lands on the same account rather than duplicating it. Update — full-replace (PUT) and partial (PATCH) both work; Orbit applies only the mapped fields above. Okta tends to PUT the whole resource, Entra tends to PATCH — both are equivalent here. Deactivate — the IdP sendsactive: false. Orbit marks the account
inactive and the user stops signing in, but the row stays, so reactivating in
the IdP restores the same account with its history.
Deprovision — the IdP sends DELETE. This is the real removal: a cascade
revokes active sessions and API access, removes the member from the roster,
and transfers their owned assets to an owner. Re-running a DELETE after the
user is gone answers 404 — safe to retry from the IdP’s side.
Errors — failures surface in the SCIM error envelope
(urn:ietf:params:scim:api:messages:2.0:Error) with the HTTP status and, when
the spec defines one, a scimType. The failures you’ll actually see:
Rate limits and pagination
SCIM traffic is capped at 30 requests per minute per Bearer token — the token is the only credential on these endpoints, so the cap is keyed to it (not your IP; an IdP behind shared egress can’t starve another tenant). Okta and Entra sync cycles fall far below this. If you script provisioning yourself, page list calls withstartIndex/count (count max 500,
responses always include totalResults) instead of polling single records.
Troubleshooting IdP sync errors
When a push fails, work in this order:- Health first.
GET /api/v1/settings/scim/healthreports anauthenticationStatus(not_configured,no_requests_yet,authenticating,auth_failing), the timestamps of the last request and last failure, per-user provisioning counts, and a best-effortdetectedIdpfrom the caller’s User-Agent. The Settings → SCIM → Test connection result lands here too. - Read the code, not the status. Several failures share HTTP status
codes; the
scimTypeand the provisioning error code tell you which gate tripped it — Troubleshooting: authentication gates maps each SCIM code (includingSCIM_ROLE_CEILING_EXCEEDED) to its fix. - Match the IdP’s template to the mapping table above. Most first-sync
failures are a missing
userName/email attribute, not a connectivity problem. - Rotate the token when in doubt. If you can’t tell which token the IdP holds, rotate it in Orbit and paste the fresh value — the old one dies immediately, so no half-configured window.
See also
- SCIM 2.0 provisioning reference — endpoint table, token endpoint, and the health-check response fields.
- Authenticate Orbit API requests — API keys vs. session, and where SAML SSO signs users in.
- Troubleshooting: authentication gates — every SCIM rejection code and its fix.
- Settings API — read and patch SCIM settings, and manage team members directly from the API.