Skip to content
Documentation

SCIM endpoint: inbound provisioning from HR

Inbound provisioning means another system pushes people and groups into SSOGEN instead of an administrator typing them in. SSOGEN offers a SCIM endpoint for this. The standard it follows is SCIM 2.0 (System for Cross-domain Identity Management), a plain web interface that HR systems and identity providers already know how to call. When a new hire is added in your HR system, they appear in SSOGEN. When their name changes, SSOGEN is updated. When they leave, their account is switched off.

This guide covers creating the access token in the console, the address and requests the other system uses, how to read the people it creates, what deprovisioning does, the errors you can see, and a worked example for Acme Corp.

  • A signed-in administrator with the role above.
  • An HR system or identity provider that can act as a SCIM 2.0 client: it must be able to call a SCIM base URL with a bearer token. Not every HR product can; check its documentation for “SCIM provisioning” or “outbound SCIM”.
  • The address of your SSOGEN installation as people reach it (in this guide, https://sso.acme.example).
  1. Sign in to the Admin Console.
  2. In the left menu open Provisioning and choose Inbound. The page title is Inbound provisioning: “Let another system manage people here over SCIM.” (If you cannot see Provisioning, your role cannot read the directory.)
The Inbound provisioning page with nothing configured: the SCIM base URL, the Add a client form and the empty list

The page has three sections:

Section What it shows
Where to point it The SCIM base URL to give to the other system, with a copy button.
Add a client A Name field and a Create button, under the text “One per system that provisions here, so that one can be stopped without stopping the others.”
Clients One row per client, or Nothing is provisioning into this directory (“Name a client and select Create. The token is shown once.”) when there are none.

A client is one system that provisions into SSOGEN, with its own token. Create one client per system, so you can stop one without stopping the others.

Under Where to point it, the SCIM base URL field shows the address, for example:

https://sso.acme.example/scim

Click the copy button beside the field (its label is Copy SCIM base URL). The address always uses your installation’s own public address. It has no version number in it: always /scim.

If the field shows Loading the address… and never fills in, the console could not work out your installation’s public address; ask whoever installed SSOGEN to check it.

  1. Under Add a client, type a Name. Use something that says which system it is, for example Acme HR (Workday). The name can be up to 128 characters.
  2. Choose Create. The button stays disabled until you have typed a name.
The Add a client form filled in with the name Acme HR (Workday)

After a moment the page shows:

  • a green message: “Acme HR (Workday)” can now provision into this directory.
  • a Token field with a copy button, holding a long value that starts with ssogen_scim_;
  • a yellow warning: Copy this now; it cannot be shown again. If lost, create another client and revoke this one.
  • a button I have copied it.
The token shown once, with the warning that it cannot be shown again
  1. Copy the token into the other system’s configuration (or a password manager) now.
  2. Choose I have copied it. The token disappears and cannot be displayed again.

If you close the page before copying it, nothing is lost except the token: create another client and revoke the first (see Rotate or revoke a token).

After creating the client, the Clients table shows:

Column Meaning
Name The name you typed.
Status active while the token works, revoked after you revoke it.
Created When the client was created (UTC).
Last used When the other system last presented the token. A dash (—) means it has never been used.
(actions) A Revoke button on active clients.
The Clients list with Acme HR (Workday), status active, last used a dash

Last used is the column to read before you revoke anything: a time from today means a live integration that will stop.

There is no “regenerate” button, and a token cannot be edited. To rotate (replace) a token:

  1. Create a new client with a name such as Acme HR (Workday) 2026-11. Copy its token.
  2. Put the new token into the other system and confirm it works (the new client’s Last used shows a time).
  3. On the old client’s row, choose Revoke.

To revoke a token:

  1. On the client’s row choose Revoke. A dialog asks Revoke Acme HR (Workday)? and says: “The token stops working now and cannot be restored. The client fails without notice.”
  2. Choose Revoke to confirm, or Cancel to keep it.
The revoke confirmation dialog

The row’s Status changes to revoked and the Revoke button goes away. The other system’s next request is refused with 401 (see Errors you can see). People already created stay as they are.

All addresses are relative to the base URL, for example https://sso.acme.example/scim.

Method and path What it does
GET /ServiceProviderConfig, GET /ResourceTypes, GET /Schemas, GET /Schemas/{id} Tell the client what SSOGEN supports. Many clients call these when you save their configuration.
GET /Users, GET /Users/{id} List or read people.
POST /Users Create a person.
PUT /Users/{id} Replace a person’s details.
PATCH /Users/{id} Change some details, including active.
DELETE /Users/{id} Archive a person.
GET /Groups, GET /Groups/{id} List or read groups.
POST /Groups Create a group, optionally with members.
PUT /Groups/{id} Set the group’s members to exactly the list sent.
PATCH /Groups/{id} Add, replace or remove members.
DELETE /Groups/{id} Delete a group.

Every request carries the header Authorization: Bearer <token>. Requests with a body use the content type application/scim+json (application/json is also accepted). Answers are application/scim+json.

SSOGEN states plainly what it does not support: bulk operations, sorting, entity tags and password changes (ServiceProviderConfig reports each as unsupported). PATCH and filtering are supported. A page of results is at most 200 people.

User

Attribute Notes
userName Required. The person’s sign-in name; must be unique.
externalId Optional. Your HR system’s own identifier for the person; must be unique if sent.
name.givenName, name.familyName Optional.
displayName Optional.
emails Optional. The primary address (or the first one) is stored as the person’s email.
active Optional. Defaults to true on create.

Any other attribute you send (for example department or title) is accepted and ignored: SSOGEN does not store it, and does not offer it for mapping.

SCIM never carries a password. A person created by SCIM has no password from SCIM. See How provisioned people sign in.

Group: displayName (required, unique), externalId (optional), members (each member is the SSOGEN id of a person).

GET /Users and GET /Groups accept filter=<attribute> eq "<value>", and nothing else. The operator must be eq, the value must be in double quotes, and the filter can be at most 512 characters. Attribute names are not case-sensitive.

Resource Attributes you can filter on
Users userName, externalId, emails.value, displayName
Groups displayName, externalId

A filtered read answers with a list of zero or one resource. This is the check an HR system makes before it creates someone.

Without a filter, GET /Users returns every person in SSOGEN, not only those this client created. Use startIndex (starting at 1) and count (default 100, at most 200) to page.

PATCH carries an Operations array of up to 200 operations. Each has op (add, replace or remove, in any letter case), an optional path and a value. With no path, the value is an object of attributes to change.

Path Effect on a user
active true or false (or the text "True" / "False"). A remove counts as false.
displayName Set or clear.
name.givenName, name.familyName Set or clear.
emails or emails.value Set or clear the email.

Other paths are ignored, so a stray attribute never stops a deactivation from working. On a group, only members is acted on:

  • add adds the listed people;
  • replace makes the list exactly the group’s members;
  • remove with the path members[value eq "<id>"] removes that one person.

A remove with no path is refused. Only [value eq "..."] is accepted as a filter inside a path.

The examples use $TOKEN for the token and https://sso.acme.example/scim as the base. Ids shown (3f1c0b2e-…) are examples; your own are returned by SSOGEN.

curl -s -X POST https://sso.acme.example/scim/Users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "maria.lopez",
"externalId": "E-10442",
"name": { "givenName": "Maria", "familyName": "Lopez" },
"displayName": "Maria Lopez",
"emails": [ { "value": "maria.lopez@acme.example", "type": "work", "primary": true } ],
"active": true
}'

