Users API
1. Overview
The Users API allows you to create, retrieve, list, update, and deactivate users in SpeakUp via the SCIM 2.0 protocol. It is designed for use by enterprise identity providers (IdPs) such as Microsoft Entra ID, Okta, and OneLogin to automate user lifecycle management.
Base Endpoint: {API_BASE_URL}/scim/v2/Users
2. Before You Begin
Review the following requirements and behavioral notes before configuring provisioning in your identity provider. Understanding these constraints upfront prevents common provisioning failures.
2.1 Supported Provisioning Features
|
Feature |
Supported |
Notes |
|---|---|---|
|
Create users |
✅ Yes |
Via |
|
Update user attributes |
✅ Yes |
Via |
|
Deactivate users |
✅ Yes |
Set |
|
Reactivate users |
✅ Yes |
Set |
|
Delete users |
❌ No |
SpeakUp does not support user deletion via SCIM. Use deactivation instead. |
|
Sync group membership |
✅ Yes |
Via Groups API |
|
Filter users by attribute |
✅ Yes |
|
|
Paginated user listing |
✅ Yes |
|
|
Multiple emails per user |
❌ No |
SpeakUp stores one email per user |
|
Multiple phone numbers per user |
❌ No |
SpeakUp stores one phone number per user |
Three attributes are mandatory for every user creation request. Your identity provider must be configured to send all three.
|
Attribute |
Type |
Constraint |
|---|---|---|
|
|
string |
Must be a valid email address. Used as the unique identifier. |
|
|
string |
The name shown in the SpeakUp UI. |
|
|
boolean |
Account state at creation. Typically |
Important: The userName value must be a valid email address. It serves as the authoritative email for the user account. If an emails array is also present in the request, SpeakUp uses userName as the stored email and gracefully ignores any conflicting values in the array.
2.3 Key Behavioral Constraints
Before provisioning users at scale, be aware of how SpeakUp handles data that your IdP may send in different formats.
One identity per user. SpeakUp enforces a single email address and a single phone number per user account. If your IdP sends arrays with multiple entries, SpeakUp applies the priority rules described in sections 2.5 and 2.6 to determine which value to store.
userName is the unique key. Attempting to create a user with a userName that already exists returns 409 Conflict.
User deletion is not supported. SpeakUp does not support permanent deletion of users via the SCIM API. A DELETErequest will be accepted but the user will be deactivated rather than removed. For all offboarding scenarios, set active: false via a PATCH request. This preserves the account for audit and historical data purposes and allows reactivation if needed.
externalId is sourced from your identity provider. SpeakUp stores the externalId value as received from the provisioning request and uses it to correlate accounts with your external identity provider. It is not used as a lookup key internally — SpeakUp identifies users by its own system-generated id returned at creation time.
2.4 Name Resolution Priority
SpeakUp stores a single name field internally. When a provisioning request includes multiple name-related attributes, SpeakUp resolves the display name using the following priority order:
-
displayName(highest priority — always send this) -
name.formatted -
name.givenName+name.familyName(concatenated)
Most identity providers send displayName by default. If your IdP attribute mapping omits displayName, verify that name.formatted or the given/family name combination is present, or the user may be created with a blank display name.
2.5 Email Resolution Priority
When the provisioning request includes both userName and an emails array, SpeakUp determines the stored email as follows:
-
userName(highest priority) -
emails[].valuewhereprimary: true -
emails[0].value
Because userName takes precedence, ensure your IdP maps the user's primary email to userName. Sending a different address in the emails array does not override the userName value.
2.6 Phone Number Resolution Priority
When multiple phone numbers are provided:
-
phoneNumbers[].valuewhereprimary: true -
phoneNumbers[0].value
If no phone number is included, SpeakUp returns an empty array [] in API responses.
3. Authentication
All SCIM API requests must include a bearer token in the Authorization header. Refer to the SpeakUp SCIM Overview for token generation instructions.
Authorization: Bearer <ACCESS_TOKEN>
Content-Type: application/scim+json
Accept: application/scim+json
4. Response Structure
4.1 Core User Attributes
|
Attribute |
Type |
Description |
|---|---|---|
|
|
string |
System-generated unique identifier. Read-only. Returned on creation. |
|
|
string |
Unique email address. Used as the primary identifier. Required. |
|
|
string |
Name shown in the SpeakUp UI. Required. |
|
|
boolean |
Whether the account is active. Required. |
|
|
string |
Full name as a single string. |
|
|
string |
First name. |
|
|
string |
Last name. |
|
|
string |
Email address. Must match |
|
|
string |
Always |
|
|
boolean |
Always |
|
|
string |
Phone number. |
|
|
string |
Always |
|
|
boolean |
Always |
|
|
string |
Job title. |
|
|
string |
User category (e.g., |
|
|
string |
External identifier from HR system or IdP. |
|
|
string |
BCP 47 language tag. Defaults to |
|
|
string |
Group ID. Returned in responses. |
|
|
string |
Group name. Returned in responses. |
|
|
string |
Full URL to the Group resource. Returned in responses. |
|
|
string |
Always |
|
|
string |
ISO 8601 timestamp of creation. |
|
|
string |
ISO 8601 timestamp of last update. |
|
|
string |
Canonical URL of this User resource. |
4.2 Enterprise Extension Attributes
To provision organizational 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 |
|---|---|---|---|
|
|
|
string |
Employee ID from HR system. Max 128 characters. |
|
|
|
option-list |
Cost center for billing allocation. |
|
|
|
option-list |
Department name. |
|
|
|
option-list |
Division name. |
|
|
|
option-list |
Organization or company name. |
|
|
|
complex |
Reference to another user: |
Note: Fields mapped to option-list types (department, division, costCenter, organization) are matched against existing values configured in your SpeakUp instance. If a value is not found, SpeakUp will create a new option-list item using the provided value.
5. Create a User
Method: POST
Endpoint: /scim/v2/Users
5.1 Minimal Request
curl -X POST 'https://your-org.speakup.com/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
}'
5.2 Request with Name and Email
curl -X POST 'https://your-org.speakup.com/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,
"name": {
"givenName": "John",
"familyName": "Doe",
"formatted": "John Doe"
},
"emails": [
{
"value": "john.doe@example.com",
"type": "work",
"primary": true
}
]
}'
5.3 Request with Enterprise Extension
curl -X POST 'https://your-org.speakup.com/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"
},
"emails": [
{
"value": "jane.doe@company.com",
"type": "work",
"primary": true
}
],
"title": "Product Manager",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"employeeNumber": "EMP-99999",
"costCenter": "Product",
"department": "Product Management",
"division": "Product Division"
}
}'
5.4 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": "https://your-org.speakup.com/scim/v2/Users/101"
}
}
5.5 Error Responses
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"
}
6. Retrieve a User
Method: GET
Endpoint: /scim/v2/Users/{id}
6.1 Query Parameters
|
Parameter |
Type |
Description |
|---|---|---|
|
|
string |
Comma-separated list of attributes to omit from the response (e.g., |
6.2 Request
curl -X GET 'https://your-org.speakup.com/scim/v2/Users/101' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'
6.3 Request (with excludedAttributes)
curl -X GET 'https://your-org.speakup.com/scim/v2/Users/101?excludedAttributes=meta' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'
6.4 Response — 200 OK
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 1,
"Resources": [
{
"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",
"groups": [
{
"value": "1",
"display": "Engineering Team",
"$ref": "https://your-org.speakup.com/scim/v2/Groups/1"
}
],
"meta": {
"resourceType": "User",
"created": "2026-02-23T10:30:00Z",
"lastModified": "2026-02-23T10:30:00Z",
"location": "https://your-org.speakup.com/scim/v2/Users/101"
}
}
]
}
6.5 Error — 404 Not Found
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail": "User not found",
"status": "404"
}
7. List Users
Method: GET
Endpoint: /scim/v2/Users
7.1 Query Parameters
|
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
integer |
|
1-based starting position for pagination. |
|
|
integer |
|
Number of results per page. |
|
|
string |
— |
SCIM filter expression (URL-encoded). |
|
|
string |
— |
Comma-separated attributes to omit (e.g., |
7.2 Supported Filter Expressions
|
Filter Expression |
Behavior |
|---|---|
|
|
Exact match on userName |
|
|
userName starts with value |
|
|
displayName contains value |
|
|
Exact match on displayName |
|
|
Active users only |
All users (default pagination):
curl -X GET 'https://your-org.speakup.com/scim/v2/Users' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'
With pagination
curl -X GET 'https://your-org.speakup.com/scim/v2/Users?startIndex=1&count=10' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'
With filter:
curl -X GET 'https://your-org.speakup.com/scim/v2/Users?filter=userName%20eq%20%22john.doe@example.com%22' \
-H 'Accept: application/scim+json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'
8. Update a User (Full Replacement — PUT)
Use PUT to fully replace a user's attributes. Attributes omitted from the request body may be cleared per SCIM semantics. Use PATCH if you only want to update specific fields.
Note: The same name, email, and phone resolution priority rules described in sections 2.4–2.6 apply to PUTrequests. userName always takes precedence as the stored email; displayName takes precedence for the stored name field.
Method: PUT
Endpoint: /scim/v2/Users/{id}
8.1 Request
curl -X PUT 'https://your-org.speakup.com/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"
}'
8.2 Response — 200 OK
Returns the full updated user in SCIM format, including updated meta.lastModified.
8.3 Error Responses
|
Code |
Cause |
|---|---|
|
400 |
Invalid or missing required fields |
|
404 |
User does not exist |
|
409 |
|
9. Update a User (Partial Update — PATCH)
Use PATCH to update one or more attributes without affecting others. This is the recommended method for lifecycle operations such as deactivation, reactivation, and attribute updates.
Note: The same name, email, and phone resolution priority rules described in sections 2.4–2.6 apply to PATCH requests. When updating userName, the stored email will be updated accordingly.
Method: PATCH
Endpoint: /scim/v2/Users/{id}
9.1 Update a Single Attribute
curl -X PATCH 'https://your-org.speakup.com/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"
}
]
}'
9.2 Update Multiple Attributes
curl -X PATCH 'https://your-org.speakup.com/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"
},
{
"op": "replace",
"path": "active",
"value": true
}
]
}'
9.3 Deactivate a User
curl -X PATCH 'https://your-org.speakup.com/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
}
]
}'
9.4 Response — 200 OK
Returns the full user in SCIM format with updated attributes and meta.lastModified.
10. Status Code Reference
|
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 |
|
500 |
Internal Server Error |
Server-side error — contact SpeakUp support |
11. Attribute Mapping Reference
11.1 Core Schema (urn:ietf:params:scim:schemas:core:2.0:User)
|
SpeakUp Field |
SCIM Attribute |
Type |
Notes |
|---|---|---|---|
|
|
|
string |
Read-only. Returned by API. |
|
|
|
string |
Required. Must be a valid email. Highest-priority source for stored email. |
|
|
|
string |
Required. Shown in UI. Highest-priority source for stored name. |
|
|
|
string |
Used if |
|
|
|
string |
Used if neither |
|
|
|
string |
Concatenated with |
|
|
|
boolean |
Required. |
|
|
|
string |
Stored email derived from |
|
|
|
string |
— |
|
|
|
string |
See phone resolution priority in section 2.6. |
|
|
|
string |
BCP 47 language tag. Defaults to |
|
|
|
string |
Sourced from identity provider. Stored as received. Not used as an internal lookup key. |
|
|
|
complex |
Read-only in user responses. Managed via Groups API. |
|
|
|
string (ISO 8601) |
Read-only. |
|
|
|
string (ISO 8601) |
Read-only. |
11.2 Enterprise Extension (urn:ietf:params:scim:schemas:extension:enterprise:2.0:User)
|
SCIM Attribute |
SpeakUp Field |
Type |
Notes |
|---|---|---|---|
|
|
|
string |
Max 128 characters. |
|
|
|
option-list |
Matched against existing values. Creates a new option-list item if not found. |
|
|
|
option-list |
Matched against existing values. Creates a new option-list item if not found. |
|
|
|
option-list |
Matched against existing values. Creates a new option-list item if not found. |
|
|
|
option-list |
Matched against existing values. Creates a new option-list item if not found. |
|
|
|
complex |
|