> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SCIM 2.0 provisioning (Okta, Entra ID, generic IdPs)

> Provision and deprovision Orbit dashboard users from your identity provider over SCIM 2.0 — base URL, Bearer token, supported resources, role mapping, health checks, and Okta / Microsoft Entra ID setup.

# SCIM 2.0 provisioning

SCIM 2.0 (RFC 7643/7644) is the standard protocol identity providers use to create, update, and deactivate users in a downstream application. Connect your IdP — Okta, Microsoft Entra ID (formerly Azure AD), OneLogin, or any SCIM 2.0 client — and team membership in Orbit follows your directory: add a person to the Orbit app in your IdP and they get an Orbit seat; remove them and access is revoked.

Use SCIM when you want the **lifecycle** of a user automated. It pairs with — but does not require — [SAML SSO](/authentication): SAML controls how users sign in, SCIM controls which users exist. Both are per-organization settings you opt into; neither is required to use Orbit, and SCIM stays off until an owner enables it.

## Base URL and organization slug

Every SCIM endpoint is keyed by your organization slug:

```
https://api.orbit.devotel.io/scim/v2/{orgSlug}
```

Find your slug under **Settings → Organization** in the dashboard. The same value is rendered for you as a fully qualified Base URL on **Settings → SCIM** — paste that into your IdP as-is. These endpoints live at the API root, **not** under `/api/v1`.

## Authentication

Your IdP authenticates with a Bearer token it sends on every request. Orbit answers with `application/scim+json` bodies and the SCIM error envelope (`urn:ietf:params:scim:api:messages:2.0:Error`), so IdPs can parse failure modes they expect.

Generate the token under **Settings → SCIM → Generate Bearer Token** (owner-only), or via the API:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/settings/scim/generate-token \
  -H "Authorization: Bearer <owner-session-token>"
```

The plaintext token is returned **once** — only its hash is stored afterwards — so copy it into your IdP immediately. Rotating the token invalidates the previous one, so update the IdP right away. A missing or wrong token gets a `401` with SCIM type `invalidCredentials`.

SCIM requests are rate-limited to 30 per minute per token. IdP syncs batch well under that; if you script provisioning yourself, page with `count` (max 500) rather than hammering the list endpoint.

## Supported resources

| Resource      | Operations                                                                                                                                                                                                                              |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Users**     | `GET /Users` (list, `filter`/`startIndex`/`count`), `POST /Users` (create), `GET /Users/{id}`, `PUT /Users/{id}` (full replace), `PATCH /Users/{id}` (partial update), `DELETE /Users/{id}` (deprovision — revokes the user's sessions) |
| **Groups**    | `GET /Groups` (list), `GET /Groups/{id}`, `PATCH /Groups/{id}` (rename, add/remove members)                                                                                                                                             |
| **Discovery** | `GET /ServiceProviderConfig`, `GET /ResourceTypes`, `GET /Schemas`                                                                                                                                                                      |

Deletions are safe to re-run: deprovisioning a user revokes their active sessions, and removing an AI agent identity suspends it rather than deleting its configuration.

User payloads accept the standard schema (`userName`, `name`, `displayName`, `emails`, `active`, `externalId`); extra attributes your IdP sends (locale, timezone, addresses) are accepted and ignored, so Okta and Entra payloads provision without attribute-trimming.

## Role mapping

Which Orbit role a synced user lands in is your configuration, set under **Settings → SCIM** or with `PATCH /api/v1/settings/scim`:

* `defaultRole` — the role for users provisioned without a group mapping (`owner`, `admin`, `developer`, `billing`, or `viewer`). `viewer` is the safe starting floor.
* `groupMapping` — a map of IdP group name → Orbit role, applied on each sync.

Treat the group mapping as a privilege vector: a mapping like `"Orbit Admins" → "owner"` makes every member of that IdP group an owner on next sync. Both settings are owner-only.

## Health and IdP detection

Check whether your IdP is actually talking to Orbit with:

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/settings/scim/health \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

The response reports an `authenticationStatus` (`not_configured`, `no_requests_yet`, `authenticating`, or `auth_failing`), the last request/success/failure timestamps, provisioning activity counts (users created, updated, deactivated, failed), and a best-effort `detectedIdp` inferred from the caller's User-Agent (Okta, Microsoft Entra ID, OneLogin, …). Run **Test connection** on the Settings → SCIM page before enabling provisioning — it verifies the token exists, the Base URL resolves, and the discovery documents build, and the result shows up as the last test on the health endpoint.

## Okta setup

1. In Okta, add an application with **SCIM 2.0** provisioning (or enable provisioning on your existing Orbit app).
2. Under **Provisioning → Configure Connection**, set the **SCIM connector base URL** to `https://api.orbit.devotel.io/scim/v2/{orgSlug}` and choose **HTTP Header** auth with the Bearer token from Orbit.
3. Test the connector configuration, then enable **Create Users**, **Update User Attributes**, and **Deactivate Users** under **To App**.
4. Assign people (or groups, if you push groups) and confirm the first sync on the health endpoint above.

## Microsoft Entra ID (Azure AD) setup

1. In Entra, create or open your enterprise application, and go to **Provisioning**.
2. Set **Provisioning Mode** to **Automatic**, then 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, and scope the users/groups you want to sync.
4. Start provisioning and verify with the health endpoint.

## Generic SCIM client

Any RFC 7643/7644-compliant client works. Create a user directly to verify the connection:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/scim/v2/{orgSlug}/Users \
  -H "Authorization: Bearer <scim-token>" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "ada@example.com",
    "name": { "givenName": "Ada", "familyName": "Lovelace" },
    "emails": [{ "value": "ada@example.com", "primary": true }],
    "active": true
  }'
```

A `201` returns the full User resource with its assigned `id`. A `400` with `invalidValue` means a required field is missing or malformed; `401` means the token; `404` means the slug.

## Scope and posture

SCIM provisioning is a tenant-owned control: you decide whether to use it, which IdP to trust, and which roles synced users receive. Orbit provides the endpoint and the audit trail — every IdP-driven create, update, and deprovision is recorded in your organization's audit log — but enabling SCIM is never a platform requirement, and organizations without an IdP can manage seats manually under **Settings → Team** indefinitely.

## See also

* [Authenticate Orbit API requests](/authentication) — SAML SSO setup and the SCIM token endpoints
* [SOC 2 Controls Mapping](/compliance/soc2-controls) — where provisioning and audit-log controls map to Trust Services Criteria