Answer: 201 Created, a Location header, and the person as stored, including the id to use from now on:

{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "3f1c0b2e-1111-4a5b-9c3d-000000000001",
"externalId": "E-10442",
"userName": "maria.lopez",
"name": { "givenName": "Maria", "familyName": "Lopez", "formatted": "Maria Lopez" },
"displayName": "Maria Lopez",
"emails": [ { "value": "maria.lopez@acme.example", "type": "work", "primary": true } ],
"active": true,
"meta": { "resourceType": "User", "location": "/scim/Users/3f1c0b2e-1111-4a5b-9c3d-000000000001" }
}

(meta also carries created, lastModified and version.) Sending the same userName or externalId again answers 409 (see Errors you can see).

curl -s -G https://sso.acme.example/scim/Users \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode 'filter=userName eq "maria.lopez"'

The answer is a list with totalResults of 1 (found) or 0 (not found).

Change only what changed, with PATCH:

curl -s -X PATCH https://sso.acme.example/scim/Users/3f1c0b2e-1111-4a5b-9c3d-000000000001 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "name.familyName", "value": "Lopez-Ortiz" },
{ "op": "replace", "path": "displayName", "value": "Maria Lopez-Ortiz" }
]
}'

Answer: 200 OK with the updated person. A PUT to the same address replaces displayName, name, emails and active with what you send. A PUT cannot change userName or externalId, and a PUT that omits active means active: true.

