SCIM API reference

This page documents the System for Cross-domain Identity Management (SCIM) v2.0 endpoints implemented by Posit Connect. For setup instructions, see SCIM provisioning. For the full protocol specification, see RFC 7644 (protocol) and RFC 7643 (schema).

Write requests (POST, PUT, PATCH) must include a Content-Type header of application/scim+json or application/json, and must include a schemas array identifying the resource type. All responses use Content-Type: application/scim+json.

Success response codes

Code Meaning Returned by
200 OK Resource retrieved or updated GET, PUT, PATCH
201 Created Resource created POST
204 No Content Request accepted (no body returned) DELETE

Discovery

The discovery endpoints are publicly accessible and do not require authentication. They allow identity providers (IdPs) and clients to determine the SCIM capabilities that Connect supports before making provisioning requests.

Method Endpoint Description
GET /scim/v2/ServiceProviderConfig Returns supported SCIM features (authentication schemes, patch support, filtering, pagination limits)
GET /scim/v2/ResourceTypes Returns the resource types Connect supports (User and Group) with their schema URIs
GET /scim/v2/Schemas Returns the full schema definitions for User and Group resources

Users

The {id} path parameter is the Connect globally unique identifier (GUID) for the user.

Endpoints

Method Endpoint Description
GET /scim/v2/Users List users (supports filtering and pagination)
GET /scim/v2/Users/{id} Get user by GUID
POST /scim/v2/Users Create user
PUT /scim/v2/Users/{id} Replace user
PATCH /scim/v2/Users/{id} Update user
DELETE /scim/v2/Users/{id} No-op (returns 204). Does not remove the user. Use the usermanager CLI to delete users.

Attributes

Attribute Required Notes
userName Yes Must be unique
active No true = unlocked, false = locked. Defaults to locked if omitted. Accepts string "True"/"False" in PATCH (Entra ID compatibility)
name.givenName No Used by POST and PUT
name.familyName No Used by POST and PUT
displayName No Used by PATCH only. Split on whitespace into first name and last name
emails[0].value No Only the first email is used
externalId No Your IdP’s identifier. See details

If your IdP sends both name and displayName in the same request, name.givenName and name.familyName take precedence and displayName has no effect. This applies to POST, PUT, and path-less PATCH operations.

Users created via SCIM are assigned the role specified by Authorization.DefaultUserRole (defaults to viewer). SCIM does not support setting or changing user roles. To modify a SCIM-provisioned user’s role, use the Connect UI or the Connect API.

PATCH operations

PATCH requests use the following request body structure:

Request body
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [...]
}

For single-valued attributes, add and replace are semantically equivalent (RFC 7644 §3.5.2.1). Both set the attribute to the supplied value. Unsupported paths are silently ignored.

All user attributes can be modified with a direct-path operation:

{"op": "replace", "path": "active", "value": false}
{"op": "replace", "path": "userName", "value": "newname"}
{"op": "replace", "path": "displayName", "value": "Jane Smith"}
{"op": "replace", "path": "name.givenName", "value": "Jane"}
{"op": "replace", "path": "name.familyName", "value": "Smith"}
{"op": "replace", "path": "externalId", "value": "external-id-value"}
{"op": "replace", "path": "emails", "value": [{"value": "new@example.com", "primary": true}]}

The path-less form supports setting multiple attributes in a single operation (Okta style):

{"op": "replace", "value": {"active": true, "userName": "jsmith", "displayName": "Jane Smith"}}

The path-less form accepts all user attributes, including name, emails, and externalId:

{"op": "replace", "value": {"name": {"givenName": "Jane", "familyName": "Smith"}, "emails": [{"value": "jane@example.com", "primary": true}], "externalId": "ext-123"}}
Note

Entra ID sends PATCH operation names with an initial capital letter (e.g., "Replace" instead of "replace") and encodes the active field as a string ("True"/"False") rather than a JSON boolean. Connect handles both forms automatically.

Examples

Create a user

Terminal
curl -X POST https://connect.example.com/scim/v2/Users \
  -H "Authorization: Bearer SERVICE-TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "jsmith",
    "name": {
      "givenName": "Jane",
      "familyName": "Smith"
    },
    "emails": [{"value": "jsmith@example.com", "primary": true}],
    "externalId": "<external-id>",
    "active": true
  }'

Response (201 Created):

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "id": "<user-guid>",
  "externalId": "<external-id>",
  "userName": "jsmith",
  "name": {
    "givenName": "Jane",
    "familyName": "Smith"
  },
  "emails": [{"value": "jsmith@example.com", "type": "work", "primary": true}],
  "active": true,
  "meta": {
    "resourceType": "User",
    "created": "<timestamp>",
    "lastModified": "<timestamp>",
    "version": "W/\"<version>\"",
    "location": "/scim/v2/Users/<user-guid>"
  }
}

Deactivate a user (PATCH)

Terminal
curl -X PATCH https://connect.example.com/scim/v2/Users/<user-guid> \
  -H "Authorization: Bearer SERVICE-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}]
  }'

Response (200 OK): Returns the full user resource with "active": false.

Replace a user (PUT)

Terminal
curl -X PUT https://connect.example.com/scim/v2/Users/<user-guid> \
  -H "Authorization: Bearer SERVICE-TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "jsmith",
    "name": {
      "givenName": "Jane",
      "familyName": "Doe"
    },
    "emails": [{"value": "jdoe@example.com", "primary": true}],
    "active": true
  }'

