Skip to main content

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.
SCIM changes membership, not login. It pairs with SAML single sign-on — SAML controls how users sign in, SCIM controls which users exist — and most enterprise IdPs expect both. Both are per-organization, tenant-owned controls: nothing enables SCIM except an owner in your workspace, an organization without an IdP can manage seats manually forever, and Orbit does not require SCIM for any compliance certification — it’s your provisioning option, not a mandate.

Prerequisites

Before you start:
  1. An owner role in the Orbit organization (token generation and SCIM settings are owner-only).
  2. Your organization slug — find it under Settings → Organization in the dashboard. Every SCIM call is keyed by it.
  3. 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.
Then, in Orbit:
  1. Open Settings → SCIM.
  2. 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.
  3. 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.
  4. 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

  1. In the Okta admin console, open your Orbit application (or add one with SCIM 2.0 provisioning).
  2. 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.
  3. Click Test Connector Configuration. When it passes, enable Create Users, Update User Attributes, and Deactivate Users under To App.
  4. 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

  1. In the Entra admin center, open your enterprise application → Provisioning, and set Provisioning Mode to Automatic.
  2. Under Admin Credentials, set Tenant URL to https://api.orbit.devotel.io/scim/v2/{orgSlug} and Secret Token to your Bearer token.
  3. Click Test Connection, save, then scope the users and groups you want to sync.
  4. 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 are owner, 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 with viewer; 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.
Groups in Orbit are synthesized from this map: the IdP sees one group per role referenced in 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 sends active: 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 with startIndex/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:
  1. Health first. GET /api/v1/settings/scim/health reports an authenticationStatus (not_configured, no_requests_yet, authenticating, auth_failing), the timestamps of the last request and last failure, per-user provisioning counts, and a best-effort detectedIdp from the caller’s User-Agent. The Settings → SCIM → Test connection result lands here too.
  2. Read the code, not the status. Several failures share HTTP status codes; the scimType and the provisioning error code tell you which gate tripped it — Troubleshooting: authentication gates maps each SCIM code (including SCIM_ROLE_CEILING_EXCEEDED) to its fix.
  3. Match the IdP’s template to the mapping table above. Most first-sync failures are a missing userName/email attribute, not a connectivity problem.
  4. 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