--- title: "User provisioning: API integration guide" slug: "user-provisioning-api-intgration-guide" description: "Automate user provisioning and group management in DocuWare with SCIM 2.0 API, integrating with Azure Entra ID, Okta, and more." updated: 2026-03-31T14:01:06Z published: 2026-03-31T14:01:06Z canonical: "knowledgecenter.docuware.com/user-provisioning-api-intgration-guide" --- > ## Documentation Index > Fetch the complete documentation index at: https://knowledgecenter.docuware.com/llms.txt > Use this file to discover all available pages before exploring further. # User provisioning: API integration guide The DocuWare User Provisioning v3 Service is a SCIM 2.0 compliant REST API that enables automatic user provisioning and group management from external Identity Providers (IdPs) such as Azure Entra ID, Okta, Ping Identity or On-premise Directory (with the help of the User Provisioning On-premise directory connector tool) to DocuWare systems. ## Base URL and endpoints ### Base URL Structure DocuWare Cloud ```xml https://{your-organization}.docuware.cloud/DocuWare/Services/UserProvisioningService/{externalIdp}/scim ``` DocuWare on-premises ```xml http(s)://{your-server-address}/DocuWare/Services/UserProvisioningService/{externalIdp}/scim ``` Where `{externalIdp}` can be: - `azure` - for Azure Entra ID - `okta `- for Okta - `ping` - for Ping Identity - `onpremise` - for on-premise directories - `generic-{identifier}` - for generic identity providers ### Available Endpoints | **Resource** | **HTTP Method** | **Endpoint** | **Description** | | --- | --- | --- | --- | | **Users** | GET | `/{externalIdp}/scim/Users` | Get all external users with optional filtering by userName or externalId | | | GET | `/{externalIdp}/scim/Users?allDocuWareUsers=true` | Get all users with optional filtering by userName or externalId | | | GET | `/{externalIdp}/scim/Users/{id}` | Get specific user by ID | | | POST | `/{externalIdp}/scim/Users` | Create new user | | | PUT | `/{externalIdp}/scim/Users/{id}` | Replace user completely | | | PATCH | `/{externalIdp}/scim/Users/{id}` | Partial user update | | | DELETE | `/{externalIdp}/scim/Users/{id}` | Delete user | | **Groups** | GET | `/{externalIdp}/scim/Groups` | Get all groups with optional filtering by displayName | | | GET | `/{externalIdp}/scim/Groups/{id}` | Get specific group by ID | | | POST | `/{externalIdp}/scim/Groups` | Create new group | | | PUT | `/{externalIdp}/scim/Groups/{id}` | Replace group completely | | | PATCH | `/{externalIdp}/scim/Groups/{id}` | Partial group update | | | DELETE | `/{externalIdp}/scim/Groups/{id}` | Delete group | | **Schemas** | GET | `/{externalIdp}/scim/Schemas` | Get SCIM schemas | | **Resource Types** | GET | `/{externalIdp}/scim/ResourceTypes` | Get supported resource types | | **Health Check** | GET | `/AvailabilityCheck` | Service availability check | ## Authentication ### JWT Bearer Authentication All endpoints (except health check) require JWT Bearer token authentication: ```json Authorization: Bearer {jwt-token} ``` ### Content Type All requests must use the SCIM content type: ```json Content-Type: application/scim+json ``` ## User Management ### User Schema (Core2EnterpriseUser) ### Get Users (GET) The GET Users endpoint supports multiple variants for retrieving user data with optional filtering and pagination. By default, it returns only users with external IDs (users from external identity providers). #### 1. Get All External Users (Default) ```json GET /{externalIdp}/scim/Users Authorization: Bearer {token} ``` Returns all users that have an externalId (users from external identity providers). **Response:** ```json {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],  "totalResults": 2,  "itemsPerPage": 2,  "startIndex": 1,  "resources": [    {      "userName": "john.doe",      "active": true,      "emails": [        {          "value": "john.doe@example.com",          "primary": true        }      ],      "name": {        "givenName": "John",        "familyName": "Doe"      },      "id": "external-user-id-123",      "meta": {        "resourceType": "User"      },      "schemas": [        "urn:ietf:params:scim:schemas:core:2.0:User",        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"      ],    },    {      "userName": "jane.smith",      "active": true,      "emails": [        {          "value": "jane.smith@example.com",          "primary": true        }      ],      "name": {        "givenName": "Jane",        "familyName": "Smith"      },      "id": "external-user-id-456",      "meta": {        "resourceType": "User"      },      "schemas": [        "urn:ietf:params:scim:schemas:core:2.0:User",        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"      ]    }  ] } ``` #### 2. Get All DocuWare Users ```json GET /{externalIdp}/scim/Users?allDocuWareUsers=true Authorization: Bearer {token} ``` Returns all users in the DocuWare system, including both external users and internal DocuWare users. > [!NOTE] > Note: internal users have no id > > Internal users do not have `id` in the response´, because they are not external and don't have an `externalId` attribute set, which is the one returned as `id`. **Response** ```json {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],  "totalResults": 2,  "itemsPerPage": 2,  "startIndex": 1,  "resources": [    {      "userName": "john.doe",      "active": true,      "emails": [        {          "value": "john.doe@example.com",          "primary": true        }      ],      "name": {        "givenName": "John",        "familyName": "Doe"      },      "id": "external-user-id-123",      "meta": {        "resourceType": "User"      },      "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User",        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],    },    {      "userName": "jane.smith",      "active": true,      "emails": [        {          "value": "jane.smith@example.com",          "primary": true        }      ],      "name": {        "givenName": "Jane",        "familyName": "Smith"      },      "meta": {        "resourceType": "User"      },      "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User",        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]    }  ] } ``` #### 3. Get Specific User by ID ```json GET /{externalIdp}/scim/Users/{externalId} Authorization: Bearer {token} ``` Returns a specific user by their external ID. **Response:** ```json {  "userName": "john.doe",  "active": true,  "emails": [    {      "value": "john.doe@example.com",      "primary": true    }  ],  "name": {    "givenName": "John",    "familyName": "Doe"  },  "id": "external-user-id-123",  "meta": {    "resourceType": "User"  },  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User",    "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"], } ``` #### 4. Query users with filtering **Filter by Username (in External Users):** ```json GET /{externalIdp}/scim/Users?filter=userName eq "john.doe" Authorization: Bearer {token} ``` **Filter by username in All DocuWare Users:** ```json GET /{externalIdp}/scim/Users?allDocuWareUsers=true&filter=userName eq "john.doe" Authorization: Bearer {token} ``` **Filter by External ID:** ```json GET /{externalIdp}/scim/Users?filter=externalId eq "external-user-id-123" Authorization: Bearer {token} ``` **Get Users with pagination:** ```json GET /{externalIdp}/scim/Users?startIndex=2&count=5 Authorization: Bearer {token} ``` ```json GET /{externalIdp}/scim/Users?allDocuWareUsers=true&startIndex=2&count=5 Authorization: Bearer {token} ``` #### Supported query parameters Pagination: - startIndex - 1-based index of the first result (default: 1, minimum: 1) - count - Number of results per page (default: all results if not specified, minimum: 0) Filtering: - filter - SCIM filter expression (supports only userName eq "value" & externalId eq "value") (case insensitive) #### Response Format All GET /Users requests return a SCIM ListResponse with the following structure: **Properties:** - schemas - Array containing "urn:ietf:params:scim:api:messages:2.0:ListResponse" - totalResults - Total number of matching users - itemsPerPage - Number of users returned in current response - startIndex - Starting index of current page (1-based) - Resources - Array of user objects #### Error Responses 400 Bad Request - Invalid Filter: ```json {  "ScimType": "invalidFilter",  "Detail": "Unsupported filter attribute: FirstName",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` ```json {  "ScimType": "invalidFilter",  "Detail": "Unsupported comparison operator: 'ne'",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` All GET `/Users/{externalId}` requests return a User object with following structure: **User Object Properties:** - `id` - User's external ID - `userName` - User's login name (without domain if email for non-generic Idps) - `active` - User's active status (boolean) - `emails` - Array of email objects with value, primary properties - `name` - Object with givenName and familyName properties - `meta` - Metadata object with resourceType: "User" - `schemas` - Array of SCIM schema identifiers #### Error Responses **404 Not Found - User Not Found:** ```json {  "Detail": "User with External ID 'external-user-id-404' was not found.",  "Status": 404,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` #### Examples Get first 5 external users: ```json GET /{externalIdp}/scim/Users?startIndex=1&count=5 ``` Get external users starting from a position: ```json GET /{externalIdp}/scim/Users?startIndex=10&count=20 ``` Find user by username: ```json GET /{externalIdp}/scim/Users?filter=userName eq "john.doe" ``` Find user by username in all DocuWare users: ```json GET /{externalIdp}/scim/Users?allDocuWareUsers=true&filter=userName eq "jane.smith" ``` Find user by externalId: ```json GET /{externalIdp}/scim/Users?filter=externalId eq "external-user-id-123" ``` Get all DocuWare users with pagination: ```json GET /{externalIdp}/scim/Users?allDocuWareUsers=true&startIndex=1&count=50 ``` ### Create user (POST) #### How user creation works The system implements an intelligent user creation/update logic that follows these steps: 1. User Lookup by External ID: First attempts to find an existing user by the provided externalId, if one is found - that is a complete match and the existing user is being updated with the request attributes. 2. Fallback to Username Lookup: If no user is found by external ID, searches by username extracted from the `userName` field, if one is found and the incomming email matches the existing user email - that is a complete match and the existing user is being updated with the attributes from the request. Otherwise when emails do not match - new user fails to be created, because a user with the provided `userName` already exists. (resulting in a 409 Conflict) User Creation versus Update Logic: - **New User**: If no existing user is found by `externalID` or `userName`, creates a new user - **User Update**: If an existing user is found and matched either by `externalId` or `userName` + email, updates the user's information - **Email Validation**: When finding by `userName`, validates that the existing user's email matches the provided email (case-insensitive). If emails don't match, throws an exception to prevent conflicts > [!NOTE] > Notes on email address resolution service > > The service determines the user's email address using the following priority order: > > 1. **Primary Email**: Uses the email marked as primary: true in the emails array. > 2. **First Valid Email**: If no primary email exists, selects the first valid email from the emails array. > 3. **Validation**: If none of the above are valid email addresses, the request fails with a 400 Bad Request. #### Request ```json POST /{externalIdp}/scim/Users Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],  "userName": "john.doe@example.com",  "externalId": "external-user-id-123",  "active": true,  "name": {    "givenName": "John",    "familyName": "Doe"  },  "emails": [    {      "value": "john.doe@example.com",      "primary": true    }  ] } ``` #### Required and Optional Fields Required fields: - `schemas` - SCIM schema identifiers (must include both Core and Enterprise User schemas) - `userName `- User's login name (must be unique) - `externalId `- External identity provider user ID (must be unique) - `active` - User active status - `emails` - Array of email addresses Optional Fields: - `name` - User's display name object - `name.givenName` - First name - `name.familyName` - Last name Field Validation Rules: - **UserName**: Required, case-sensitive, must not be empty or whitespace - **ExternalId**: Required, case-sensitive, must not be empty or whitespace - **Emails**: At least one valid email must be resolvable (in case of multiple **Email Address Resolution** rules are respected) - **Active**: Boolean value - **Name fields**: Optional strings for display purposes #### Response **Success (200 OK):** ```json {  "userName": "john.doe",  "active": true,  "emails": [    {      "value": "john.doe@example.com",      "primary": true    }  ],  "name": {    "givenName": "John",    "familyName": "Doe"  },  "id": "external-user-id-123",  "meta": {    "resourceType": "User"  },  "schemas": [      "urn:ietf:params:scim:schemas:core:2.0:User",      "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"  ] } ``` #### Error Responses 400 Bad Request - Missing Required Fields: ```json {  "ScimType": "invalidValue",  "Detail": "Validation failed: UserName: is required",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` 409 Conflict - User already exists: ```json {  "ScimType": "uniqueness",  "Detail": "User with username 'john.doe' already exists with different email address!",  "Status": 409,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` ### Update user (PUT) - complete user replacement The PUT operation performs a complete replacement of a user resource. Unlike PATCH, which updates only specified fields, PUT replaces the entire user object with the provided data. #### Basic PUT Request ```json PUT /{externalIdp}/scim/Users/{externalId} Content-Type: application/scim+json Authorization: Bearer {token} {  "userName": "john.doe",  "externalId": "external-user-id-123",  "active": true,  "emails": [    {      "value": "john.doe@example.com",      "primary": true    }  ],  "name": {    "givenName": "John",    "familyName": "Doe"  },  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"] } ``` #### **Parameters** - `{externalIdp} `- External identity provider identifier (azure, okta, ping, onpremise, etc.) - `{externalId} `- The external ID of the user to update #### Required fields for PUT **All fields that are mandatory for user creation must be provided:** - `userName `- User's login name - `externalId` - External identity provider user ID - `active` - User active status (boolean, defaults to false if not provided) - `emails` - Array of email addresses (check **Email Address Resolution**) - `schemas` - SCIM schema identifiers (must include both Core and Enterprise User schemas) #### Optional fields (old values are persisted if new ones are not provided) - name - User's display name object - name.givenName - First name - name.familyName - Last name #### Complete PUT Example ```json PUT /azure/scim/Users/external-user-id-123 Content-Type: application/scim+json Authorization: Bearer {jwt-token} {  "userName": "john.smith",  "externalId": "external-user-id-123",  "active": false,  "name": {    "givenName": "John",    "familyName": "Smith"  },  "emails": [    {      "value": "john.smith@example.com",      "primary": true    }  ],  "schemas": [    "urn:ietf:params:scim:schemas:core:2.0:User",    "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"  ] } ``` #### Response Success (200 OK): ```json {  "userName": "john.smith",  "active": false,  "emails": [    {      "value": "john.smith@example.com",      "primary": true    }  ],  "name": {    "givenName": "John",    "familyName": "Smith"  },  "id": "external-user-id-123",  "meta": {    "resourceType": "User"  },  "schemas": [    "urn:ietf:params:scim:schemas:core:2.0:User",    "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"  ] } ``` #### Error Responses 400 Bad Request - Missing Required Fields ```json {  "ScimType": "invalidValue",  "Detail": "Validation failed: UserName: is required",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` 404 Not Found - User Not Found: ```json {  "Detail": "User with External ID 'external-user-id-404' was not found.",  "Status": 404,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` 409 Conflict - Duplicate Username: ```json {    "ScimType": "uniqueness",    "Detail": "User with username 'john.doe' already exists!",    "Status": 409,    "Schemas": [        "urn:ietf:params:scim:api:messages:2.0:Error"    ] } ``` 409 Conflict - Duplicate ExternalId: ```json {  "ScimType": "uniqueness",  "Detail": "User with External ID 'external-user-id-409' already exists!",  "Status": 409,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` 409 Conflict - Locked Resource: ```json {  "ScimType": "mutability",  "Detail": "The resource with ID 'external-user-id-409' is immutable.",  "Status": 409,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` #### Validation Rules for PUT All validation rules from POST operations apply to PUT operations: - **UserName**: Required, case-sensitive, must not be empty or whitespace - **ExternalId**: Required, case-sensitive, must not be empty or whitespace - **Active**: boolean value (defaults to `false` if not provided) - **Emails**: At least one valid email must be resolvable (in case of multiple **Email Address Resolution** rules are respected) - **Name Fields**: Optional but recommended for user experience - **Schemas**: Must include both Core and Enterprise User schemas ### Patch User (PATCH) operations guide The PATCH operation allows partial updates to user attributes using SCIM 2.0 patch operations. The service supports `replace` and `add` operations for user updates. #### **Basic PATCH structure:** ```json PATCH /{externalIdp}/scim/Users/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "replace",      "path": "attribute_path",      "value": "new_value"    },    {      "op": "add",      "path": "attribute_path",      "value": "new_value"    }  ] } ``` #### **Supported Operations** - `replace` - Update an existing attribute value - `add `- Update an empty/existing attribute value - `remove` - Not supported for user operations #### **Supported attribute paths** User Activity Status: ```json {  "op": "replace",  "path": "active",  "value": "false" } ``` Username update: ```json {  "op": "replace",  "path": "userName",  "value": "new.username" } ``` Name Fields: ```json {  "op": "replace",  "path": "name.givenName",  "value": "NewFirstName" } ``` ```json {  "op": "replace",  "path": "name.familyName",  "value": "NewLastName" } ``` Email address: ```json {  "op": "replace",  "path": "emails",  "value": "new.email@example.com" } ``` ```json {  "op": "replace",  "path": "emails[primary eq true].value",  "value": "new.email@example.com" } ``` **Notes:** - Both syntaxes for emails path are valid - Email address must be in valid email format External ID ```json {  "op": "replace",  "path": "externalId",  "value": "new-external-id-456" } ``` Multiple Operations Example: ```json PATCH /{externalIdp}/scim/Users/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "replace",      "path": "active",      "value": "false"    },    {      "op": "replace",      "path": "name.givenName",      "value": "Jonathan"    },    {      "op": "replace",      "path": "name.familyName",      "value": "Smith"    },    {      "op": "replace",      "path": "emails",      "value": "jonathan.smith@example.com"    }  ] } ``` > [!NOTE] > Important notes: > > - All operations are processed in sequence > - The `remove` operation is not supported and will return an error > - Email validation is performed for email-related fields > - The `active `field requires boolean string values ("true" or "false") > - Invalid attribute paths will result in a 400 Bad Request error > - If the `externalId` or `userName` is already taken by another user, that will result in a conflict error Error Handling: - **400 Bad Request**: Invalid operation type, unsupported path, or validation failure - **404 Not Found**: User with specified ID not found - **409 Conflict**: Update would create a conflict (e.g., duplicate username, externalId) #### Supported user attributes for PATCH operations - `userName` - User's login name - `externalId `- External identity provider user ID - `name.givenName` - First name - `name.familyName` - Last name - `active` - User active status (true/false) - `emails/emails[].value `- Email address ### Delete User (DELETE) The DELETE operation soft deletes a user from the DocuWare system. This operation deactivates the user. #### Basic DELETE Request ```json DELETE /{externalIdp}/scim/Users/{externalId} Authorization: Bearer {token} ``` Parameters: - `{externalIdp} `- External identity provider identifier (azure, okta, ping, etc.) - `{externalId} `- The external ID of the user to delete #### Request Example ```json DELETE /azure/scim/Users/external-user-id-123 Authorization: Bearer {jwt-token} ``` #### Response Success (204 No Content): ```json HTTP/1.1 204 No Content Content-Type: application/scim+json ``` The DELETE operation returns HTTP 204 (No Content) with an empty response body when successful. #### Error Responses 404 Not Found - User Not Found: ```json {  "Detail": "User with External ID 'ExternalUser112' was not found.",  "Status": 404,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` 409 Conflict - User is currently locked and cannot be deleted: ```json {  "ScimType": "mutability",  "Detail": "The resource 'ExternalUser11' with ID 'ExternalUser11' is immutable.",  "Status": 409,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` Alternative to deletion: Instead of deleting a user, alternative is deactivating them using a PATCH or PUT operation: ```json PATCH /{externalIdp}/scim/Users/{externalId} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "replace",      "path": "active",      "value": "false"    }  ] } ``` ## Group Management ### Group Schema (Core2Group) ### How Group Creation Works The system implements an intelligent group creation/update logic that follows these steps: 1. Group Lookup by DisplayName: First attempts to find an existing group by the provided `displayName`, if one is found it's treated as Group Update, otherwise - Group Creation 2. Group creation versus update logic: - New Group: If no existing group is found by `displayName`, creates a new group with the provided members - Group Update: If an existing group is found, updates the group's information and adds new members to the existing membership (does not replace existing members) - Member Addition: New members are added to existing groups without removing current members - Duplicate Prevention: The system prevents adding duplicate members to groups > [!NOTE] > Important Group Creation Notes: > > - Display Name Uniqueness: Groups are identified by their `displayName` > - Member Resolution: All member references (`value` field) must be valid `externalId` values of existing users > - Incremental Membership: POST operations on existing groups add members incrementally rather than replacing the entire membership > - Member Validation: The system only adds members that exist. If member with provided `value` (externalId) does not exist - it's being skipped with no error returned. > - External Identity Provider Scope: You can only manage the part of the group that consists of users from the current `externalIdp`. Users from other external identity providers or internal DocuWare users remain unaffected by these operations. > - Response: The response includes only group members who are external users provisioned by the specified `externalIdp` (such as azure, okta, ping, onpremise or generic). Internal users or users created by other external identity providers are excluded from the response. Member reference format: - Members are referenced by their` externalId` (not internal DocuWare user ID) - Each member object must contain a `value `field with the user's external ID - Optional `display` field (users `userName`) can be provided but is not required for membership assignment ### Create Group (POST) ```json POST /{externalIdp}/scim/Groups Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],  "displayName": "Engineering Team",  "members": [    {      "value": "external-user-id-123"    },    {      "value": "external-user-id-456"    }  ] } ``` #### Response ```json {  "displayName": "Engineering Team",  "members": [    {      "value": "external-user-id-123",      "display": "john.doe"    },    {      "value": "external-user-id-456",      "display": "jane.smith"    }  ],  "id": "12345678-1234-1234-1234-123456789012",  "meta": {    "resourceType": "Group"  },  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"] } ``` **Empty Group Creation:** ```json POST /{externalIdp}/scim/Groups Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],  "displayName": "Future Project Team",  "members": [] } ``` **Mandatory Fields:** - `schemas` - SCIM schema identifiers (must include `"urn:ietf:params:scim:schemas:core:2.0:Group"`) - `displayName` - Group's display name (used for identification) - `members` - Array of member objects (can be empty for group creation) - `members[].value `- User's external ID (required if members are specified) #### Error Responses **400 Bad Request - Missing Required Fields:** ```json {  "ScimType": "invalidValue",  "Detail": "Validation failed: DisplayName: is required",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` ```json {  "ScimType": "invalidValue",  "Detail": "Validation failed: Members: The Members field is required.",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` ```json {  "ScimType": "invalidValue",  "Detail": "Validation failed: Members[0].Value: Member Value is required.",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` ### Get groups (GET) The GET Groups endpoint supports multiple variants for retrieving group data with optional filtering and pagination. Groups include members that are external users from the specified external identity provider. #### 1. Get all groups (default) ```json GET /{externalIdp}/scim/Groups Authorization: Bearer {token} ``` Returns all groups that exist in DocuWare, without returning the members, they can be queried with the GET request: /Groups/{groupId} Response: ```json {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],  "totalResults": 2,  "itemsPerPage": 2,  "startIndex": 1,  "resources": [    {      "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],      "id": "group-id-123",      "displayName": "Engineering Team",      "meta": {        "resourceType": "Group"      }    },    {      "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],      "id": "group-id-456",      "displayName": "Marketing Team",      "meta": {        "resourceType": "Group",      }    }  ] } ``` #### 2. Get Specific Group by ID ```json GET /{externalIdp}/scim/Groups/{groupId} Authorization: Bearer {token} ``` Retrieves details for a specific group using its group ID. The `members` attribute includes only external users provisioned by the specified identity provider. **Response:** ```json {  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],  "displayName": "Engineering Team",  "members": [    {      "value": "external-user-id-123",      "display": "john.doe",    },    {      "value": "external-user-id-456",      "display": "jane.smith",    }  ],  "id": "group-external-id-123",  "meta": {    "resourceType": "Group"  } } ``` #### 3. Query Groups with Filtering Filter by Display Name: ```json GET /{externalIdp}/scim/Groups?filter=displayName eq "Engineering Team" Authorization: Bearer {token} ``` Get Groups with Pagination: ```json GET /{externalIdp}/scim/Groups?startIndex=1&count=10 Authorization: Bearer {token} ``` ```json GET /{externalIdp}/scim/Groups?startIndex=2&count=5 Authorization: Bearer {token} ``` #### Supported Query Parameters Filtering: - `filter `- SCIM filter expression (supports only displayName eq "value") (case-insensitive, exact match) **Pagination:** - `startIndex `- 1-based index of the first result (default: 1, minimum: 1) - `count `- Number of results per page (default: all results if not specified, minimum: 0) #### Response Format All GET /`Groups` requests return a SCIM ListResponse with the following structure: **ListResponse Properties:** - `schemas` - Array containing `"urn:ietf:params:scim:api:messages:2.0:ListResponse"` - `totalResults `- Total number of matching groups - `itemsPerPag`e - Number of groups returned in current response - `startIndex` - Starting index of current page (1-based) - `resources `- Array of group objects (members attribute available only when fetched by group ID) **Group Object Properties:** - `id` - Group's external ID - `displayName` - Group's display name - `members` - Array of member objects (only external users from the specified `externalIdp`) - `value `- Member's external user ID - `display` - Member's username - `meta `- objects resource type - `schemas` - Array containing SCIM schema identifiers #### > [!NOTE] > Notes about group responses > > **Member Filtering:** > > - Only members who are external users managed by the specified {`externalIdp`} are included in responses > - Internal DocuWare users and users from other external identity providers are excluded > - Empty groups (no qualifying members) may still appear in results if they exist > > **Group Identification:** > > - Groups are identified by their `ID `for GET operations > - The displayName is used for filtering and group lookup during creation/updates #### Error Responses 400 Bad Request - Invalid Filter: Filtering by wrong attribute: ```json {  "ScimType": "invalidFilter",  "Detail": "Unsupported filter attribute: id",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` Filtering with invalid expression (only valid is - filter=displayName eq "groupName"): ```json {  "ScimType": "invalidFilter",  "Detail": "Invalid filter expression: 'displasyname asd \"engineering team\"'",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` Filtering with unsupported comparison operator: ```json {  "ScimType": "invalidFilter",  "Detail": "Unsupported comparison operator: 'ne'",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` 404 Not Found - Group Not Found: ```json {  "Detail": "Group with identifier 'group-id-404' was not found.",  "Status": 404,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` ### Update Group Membership (PATCH) The PATCH operation allows partial updates to group attributes using SCIM 2.0 patch operations. The service supports add, remove and replace(only for group displayName) operations for group management. #### Basic PATCH Structure ```json PATCH /{externalIdp}/scim/Groups/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "operation_type",      "path": "attribute_path",      "value": "new_value_or_array"    }  ] } ``` #### Supported Operations Add Members (`add`): adds new members to the group without removing existing members. ```json vPATCH /{externalIdp}/scim/Groups/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "add",      "path": "members",      "value": [        {          "value": "external-user-id-789"        },        {          "value": "external-user-id-101"        }      ]    }  ] } ``` Remove specific members (`remove`): removes specified members from the group. ```json PATCH /{externalIdp}/scim/Groups/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "remove",      "path": "members",      "value": [        {          "value": "external-user-id-123"        },        {          "value": "external-user-id-456"        }      ]    }  ] } ``` Remove All Members (`remove`): removes all members that are users created by the provided externalIdp from the group (empties the group). ```json PATCH /{externalIdp}/scim/Groups/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "remove",      "path": "members"    }  ] } ``` When no `value `is provided with remove operation, all external members (from the provided externalIdp) are removed. 1. **Replace Group Display Name (**replace**)** Updates the group's display name. ```json PATCH /{externalIdp}/scim/Groups/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "replace",      "path": "displayName",      "value": "Updated Team Name"    }  ] } ``` #### Supported Attribute Paths | **Path** | **Operations** | **Description** | **Value Format** | | --- | --- | --- | --- | | `displayName` | `replace, add` | Group display name | String | | `members` | `add, remove` | Group membership | Array of member objects | #### Multiple Operations in Single Request You can combine multiple operations in a single PATCH request: ```json PATCH /{externalIdp}/scim/Groups/{id} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],  "Operations": [    {      "op": "replace",      "path": "displayName",      "value": "DevOps Engineering Team"    },    {      "op": "add",      "path": "members",      "value": [        {          "value": "external-user-id-new1"        }      ]    },    {      "op": "remove",      "path": "members",      "value": [        {          "value": "external-user-id-old1"        }      ]    }  ] } ``` #### Member Object Format When specifying members in operations, use this format: **Required Fields:** - `value` - The external ID of the user to add/remove **Example Member Object:** ```json {  "value": "external-user-id-123" } ``` #### Operation Behavior Details **Add Operation:** - Adds specified members to the group - Ignores members that are already in the group (no duplicates) - Non-existent user external IDs are silently ignored - Does not affect existing members **Remove Operation:** - With `value`: Removes only the specified members (if they are users created from provided externalIdp) - Without `value`: Removes all members (users created from provided externalIdp) from the group - Ignores external IDs that are not current members - Does not affect non-specified members **Replace Operation:** - For `displayName`: Updates the group name #### Responses - Successful PATCH Response (204 No Content) - 400 Bad Request - Invalid Operation - 400 Bad Request - Invalid Path - 400 Bad Request - Invalid Member Format - 404 Not Found - Group Not Found - 409 Conflict - Group Name Already Exists #### Important PATCH Operation Notes **Operation Processing:** - Operations are processed sequentially in the order they appear **Member Validation:** - User external IDs must reference existing users - Invalid external IDs are silently ignored (no error thrown) - Only external users from the same identity provider (`externalIdp`) are managed **Group State:** - The response includes only external users from the specified `{externalIdp}` - Internal DocuWare users and users from other identity providers are excluded from responses - Empty groups remain valid and are included in responses ### Update Group (PUT) - Complete Group Replacement The PUT operation performs a complete replacement of the group part provided by the externalIdp. Unlike PATCH, which updates only specified fields, PUT replaces the entire group object with the provided data. #### Basic PUT Request ```json PUT /{externalIdp}/scim/Groups/{groupId} Content-Type: application/scim+json Authorization: Bearer {token} {  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],  "displayName": "Updated Engineering Team",  "members": [    {      "value": "external-user-id-123"    },    {      "value": "external-user-id-456"    }  ] } ``` #### Parameters - `{externalIdp} `- External identity provider identifier (azure, okta, ping, etc.) - `{groupId} `- The ID of the group to update #### Required Fields for PUT All fields that are mandatory for group creation must be provided: - `schemas` - SCIM schema identifiers (must include `"urn:ietf:params:scim:schemas:core:2.0:Group"`) - `displayName` - Group's display name - `members` - Array of member objects (can be empty) #### Complete PUT Example ```json PUT /azure/scim/Groups/group-id-123 Content-Type: application/scim+json Authorization: Bearer {jwt-token} {  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],  "displayName": "DevOps Engineering Team",  "members": [    {      "value": "external-user-id-789"    },    {      "value": "external-user-id-101"    }  ] } ``` #### Response Success (200 OK): ```json {  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],  "id": "group-id-123",  "displayName": "DevOps Engineering Team",  "members": [    {      "value": "external-user-id-789",      "display": "john.doe",    },    {      "value": "external-user-id-101",      "display": "jane.smith",    }  ],  "meta": {    "resourceType": "Group"  } } ``` > [!NOTE] > Important PUT Behavior Notes > > 1. **Complete Member Replacement**: PUT replaces the entire member list managed by current `externalIdp`. Any member not included in the request will be removed from the group. > 2. **Display Name Update**: The group's display name can be changed using PUT operations. > 3. **Member Validation**: All specified member external IDs must reference existing users. Invalid external IDs will be skipped silently. > 4. **External Identity Provider Scope**: Only members who are external users from the specified `{externalIdp}` are managed by this operation. Internal DocuWare users and users from other identity providers remain unaffected. > 5. **Group Identification**: The group is identified by the` {groupId}` parameter in the URL. #### Error Responses 400 Bad Request - Missing Required Fields: ```json {  "ScimType": "invalidValue",  "Detail": "Validation failed: DisplayName: is required",  "Status": 400,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` 404 Not Found - Group Not Found: ```json {  "Detail": "Group with identifier 'group-id-404' was not found.",  "Status": 404,  "Schemas": [      "urn:ietf:params:scim:api:messages:2.0:Error"  ] } ``` #### Validation Rules for PUT All validation rules from POST operations apply to PUT operations: - **DisplayName**: Required, case-sensitive, must not be empty or whitespace - **Members**: Optional array, each member must have a valid value field with existing user's external ID - **Member External IDs**: Must reference existing users from the same external identity provider - **Schemas**: Must include the Core Group schema ### Delete Group (DELETE) - Not Supported The DELETE operation for groups is **not supported** by the DocuWare User Provisioning v3 Service. Attempting to delete a group will result in an error response. ## HTTP Status Codes | **Status Code** | **Description** | **When Used** | | --- | --- | --- | | 200 OK | Success | GET, PATCH operations | | 201 Created | Resource created | POST operations | | 204 No Content | Success, no content | DELETE, some PATCH operations | | 400 Bad Request | Invalid request | Validation errors | | 401 Unauthorized | Authentication required | Missing/invalid token | | 403 Forbidden | Access denied | Insufficient permissions | | 404 Not Found | Resource not found | Invalid resource ID | | 409 Conflict | Resource conflict | Duplicate username/email | | 500 Internal Server Error | Server error | Service issues | | 501 Not Implemented | Not supported | Not supported by product | ## Error Response Format ```json {  "ScimType": "invalidValue",  "Detail": "Validation failed.",  "Status": 400,  "Schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"] } ``` ## Configuration Requirements ### Identity Provider Setup 1. Configure your IdP to point to the appropriate tenant URL 2. Set up OAuth 2.0/OIDC authentication with JWT tokens 3. Configure the correct scopes: `docuware.userProvisioning` 4. Make sure the user performing API operations has sufficient permissions. ### Supported Identity Providers - **Azure Entra ID (Azure AD)**: Use `azure` as externalIdp - **Okta**: Use `okta` as externalIdp - **Ping Identity**: Use `ping` as externalIdp - **On-Premise**: Use `onpremise` as externalIdp - **Generic Idp** ## Schema Information ### Get Available Schemas ```json GET /{externalIdp}/scim/Schemas Authorization: Bearer {token} ``` ### Get Resource Types ```json GET /{externalIdp}/scim/ResourceTypes   Authorization: Bearer {token} ``` ## Health Check ### Service Availability ```json GET /AvailabilityCheck ``` This endpoint requires no authentication and returns 200 OK if the service is running. ## Example Integration Workflows ### Complete User Provisioning Workflow 1. **Create User**: POST to `/Users` with user details 2. **Verify Creation**: GET `/Users/{id}` to confirm 3. **Update User**: PATCH `/Users/{id}` for changes 4. **Add to Groups**: PATCH `/Groups/{groupId}` to add user 5. **Deactivate**: PATCH `/Users/{i`d} with `active: false` ### Group Management Workflow 1. **Create Group**: POST to `/Groups` with group details 2. **Add Members**: PATCH `/Groups/{id}` with add operations 3. **Update Name**: PATCH `/Groups/{id}` with displayName change 4. **Remove Members**: PATCH /`Groups/{id}` with remove operations This API provides a robust, standards-compliant interface for managing users and groups in DocuWare through external identity providers while maintaining security and performance best practices. ## Supported versions: DocuWare Cloud + 7.14 + 7.13