Response (200 OK): Returns the full updated user resource. PUT preserves system-managed fields (GUID, role, unique ID, creation time) and replaces only profile attributes. Connect ignores the externalId field in PUT requests. To update a user’s unique ID after creation, use the usermanager alter --new-unique-id CLI command on the Connect server.

Groups

Endpoints

Method Endpoint Description
GET /scim/v2/Groups List groups (supports filtering and pagination)
GET /scim/v2/Groups/{id} Get group by GUID
POST /scim/v2/Groups Create group
PUT /scim/v2/Groups/{id} Replace group
PATCH /scim/v2/Groups/{id} Update group or members
DELETE /scim/v2/Groups/{id} Delete group

Attributes

Attribute Required Notes
displayName Yes Maximum 4096 characters
members No Array of {"value": "<user-guid>"} objects

PATCH operations

PATCH requests use the following request body structure:

Request body
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [...]
}

The supported operations are listed below. Unsupported paths are silently ignored.

Add members to a group

Duplicates are ignored.

{"op": "add", "path": "members", "value": [{"value": "<user-guid>"}]}

Remove members (Entra ID style)

No error if the user is not a member.

{"op": "remove", "path": "members", "value": [{"value": "<user-guid>"}]}

Remove a single member (Okta style)

No error if the user is not a member.

{"op": "remove", "path": "members[value eq \"<user-guid>\"]"}

Replace the entire member list

{"op": "replace", "path": "members", "value": [{"value": "<user-guid>"}]}

Rename the group (Entra ID style)

For single-valued attributes like displayName, add and replace are equivalent. Entra ID uses add when it believes the attribute is unset.

{"op": "replace", "path": "displayName", "value": "New Group Name"}
{"op": "add", "path": "displayName", "value": "New Group Name"}

Rename the group (Okta style)

The path is omitted and the value is an object:

{"op": "replace", "value": {"displayName": "New Group Name"}}
Note

Entra ID sends PATCH operation names with an initial capital letter (e.g., "Replace" instead of "replace"). Connect normalizes this automatically.

Examples

Create a group

Terminal
curl -X POST https://connect.example.com/scim/v2/Groups \
  -H "Authorization: Bearer SERVICE-TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
    "displayName": "Data Science Team",
    "members": [
      {"value": "<user-guid>"}
    ]
  }'

Response (201 Created):

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
  "id": "<group-guid>",
  "displayName": "Data Science Team",
  "members": [
    {
      "value": "<user-guid>",
      "$ref": "/scim/v2/Users/<user-guid>",
      "display": "Jane Smith",
      "type": "User"
    }
  ],
  "meta": {
    "resourceType": "Group",
    "location": "/scim/v2/Groups/<group-guid>"
  }
}

Add members (PATCH)

Terminal
curl -X PATCH https://connect.example.com/scim/v2/Groups/<group-guid> \
  -H "Authorization: Bearer SERVICE-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-guid-2>"}]
    }]
  }'

Response (200 OK): Returns the full group resource with the updated member list.

Remove members (PATCH)

Terminal
curl -X PATCH https://connect.example.com/scim/v2/Groups/<group-guid> \
  -H "Authorization: Bearer SERVICE-TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{
      "op": "remove",
      "path": "members",
      "value": [{"value": "<user-guid-2>"}]
    }]
  }'

Response (200 OK): Returns the full group resource with the updated member list.

Filtering

Connect supports the eq (equals) operator for filtering. String comparisons are case-insensitive. Other SCIM filter operators are not supported.

Resource Filterable attributes
Users userName, email or emails.value, externalId
Groups displayName

Example:

Terminal
curl -H "Authorization: Bearer SERVICE-TOKEN" \
  "https://connect.example.com/scim/v2/Users?filter=userName%20eq%20%22jsmith%22"

Enclose filter values in double quotes per the SCIM specification. URL-encode the filter parameter.

Pagination

Parameter Description Default
startIndex 1-based starting position 1
count Results per page 20

Connect advertises a maxResults of 200 in the ServiceProviderConfig endpoint. Responses include totalResults, startIndex, and itemsPerPage for navigation.

Error responses

Connect returns errors in the SCIM error format defined by RFC 7644 section 3.12:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "status": "409",
  "scimType": "uniqueness",
  "detail": "User already exists"
}
Status scimType Cause
400 invalidSyntax Malformed JSON, missing schemas array, or missing required schema
400 invalidValue Missing required attribute (e.g., userName, displayName, email.value, member.value)
400 invalidPath Invalid resource path in URL
401 Missing or invalid credentials
403 Authenticated but insufficient permissions
404 Resource not found (user or group GUID does not exist)
405 HTTP method not allowed for the endpoint
409 uniqueness Username or group name already exists
500 Internal server error
501 Unsupported endpoint (/Bulk, /Me)

Limitations

Feature Status
Bulk operations (/scim/v2/Bulk) Not supported
Current user (/scim/v2/Me) Not supported
Change password Not supported
User deletion Returns 204 but does not delete
Sorting (sortBy, sortOrder) Not supported
ETags Not supported
Filter operators other than eq Not supported
Logical operators (and, or, not) Not supported