Skip to content
English - United Kingdom
  • There are no suggestions because the search field is empty.

SCIM Users API

Create, retrieve, list, update, and deactivate Users in SpeakUp through the SCIM 2.0 protocol. Designed for identity providers such as Microsoft Entra ID and Okta to automate user lifecycle management.

Users cannot be deleted through SCIM. Offboarding is done by deactivation.

{API_BASE_URL}/scim/v2/Users

On this page: Authentication · Supported features · Required fields · Behavioural constraints · Resolution priorities · User attributes · Create a User · Retrieve a User · List Users · Update with PUT · Update with PATCH · Status codes · Attribute mapping

Authentication

All SCIM requests need a bearer token. See what is SCIM provisioning and when should I use it? for how the connection is set up.

Authorization: Bearer <ACCESS_TOKEN>
Content-Type: application/scim+json
Accept: application/scim+json

Provisioning requires Full access for Users and Groups on the App Integration. Read only access can retrieve Users but cannot create, update, or deactivate them.

Supported features

Review these before configuring provisioning in your identity provider. Understanding the constraints up front prevents the most common provisioning failures.

Feature Supported Notes
Create Users Yes Via POST /scim/v2/Users
Update User attributes Yes Via PUT or PATCH
Deactivate Users Yes Set active: false via PATCH
Reactivate Users Yes Set active: true via PATCH
Delete Users No SpeakUp does not support User deletion via SCIM. Use deactivation instead.
Sync group membership Yes Via the Groups API
Filter Users by attribute Yes userName, displayName, active
Paginated listing Yes startIndex and count parameters
Multiple emails per User No SpeakUp stores one email per User
Multiple phone numbers per User No SpeakUp stores one phone number per User

Required fields

Three attributes are mandatory for every User creation request. Your identity provider must be configured to send all three.

Attribute Type Constraint
userName String Must be a valid email address. Used as the unique identifier.
displayName String The name shown in the SpeakUp interface.
active Boolean Account state at creation. Typically true.

 

The userName value must be a valid email address. It serves as the authoritative email for the account. If an emails array is also present, SpeakUp uses userName as the stored email and ignores conflicting values in the array.

Behavioural constraints

One identity per User. SpeakUp stores a single email address and a single phone number per account. If your identity provider sends arrays with multiple entries, the priority rules below determine which value is stored.

userName is the unique key. Creating a User with a userName that already exists returns 409 Conflict.

User deletion is not supported. A DELETE request is accepted but the User is deactivated rather than removed. For all offboarding, set active: false via PATCH. This preserves the account for audit and historical purposes and allows reactivation.

externalId comes from your identity provider. SpeakUp stores it as received and uses it to correlate accounts with your provider. It is not an internal lookup key. SpeakUp identifies Users by its own system-generated id, returned at creation.

Resolution priorities

SpeakUp stores one value where SCIM allows several. These rules decide which one.

Name

  1. displayName, highest priority. Always send this.
  2. name.formatted
  3. name.givenName and name.familyName, concatenated

Most identity providers send displayName by default. If your attribute mapping omits it, make sure name.formatted or the given and family names are present, or the User may be created with a blank display name.

Email

  1. userName, highest priority
  2. emails[].value where primary: true
  3. emails[0].value

Because userName takes precedence, map the User's primary email to userName. A different address in the emails array does not override it.

Phone number

  1. phoneNumbers[].value where primary: true
  2. phoneNumbers[0].value

If no phone number is included, SpeakUp returns an empty array.

User attributes

Core attributes