curl -s -X PATCH https://sso.acme.example/scim/Users/3f1c0b2e-1111-4a5b-9c3d-000000000001 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [ { "op": "replace", "path": "active", "value": false } ]
}'

Answer: 200 OK with "active": false. To switch the person back on, send true.

curl -s -X POST https://sso.acme.example/scim/Groups \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"displayName": "Finance",
"externalId": "DEPT-FIN",
"members": [ { "value": "3f1c0b2e-1111-4a5b-9c3d-000000000001" } ]
}'

Answer: 201 Created with the group, its id and its members. A member value that is not an id SSOGEN issued is dropped without an error, so check the members in the answer.

Add or remove one member later:

# add
curl -s -X PATCH https://sso.acme.example/scim/Groups/<group-id> \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/scim+json" \
-d '{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations":[{"op":"add","path":"members","value":[{"value":"<user-id>"}]}]}'
# remove
curl -s -X PATCH https://sso.acme.example/scim/Groups/<group-id> \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/scim+json" \
-d '{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations":[{"op":"remove","path":"members[value eq \"<user-id>\"]"}]}'

Open Identity → Users. A person created over SCIM is listed like any other, with the Source column reading Provisioned from client name, for example Provisioned from Acme HR (Workday). A person created by hand reads Created here.

The Users list showing Maria Lopez with Source Provisioned from Acme HR (Workday)

If the client’s name cannot be found, the source reads Provisioned over SCIM. Groups created over SCIM are ordinary groups and appear under Identity → Groups.

A SCIM-created person is a normal account. Assign them applications, add them to groups, and manage them in the console as usual.

If a person belongs to a directory you connected (Active Directory or LDAP), that directory owns their name and email, and a SCIM change to those is refused with a mutability error (see Errors you can see). Changing active still works.

SCIM does not carry a password, and SSOGEN does not accept one over SCIM. A new SCIM person therefore has no password from SCIM. An administrator can set one (open the person in Identity → Users, then choose Set password), or the person can sign in through an external identity provider you have configured. SSOGEN sends no automatic invitation or password-setup message to new SCIM people.

Deprovisioning: what happens when someone leaves

Section titled “Deprovisioning: what happens when someone leaves”
What the other system sends What SSOGEN does
PATCH with active set to false (the usual way, used by Okta, Microsoft Entra ID and most HR systems) The account is disabled. They cannot sign in with any method. Nothing is deleted, and active: true switches them back on.
PUT with "active": false Same: disabled.
DELETE /Users/{id} The account is archived: it leaves the Users list, every session ends, they can no longer sign in, and their history stays in the audit trail. An administrator can restore it. It is never erased. The answer is 204 No Content.
DELETE /Groups/{id} The group is deleted.

A person that is already archived is not brought back to disabled by a later active: false.

Administrators are protected. A SCIM client holds no administrator role, so it cannot change an account that holds one unless that client created it, and even then it cannot change its user name or email (where sign-in codes and reset links go). A group change that would add or remove such an administrator is refused too (403 “This change would add or remove an SSOGEN administrator this client did not provision. A Super Admin changes their groups in the SSOGEN console.”). It also cannot deactivate or delete the last administrator who can still sign in to the Admin Console. Nothing is changed in either case, and the refusal is recorded in the audit log. See Admin Console sign-in and lockout protection.

Each create, update, deactivation and token event is written to the audit trail, with the client that did it.

Answers use the standard SCIM error shape: schemas, optional scimType, detail and status (as text).

Status scimType detail (text you will see) Meaning and fix
401 A valid provisioning token is required. Missing, wrong or revoked token. The answer also carries WWW-Authenticate: Bearer realm="SSOGEN SCIM". Check the header is Authorization: Bearer <token>, and the client is not revoked.
400 invalidFilter e.g. only the eq operator is supported, not “co”; filter on “department” is not supported; this directory filters on userName, externalId, emails.value and displayName Use attribute eq "value" on a supported attribute.
400 invalidSyntax No body.; a PATCH must carry a non-empty Operations array; unknown op: …; a remove operation must name a path Fix the request body.
400 invalidValue userName is required; displayName is required Send the missing required attribute.
400 mutability This user’s name and email are managed by the directory … and are read-only here. Send only active to change the account’s status. The person belongs to a connected directory. Change active only, or change the name in that directory.
403 This account holds an SSOGEN administrator role and was not provisioned by this client. A Super Admin changes it in the SSOGEN console.; This account holds an SSOGEN administrator role. A SCIM client may end it or rename it, but not change its user name or email; a Super Admin does that in the SSOGEN console. The account is an administrator’s. Change it in the console as a Super admin.
409 Nobody else could sign in to the SSOGEN admin console under its sign-in policy, so this account was not deactivated. A Super Admin gives another account that can sign in to the console the Super Admin role first. Nothing was changed. The account is the last administrator the Admin Console admits. Give another account the Super Admin role first.
404 No such user.; No such group.; No such schema. The id does not exist in SSOGEN (also returned when the id is not one SSOGEN issued). Look the person up by filter.
409 uniqueness a user with that userName already exists; a user with that externalId already exists; a group with that displayName already exists The person or group is already there. Look them up with a filter and update them instead of creating.

