SCIM provisioning
SCIM provisioning makes your identity provider the source of truth for who exists in a LedgerBee company and what they can do. The IdP pushes users and groups over SCIM 2.0; each group's effect is configured in LedgerBee under Settings → Access → User provisioning and is never writable over the protocol.
A synced user is an identity with no rights of its own. Group membership decides what it materializes:
- Employee record — the person appears in the employee directory and flows into payroll where that integration is connected.
- App access — the person gets a LedgerBee account, can sign in, and holds the roles and admin rights their groups grant.
A group can do either, both, or neither. A user provisioned only through an app-access group never becomes an employee, and an employee never requires app access.
Endpoint and authentication
The SCIM 2.0 base URL is https://api.ledgerbee.com/api/v1/scim. Every request
carries the provisioning token as a bearer token:
Code
The token identifies the company, so no company identifier appears in any request path or body.
Generate it under Settings → Access → User provisioning. It is displayed
once. The Provisioning status toggle suspends provisioning while keeping the
token valid; every request returns 403 while it is off. Revoking the token
invalidates it permanently.
These endpoints implement a protocol rather than the REST API, so they are not part of the generated API Reference. The tables below are the contract.
Supported operations
| Resource | Operations |
|---|---|
| Users | POST /Users, GET /Users, GET /Users/{id}, PUT /Users/{id}, PATCH /Users/{id}, DELETE /Users/{id} |
| Groups | POST /Groups, GET /Groups, GET /Groups/{id}, PUT /Groups/{id}, PATCH /Groups/{id}, DELETE /Groups/{id} |
| Discovery | GET /ServiceProviderConfig, GET /ResourceTypes, GET /Schemas, GET /Schemas/{id} |
Support matrix
| Capability | Supported | Detail |
|---|---|---|
PATCH | Yes | Path-based and pathless replace forms |
| Filtering | Partial | eq only, on userName and externalId for Users, displayName and externalId for Groups |
| Pagination | Yes | startIndex and count; count is capped at 200 per page |
| Bulk operations | No | Send individual requests |
| Sorting | No | |
| ETag | No | |
| Password sync | No | A password is never accepted over SCIM |
Group-driven provisioning
Groups pushed by the IdP appear under Provisioned groups. Opening a group exposes four settings:
| Setting | Effect on members |
|---|---|
| Provision employees | An employee record is created. Leaving the group never removes it. |
| Grant app access | A LedgerBee account is created. How the member signs in is governed by your SSO enforcement settings, not by provisioning. |
| Roles | The member holds the permissions of the selected roles. |
| Grant admin | The member is an administrator of the company. |
App access needs no single sign-on connection. Provisioning decides who has an account and what it can reach; how the member signs in — password, passkey, or single sign-on — is governed separately by SSO enforcement on their email domain. A provisioned member on an unregistered domain can set a password through the ordinary reset flow and sign in with it.
Removing a member from the group, or the IdP marking them inactive, withdraws the access that group granted.
Provisioning one person
Group membership is not the only source. Each synced user has its own app-access and employee settings, edited by opening the user in the Users list. They are additive with whatever the person's groups already grant, so a member who is an employee through a group can be given app access without that group conferring it on everyone else, and a directory that sends no groups at all can still provision individuals.
Because the two sources are independent, clearing a per-user setting withdraws access only when no group still grants it.
Roles and admin are not set here. Once a person is provisioned they appear in the Users list, where permissions are assigned by hand; those assignments live apart from group-derived grants and survive every later sync.
Grants combine additively across groups: a member of two app-access groups holds the union of both role sets, and is an admin when either group grants admin. Group-derived grants are tracked separately from roles assigned by hand, so removing someone from a group withdraws exactly what that group gave and leaves manual assignments untouched. The Users list marks group-derived roles and flags accounts that SCIM created.
Losing membership of every app-access group deactivates the SCIM-created account and ends its live sessions within the access-token lifetime. An account created by invitation keeps its access and loses only the group-derived grants.
Employee records are retained
A group change never removes an employee record, because bookkeeping records reference employees. An employee is deactivated only when the IdP marks the user inactive.
Only Provision employees creates one. A user whose groups carry Provision app access alone receives an app account and no employee record.
Provisioning lifecycle
| Phase | What happens |
|---|---|
| Create | POST /Users stores the identity. Employee and app-access projections are applied from current group membership. |
| Update | PUT or PATCH /Users/{id} updates the identity, mirrors changed attributes onto a linked employee record, and re-applies projections. |
| Group change | A membership PATCH on /Groups/{id} re-applies projections for every affected member. |
| Deactivate | active: false or DELETE /Users/{id} deactivates the account, ends live sessions, and marks a linked employee inactive. The record is retained. |
Microsoft Entra ID
- Open the LedgerBee enterprise application in the Microsoft Entra admin center. Create one through Enterprise applications → New application → Create your own application if none exists.
- Open Provisioning and select Automatic.
- Set Tenant URL to
https://api.ledgerbee.com/api/v1/scimand Secret Token to the generated token. - Select Test Connection, then Save.
- Keep the default attribute mappings. LedgerBee reads
userName,active,name.givenName,name.familyName,title,externalId, and the work entries ofemails,phoneNumbers, andaddresses. - Enable group provisioning, then assign the groups to sync under Users and groups.
- Set Provisioning Status to On.
Entra provisions on a fixed cycle of roughly 40 minutes. Provision on demand applies a single user immediately. Repeated failures quarantine the provisioning job, which is why a token change should use rotation with a grace window rather than a revoke.
Map objectId to externalId for Microsoft sign-in
LedgerBee stores a provisioned user's externalId as their Microsoft object id
when it creates the account, which is what lets them sign in with Microsoft
without a separate invitation. That only works when externalId carries the
object id: Entra's default mapping sends mailNickname, which is not an
object id, and LedgerBee ignores it rather than storing a value that cannot
match a sign-in.
In Provisioning → Mappings → Provision Microsoft Entra ID Users, edit the
attribute whose customappsso target is externalId and set its source to
objectId. Users provisioned before the change keep no object id — they link on
their first Microsoft sign-in instead.
Okta
- Open the LedgerBee application in the Okta admin console, select Provisioning, then Configure API Integration.
- Enable Enable API integration, set the base URL to
https://api.ledgerbee.com/api/v1/scim, and paste the token as the API token. - Select Test API Credentials, then Save.
- Under To App, enable Create Users, Update User Attributes, and Deactivate Users.
- Set the unique identifier field for users to
userName. Okta resolves existing users withGET /Users?filter=userName eq "...". - Push each group to sync from the Push Groups tab. Assigning a group to the application does not push it.
Okta imports users in pages of 100. Unlinking a pushed group offers to delete it in the target application, which removes the group from LedgerBee and withdraws the app access it granted.
Deprovisioning
| Event in the IdP | Effect in LedgerBee |
|---|---|
User deactivated (active: false) | Account deactivated, live sessions ended, linked employee marked inactive |
| User deleted from the application | Treated as deactivation; records are retained, never hard-deleted |
| Removed from every app-access group | SCIM-created account deactivated; invited accounts keep access and lose group-derived grants |
| Removed from an employee-flagged group | No effect on the employee record |
| Group deleted | Members lose the app access and roles that group granted |
Errors & failure states
Errors use the SCIM error schema, with the code below in detail.
| Condition | What you observe | Fix |
|---|---|---|
| Missing or wrong token | 401 SCIM_INVALID_TOKEN | Re-copy the token, or generate a new one |
| Provisioning toggled off | 403 SCIM_CONNECTION_DISABLED | Enable Provisioning status |
| Unsupported filter attribute or operator | 400 SCIM_INVALID_FILTER | Use eq on a supported attribute |
| Malformed patch body or unsupported operation | 400 SCIM_INVALID_PATCH | Correct the operation shape |
| Unknown user id | 404 SCIM_USER_NOT_FOUND | Re-resolve the user by externalId filter |
| Unknown group id | 404 SCIM_GROUP_NOT_FOUND | Re-push the group |
| Unknown schema URN | 404 SCIM_SCHEMA_NOT_FOUND | Request a URN listed by GET /Schemas |
Duplicate externalId or work email | 409 SCIM_DUPLICATE_USER | Resolve the existing user and update it |
Duplicate group externalId | 409 SCIM_DUPLICATE_GROUP | Resolve the existing group and update it |
Troubleshooting
Test Connection fails. Confirm the base URL ends in /api/v1/scim, the
token was pasted whole, and Provisioning status is enabled.
Users sync but no groups appear. In Entra, group provisioning must be enabled and the groups assigned to the application. In Okta, groups must be pushed from the Push Groups tab.
A member of the right group has no access. Confirm the group has Grant app access enabled. A membership pushed before the user existed in LedgerBee is skipped, so re-push that group.
A user cannot sign in with Microsoft. The Microsoft identity is linked only on accounts SCIM creates. An account that already existed connects Microsoft sign-in once from its own profile.
SSO enforcement
Provisioning users decides who has an account; SSO enforcement decides how they are allowed to sign in. It is set per verified email domain under Settings → Workflows & access → Single sign-on, and a member on a domain you have not registered keeps every sign-in method — see SSO enforcement.
Organizations
A company that belongs to an organization can also be provisioned by the organization itself. The organization holds its own SCIM connections — one per directory it federates, up to ten — under System → Organization → Provisioning, and every connection pushes to the same base URL with its own bearer token.
Users and groups pushed on an organization connection land in a pool shared across the organization rather than in one company. What a group provisions is decided per member company in the group's assignment matrix: for each company, whether members get app access, which of that company's roles they receive, whether they are admins, and whether an employee record is created. One group can grant app access in two companies while creating employees in only one of them.
The protocol behaves exactly as it does for a single company, with these differences:
| Aspect | Single company | Organization |
|---|---|---|
| Connections | One; generating a new token replaces it | Up to ten, each independent |
| Pool | The company's own | Shared across the organization, isolated per connection |
| Group effect | Per-group settings | Per-group-and-company assignment matrix |
| Employee records | Created in the company | Created in each company the matrix assigns |
| Deleting the connection | Token stops authenticating; synced records remain | Also deprovisions the users and groups that connection created |
Connections are isolated: a group pushed on one connection cannot be read or modified with another connection's token, and identical users pushed on two connections do not conflict.
A company and its organization can provision the same person at once. Access is the union of both sources — deactivating the person in one directory removes only what that directory granted — and an employee record is never duplicated: the first source to create it owns it, and the other links to the same record.
When a company leaves the organization, the organization's assignments into it are severed. Accounts the organization provisioned there stay active as ordinary invited users; they are no longer directory-managed.