Attribute Type Description
id String System-generated unique identifier. Read only. Returned on creation.
userName String Unique email address, used as the primary identifier. Required.
displayName String Name shown in the SpeakUp interface. Required.
active Boolean Whether the account is active. Required.
name.formatted String Full name as a single string.
name.givenName String First name.
name.familyName String Last name.
emails[].value String Email address. Matches userName.
emails[].type String Always "work" in responses.
emails[].primary Boolean Always true in responses.
phoneNumbers[].value String Phone number.
phoneNumbers[].type String Always "work" in responses.
phoneNumbers[].primary Boolean Always true in responses.
title String Job title.
userType String User category, for example Employee or Contractor.
externalId String External identifier from your HR system or identity provider.
preferredLanguage String BCP 47 language tag. Defaults to "en-GB".
groups[].value String Group ID. Returned in responses.
groups[].display String Group name. Returned in responses.
groups[].$ref String Full URL to the Group resource. Returned in responses.
meta.resourceType String Always "User".
meta.created String ISO 8601 timestamp of creation.
meta.lastModified String ISO 8601 timestamp of last update.
meta.location String Canonical URL of this User resource.

Enterprise extension attributes

To provision organisational attributes such as department or manager, include the enterprise extension schema urn:ietf:params:scim:schemas:extension:enterprise:2.0:User in the schemas array.

Attribute SpeakUp field Type Description
employeeNumber employeeNumber String Employee ID from your HR system. Maximum 128 characters.
costCenter costCentreId Option list Cost centre for billing allocation.
department departmentId Option list Department name.
division divisionId Option list Division name.
organization organizationId Option list Organisation or company name.
manager managerId Complex Reference to another User: value is the user ID, $ref the User URL, displayName the manager's name.

 

Option list fields (department, division, costCenter, organization) are matched against existing values configured in your SpeakUp instance. If a value is not found, SpeakUp creates a new option list item using the provided value.

Create a User

POST /scim/v2/Users

Minimal request:

curl -X POST '{API_BASE_URL}/scim/v2/Users' \
-H 'Content-Type: application/scim+json' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
--data-raw '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "john.doe@example.com",
"displayName": "John Doe",
"active": true
}'

With the enterprise extension:

curl -X POST '{API_BASE_URL}/scim/v2/Users' \
-H 'Content-Type: application/scim+json' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
--data-raw '{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
],
"userName": "jane.doe@company.com",
"displayName": "Jane Doe",
"active": true,
"name": {
"givenName": "Jane",
"familyName": "Doe"
},
"title": "Product Manager",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"employeeNumber": "EMP-99999",
"costCenter": "Product",
"department": "Product Management",
"division": "Product Division"
}
}'

Response, 201 Created

{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "101",
"userName": "john.doe@example.com",
"displayName": "John Doe",
"active": true,
"name": {
"givenName": "John",
"familyName": "Doe",
"formatted": "John Doe"
},
"emails": [
{ "value": "john.doe@example.com", "type": "work", "primary": true }
],
"title": "Senior Software Engineer",
"phoneNumbers": [
{ "value": "+1-555-0123", "type": "work", "primary": true }
],
"preferredLanguage": "en",
"meta": {
"resourceType": "User",
"created": "2026-02-23T10:30:00Z",
"lastModified": "2026-02-23T10:30:00Z",
"location": "{API_BASE_URL}/scim/v2/Users/101"
}
}

Errors

400 Bad Request, missing or invalid required fields:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"scimType": "invalidValue",
"detail": "Validation failed: userName is required",
"status": "400"
}

409 Conflict, a User with the same userName already exists:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"scimType": "uniqueness",
"detail": "A user with userName 'john.doe@example.com' already exists",
"status": "409"
}

Retrieve a User

GET /scim/v2/Users/{id}
Query parameter Type Description
excludedAttributes String Comma-separated list of attributes to omit from the response, for example meta.
curl -X GET '{API_BASE_URL}/scim/v2/Users/101' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'

The response includes the User's groups array, showing every Group they belong to.

A User ID that does not exist returns 404:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail": "User not found",
"status": "404"
}

List Users

GET /scim/v2/Users
Query parameter Type Default Description
startIndex Integer 1 1-based starting position for pagination.
count Integer 50 Number of results per page.
filter String   SCIM filter expression, URL-encoded.
excludedAttributes String   Comma-separated attributes to omit.