Errors on the console page itself:

Message Meaning
The provisioning clients could not be loaded. The list could not be read. Reload; if it persists, check you are still signed in.
That client could not be created. The create failed, for example an empty or over-long name.
That client could not be revoked. The revoke failed, for example it was already revoked.

The exact screens differ by product, and SSOGEN cannot check them for you, so use the product’s own documentation for where each field lives. The values to supply are the same everywhere:

The HR system asks for Give it
SCIM base URL, tenant URL or connector URL https://sso.acme.example/scim
Authentication type Bearer token (sometimes called “OAuth bearer token” or “API token”)
Token The ssogen_scim_… value from step 3
Unique identifier for matching userName
Employee id attribute externalId
Attributes to send userName, name.givenName, name.familyName, displayName, emails (work, primary), active
Group push Optional. Group displayName and members (the SSOGEN ids it received when it created each person)
Deprovisioning Set active = false on leaving (the most common setting), unless you want accounts archived, in which case use delete

Whether a specific HR product (for example Workday or BambooHR) can act as a SCIM client directly, or needs an intermediary, depends on the product and your license. Check with the vendor.

Acme Corp (acme.example) hires Maria Lopez on 1 November. Its HR system will provision her into SSOGEN, and switch her off when she leaves.

  1. A Directory admin opens Provisioning → Inbound, types the name Acme HR (Workday) and chooses Create.
  2. They copy the token, paste it into the HR system’s SCIM settings along with https://sso.acme.example/scim, and choose I have copied it.
  3. On Monday the HR system runs: it asks GET /Users?filter=userName eq "maria.lopez", gets totalResults: 0, and sends POST /Users as in the example. SSOGEN answers 201.
  4. An administrator opens Identity → Users and sees Maria Lopez with Source Provisioned from Acme HR (Workday). In Provisioning → Inbound the client’s Last used now shows today’s time.
  5. The HR system adds Maria to its Finance department. It sends POST /Groups (first time) or PATCH /Groups/{id} with an add on members. Maria appears in Identity → Groups → Finance, and any application assigned to that group is available to her.
  6. An administrator sets Maria’s password (Set password) or she signs in through the company’s identity provider.
  7. Months later Maria leaves. HR sends PATCH with active: false. In Identity → Users her account is disabled, and she cannot sign in. Her history remains in the audit trail.
Symptom Likely cause and fix
The HR system’s “test connection” fails with 401 Wrong token, extra spaces or quotes around it, or the client was revoked. Create a new client.
It fails and Last used stays a dash The request never reached SSOGEN: wrong base URL, firewall or TLS. Test with curl -i -H "Authorization: Bearer $TOKEN" https://sso.acme.example/scim/ServiceProviderConfig, which should answer 200.
Every create returns 409 The people already exist (for example you created them by hand). Have the HR system match on userName first.
The HR system shows success but the person can still sign in It may not be sending active: false. Check its leaver action, and the person’s status in Identity → Users.
People appear but not in the group Group members must be SSOGEN ids, as returned when each person was created. Unknown ids are skipped silently.
A name change is refused with mutability The person belongs to a connected directory (AD/LDAP), which owns their name and email. Change it there.
A department or title never arrives SSOGEN stores only the attributes listed above and ignores the rest.
You lost the token It cannot be shown again. Create a new client and revoke the old one.
  • Vendor-specific screens for Workday, BambooHR or other HR systems: follow the vendor’s own documentation for its SCIM client.
  • Filling custom profile attributes over SCIM: not offered; only the attributes listed above are stored.
  • Automatic welcome or password-setup messages to people provisioned over SCIM: none are sent; an administrator can set a password or the person can use an external identity provider.

Send accounts on to applications with outbound provisioning, import from a directory with Active Directory sync, or see user provisioning software.