Supported filter expressions

Expression Behaviour
userName eq "john.doe@example.com" Exact match on userName
userName sw "john" userName starts with the value
displayName co "Doe" displayName contains the value
displayName eq "John Doe" Exact match on displayName
active eq true Active Users only
curl -X GET '{API_BASE_URL}/scim/v2/Users?startIndex=1&count=10' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'
curl -X GET '{API_BASE_URL}/scim/v2/Users?filter=userName%20eq%20%22john.doe@example.com%22' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'

Update with PUT

PUT /scim/v2/Users/{id}

Fully replaces a User's attributes. Attributes omitted from the request body may be cleared, per SCIM semantics. Use PATCH if you only want to change specific fields.

The name, email, and phone resolution priorities above apply. userName always takes precedence as the stored email, and displayName for the stored name.

curl -X PUT '{API_BASE_URL}/scim/v2/Users/101' \
-H 'Content-Type: application/scim+json' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
--data-raw '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "john.doe@example.com",
"displayName": "John Michael Doe",
"active": true,
"name": {
"givenName": "John",
"familyName": "Doe"
},
"title": "Principal Software Engineer"
}'

Returns the full updated User with an updated meta.lastModified.

Code Cause
400 Invalid or missing required fields
404 User does not exist
409 userName already in use by a different User

Update with PATCH

PATCH /scim/v2/Users/{id}

Updates one or more attributes without affecting others. This is the recommended method for lifecycle operations such as deactivation, reactivation, and attribute updates.

Update a single attribute:

curl -X PATCH '{API_BASE_URL}/scim/v2/Users/101' \
-H 'Content-Type: application/scim+json' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
--data-raw '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "title", "value": "Engineering Manager" }
]
}'

Deactivate a User. This is how offboarding is done:

curl -X PATCH '{API_BASE_URL}/scim/v2/Users/101' \
-H 'Content-Type: application/scim+json' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
--data-raw '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "active", "value": false }
]
}'

Set active to true to reactivate.

Returns the full User with updated attributes and meta.lastModified.

Status codes

Code Meaning When it occurs
200 OK Successful GET, PATCH, or PUT
201 Created Successful POST
400 Bad Request Missing required fields, invalid data format, or malformed patch operation
401 Unauthorized Invalid or missing access token
403 Forbidden Insufficient permissions for the operation
404 Not Found User ID does not exist
409 Conflict Duplicate userName or constraint violation
500 Internal Server Error Server-side error. Contact SpeakUp support.

Attribute mapping

How SCIM attributes map to SpeakUp fields. Use this when configuring attribute mapping in your identity provider.

Core schema

SCIM attribute SpeakUp field Notes
id id Read only. Returned by the API.
userName email Required. Must be a valid email. Highest priority source for the stored email.
displayName name Required. Shown in the interface. Highest priority source for the stored name.
name.formatted name Used if displayName is absent.
name.givenName firstName Used if neither displayName nor name.formatted is present.
name.familyName lastName Concatenated with name.givenName as the last fallback.
active enabled Required.
emails[].value email Derived from userName. The array is accepted but userName takes precedence.
title jobTitle  
phoneNumbers[].value phone See phone resolution priority above.
preferredLanguage preferredLanguage BCP 47 language tag. Defaults to "en-GB".
externalId externalId Stored as received. Not used as an internal lookup key.
groups groups Read only in User responses. Managed through the Groups API.
meta.created createdAt Read only.
meta.lastModified updatedAt Read only.

Enterprise extension

SCIM attribute SpeakUp field Notes
employeeNumber employeeNumber Maximum 128 characters.
costCenter costCentreId Matched against existing values. Creates a new option list item if not found.
department departmentId Matched against existing values. Creates a new option list item if not found.
division divisionId Matched against existing values. Creates a new option list item if not found.
organization organizationId Matched against existing values. Creates a new option list item if not found.
manager managerId value is the user ID, $ref the User URL, displayName the manager's name.

Related