# SailPoint Web Services SaaS Connector Documentation
> Web Services SaaS Connector Documentation
# Documentation
# Configuration Parameters
For the Web Services source you can configure the values of the following attributes using the SailPoint REST API. For the usage of the SailPoint REST APIs for the following attributes and keys, refer to:
- API to get source details - [list-sources]()
- API to get a specific source's current schema details - [list-schemas]()
- API to add a new schema attribute to a source - [create-schema]()
- [SailPoint REST API - Update Source (Partial)]()
## createAccountWithEntReq
By default, the Web Services source creates an account for a `Create Account` operation and then adds the entitlements one by one. For example, if there are three entitlements (Role, Group, Profile), the source executes three requests and three API calls are sent.
Adding the `createAccountWithEntReq` attribute merges all the entitlement requests in a single API call. Use the `createAccountWithEntReq` attribute key with the value `true` to enable the functionality of sending entitlements with create account in a single request to the managed system.
Default value: `false`
## possibleHttpErrors
When an API endpoint does not send expected error codes to flag failure conditions, the connector can be configured with all possible HTTP error codes and messages that the API endpoint returns, which result in failure of operations.
Use the `possibleHttpErrors` attribute with `["errorCodes","errorMessages"]` as the value.
Occasionally, the Web Services connector returns the HTTP status code `200` but the response payload may contain errors. In this case, the connector must fail the request, or an OAuth token generation must try to regenerate the token.
You can also configure these possible HTTP error codes and messages to specify invalid or expired token errors. In this case, the connector regenerates and saves the token for OAuth 2.0 authentication, then retries the operation with the newly generated access token.
> [!NOTE]
>
> This flag is not applicable for child endpoints.
## objectNotFoundErrorMsg
Based on the error message list, the source decides whether to display the `objectNotFoundErrorMsg` error. For example, you can create an entry for `objectNotFoundErrorMsg` with a custom error message to identify multiple exceptions by setting the `objectNotFoundErrorMsg` attribute key with `["404: Not Found", "404"]` as the value.
## updateAttrWithChangePassword
To enable single requests for change password and update operations, use the `updateAttrWithChangePassword` attribute key with `true` as a value.
If the value of the `updateAttrWithChangePassword` attribute is `true` in the source and the plan contains no attribute request named "password" (change password), then the specific Update operation type endpoint is invoked.
Setting the value of the `updateAttrWithChangePassword` attribute to `true` does not include requests for add or remove entitlements. These requests are executed independently.
## disableCookies
By default, the Web Services source supports cookies. Disable cookies by adding the `disableCookies` attribute key with `true` as a value. This attribute is not applicable for the authentication API call operation.
## addRemoveEntInSingleReq
Add or remove multiple entitlements such as Role, Permissions, or Profile. To send multiple entitlement requests in a single request to the managed system, set the value of the `addRemoveEntInSingleReq` parameter to `true` as shown in the following example:
```xml
true
```
If `addRemoveEntInSingleReq` is set to `true`, then the payload for entitlements must also be set as shown in the following example:
```text
{"group_id" : $plan.groups$,
"permission":$plan.permission$,
"roles": $plan.roles$
}
```
## skipGetObjectInCreate
The Web Services SaaS connector supports the `skipGetObjectInCreate` attribute (Boolean) to skip the `getObject` call if it is present during the Create provisioning operation.
## deleteStatus
This attribute marks whether an object is deleted during delta aggregation. To set the value of `deleteStatus`, set the value as shown in the following example:
```xml
```
## retryDelay
By default, the connector waits 30 seconds between automatic retries for HTTP 429 and HTTP 503 errors. The connector performs a maximum of three retries per request. The connector determines the delay in the following order:
- `retryDelay` - If this attribute is set to a positive integer on the source, the connector uses this fixed value first.
- `Retry-After` header - If no valid `retryDelay` exists, the connector uses the numeric value (in seconds) provided in the `Retry-After` header.
- Fallback - If neither of the previous values is valid or present, the connector defaults back to 30 seconds.
> [!NOTE]
>
> Additional configurable attributes are available beyond those documented here. Refer to the SailPoint REST API links above to list a source's current configuration and confirm available attribute keys before setting a new one.
## Configuration for Response
When configuring the Web Services source, map the schema attribute as follows for JSON and XML.
### JSON Response Configuration
Single endpoint - In a JSON response, all the attributes can be mapped as follows, considering the Root Path as `$.list`:
```text
Id = id
displayName = displayName
username = jive.username
enabled = jive.enabled
emails = emails[*].value
```
Multiple endpoints - Refer to the following response example for the first and second endpoints:
| Type | Response Example | Response Mapping |
| --- | --- | --- |
| First endpoint | `{"meta": {...}, "resources": ["01dcc3dd-5b72-4fb2-a43b-424e092bd6af", "032b704e-1467-48b3-ad70-29a04f1a20ab", "042ab092-918f-4ed3-97eb-196fbe917e77"], "errors": []}` | Response Attribute Mapping: `uid = $`. Root Path: `$.resources.*` |
| Second endpoint | Context URL - `/users/entities/users/v1?ids=$response.uid$`. Example: `{"meta": {...}, "resources": [{"uid": "john.doe@santander.us", "firstName": "John", "lastName": "Doe", "uuid": "01dcc3dd-5b72-4fb2-a43b-424e092bd6af", "customer": "81971f9d094d494bae5a5fd97052509f"}], "errors": []}` | Response Attribute Mapping: `firstName = $.resources[0].firstName`, `lastName = $.resources[0].lastName`. Root Path: not required |
Parsing JSON array - The following is an example for parsing a JSON array:
```json
[1,10,21,31,46,89,90,67,88,98,101]
```
The response mapping for the above example is:
- Response Attribute Mapping (`id` is an attribute in the schema): `id = $`
- Root Path: `$.*`
### XML Response Configuration
Example 1 - XML response for mapping:
```xml
.....
true
User
123456
Alias
CName1
test@test.com
false
test@test.com
Test
Test
1
```
Example 2 - XML response for mapping:
```xml
DillardsEveryone
example@example.com
gage5.test5@test5.dillards.com
```
For more specific examples of the JSON and XML format responses or inputs for the supported fields or operations on the Web Services source, refer to [Operations Reference]().
# Configuring Web Services SaaS for Integration
> [!WARNING]
>
> When configuring the source, do not hard code sensitive data. If sensitive data is hard coded, it can lead to that data being exposed when moving to a production environment. SailPoint recommends putting sensitive information in the encrypted attribute value list in the application XML and then using the encrypted variable name when configuring the source. For example, if you want to add the custom variable `Custom_Variable` in the encrypted list, append the variable name in the following list: ``
This section describes the various configurations to be performed to support the following features.
## Pass-Through Authentication
Configure Pass-Through Authentication on existing Web Services.
1. On the **Additional Settings** page, select the **Get Object Required for Pass-Through Authentication** checkbox.
> **Notes**
>
> - When selected, it executes the Get Object operation to verify if the entered Username (considered an identity attribute) is present on the managed system or not.
> - When deselected, it skips the Get Object operation and the Pass-Through Authentication operation must have response mapping with account object schema attributes.
2. (Optional) If you need to configure error messages for Pass-Through Authentication, use the following entry keys:
- `objectNotFoundErrorMsg`
- `authenticationFailedErrorMsg`
- `expiredPasswordErrorMsg`
The following process is an example to configure Pass-Through Configuration.
### Pass-Through Authentication General Information
1. In the **Operation Name** field, enter `Pass-Through Authentication` as the operation name.
2. From the **Operation Type** dropdown list, select **Pass-Through Authentication**.
3. In the **Authentication URL** field, enter the URL specific to the Pass-Through Authentication.
4. In the **HTTP Method** dropdown list, select **POST**.
### Pass-Through Authentication Header and Body
The HTTP body is used to post data with a request. The Header has the data keys and their corresponding values. These key-value pairs are sent as part of the Header in the HTTP Request.
1. Under the **Header** tab, enter the following **Key**/**Value** pairs:
- **Key** = `SOAPAction`, **Value** = `urn:partner.soap.sforce.com/Soap/queryReq`
- **Key** = `Content-Type`, **Value** = `text/xml`
Refer to [Header]() for more information.
2. Under the **Body** tab, select the **Raw** radio button.
3. In the **Body** field, enter the XML payload for the Pass-Through Authentication.
> **Note**
>
> The Body has two types: Form Data and Raw. XML format does not support Form Data.
> **XML Payload Example**
>
> ```xml
> xmlns:urn=urn:partner.soap.sforce.com">
>
>
>
>
>
>
>
>
> $authenticate.username$
> $authenticate.password$
>
>
>
> ```
Refer to [Body]() for more information.
### Pass-Through Authentication Response Information
Refer to [Response Information]() for more information.
The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
1. In the **Root Path** field, enter `//ns:userInfo`.
2. In the **Success Code** field, enter `2**`.
### Pass-Through Authentication Response Mapping
Refer to [Response Mapping]() for more information.
Enter the following **Schema Attribute** and **Attribute Path** pairs:
- **Schema Attribute** = `Username`, **Attribute Path** = `ns:userName`
- **Schema Attribute** = `email`, **Attribute Path** = `ns:userEmail`
- **Schema Attribute** = `firstName`, **Attribute Path** = `ns:firstName`
### Pass-Through Authentication XPath Namespace Mapping
Refer to [XPath Namespace Mapping]() for more information.
Enter the following **Namespace Prefix** and **Namespace URI** pairs:
- **Namespace Prefix** = `soapenv`, **Namespace URI** = `http://schemas.xmlsoap.org/soap/envelope/`
- **Namespace Prefix** = `ns`, **Namespace URI** = `urn:partner.soap.sforce.com`
- **Namespace Prefix** = `xsi`, **Namespace URI** = `http://www.w3.org/2001/XMLSchema-instance`
## Multiple Independent Endpoints
Web Services allows aggregation from multiple independent endpoints. The Web Service depends upon the **Operation Type** and the **Parent Endpoint** configuration to determine whether the endpoints of type Aggregation or Get Object must be executed independently.
- When Aggregation and Get Object endpoints need to aggregate attributes from multiple endpoints in a chained manner, the administrator must configure the parent endpoint name in every child endpoint. There has to be a dependency between the first and subsequent endpoints. The parent endpoint must be explicitly configured using the **Parent Endpoint** configuration tab.
- If multiple child endpoints are configured for any given endpoint, then the sequence of execution of child endpoints is determined by the sequence in which they have been configured in the application. For example, if account aggregation requires attributes from four different endpoints (EP1, EP2, EP3, and EP4), then:
1. EP1 aggregates userId and primary email.
2. EP2 aggregates personal information using userId.
3. EP3 aggregates skill ID information using primary email.
4. EP4 aggregates skill name using skill ID from EP3.
Where EP = Endpoint and RO = Resource Object/Account object.
### Configuring Multiple Independent Endpoints for Aggregation
- For a target system where accounts are aggregated from multiple endpoints and there is no relationship between such endpoints, you can configure Web Services to aggregate information from independent endpoints.
- Each endpoint can be configured independently using the same **Operation Type**. No parent endpoint configuration is required.
- Every independent endpoint can have a paging of its own, if applicable.
- Every endpoint collects resource objects from the configured Web Service. Upon completion of collecting all information, the next independent endpoint is triggered for collecting resource objects. For example, if there are two endpoints EP1 and EP2, then EP1 aggregates accounts from a certain geographic location and EP2 aggregates from another.
| Endpoint Name | Child Endpoint(s) | Returns | |
| --- | --- | --- | --- |
| EP1 | EP2, EP3, EP5 | RO(1, RO(2), RO(3,4), RO(5)), RO(6,7), RO(8) | Independent |
| EP2 | \- | RO(2) | Child of EP1 |
| EP3 | EP4 | RO(3,4) | Child of EP1 |
| EP4 | | RO(4) | Child of EP3 |
| EP5 | | RO(5) | Child of EP1 |
| EP6 | EP7 | RO(6,7), RO(8) | Independent |
| EP7 | | RO(7) | Child of EP6 |
| EP8 | | RO(8) | Independent |
> [!NOTE]
>
> **Screenshot**
>
> [![Multiple Independent Endpoints]()]()
> [!NOTE]
>
> The **Parent Endpoint** configuration tab displays for existing Web Services SaaS sources. However, any changes to the parent configuration have no effect on such applications and the operations behave per the previous endpoint chaining rules: the first endpoint of the specific operation type is the parent and subsequent endpoints of the same operation type are its child endpoints.
### Parent Endpoint
The Parent Endpoint tab displays for aggregation operations. Refer to [Aggregation]() for more information.
> [!NOTE]
>
> **Screenshot**
>
> [![Parent Endpoint]()]()
1. Select the **Parent Endpoint** from the dropdown list.
2. Select **Save**.
## Enabling Single API Calls
The Web Services connector supports sending data for multiple users in a single API call. If the managed system supports sending data for multiple users in a single call, the single API call can be enabled or configured by adding the `evalPattern`.
Add the following evaluation pattern function to the **Body** or **URL** to send attributes in the request:
```text
evalPattern(pattern,delimiter,count)
```
The following table describes the terminology used in the above evaluation pattern (`evalPattern`) function, which is used to specify the repeated pattern of attributes data to be resolved:
| Attributes | Description |
| --- | --- |
| `pattern` | Repeated pattern for a set of users in the request. |
| `delimiter` | Delimiter for the repeated patterns. |
| `count` | (Optional) Specifies the number of users' data to be sent with the request endpoint. The default value is 10 for query parameters and 50 for Body parameters. |
For example, consider the Get Users data API:
- **Required URL**:
```text
http://Hostname:8080/identityiq/scim/v2/Users?filter=userName eq "spadmin" or userName eq "abhijit" or userName eq "wadekar" or userName eq "imran" or userName eq "test"
```
- **Modified URL** - The following modified URL used to get users data API has an `evalPattern` placeholder which is replaced with resolved information. The placeholder string is replaced by five repeated patterns of `userName` placeholders and a separator.
```text
http://Hostname:8080/identityiq/scim/v2/Users?filter=evalPattern("userName eq $response.userName$"," or ",5)
```
> [!NOTE]
>
> **Notes**
>
> - This functionality is not applicable for the first aggregation endpoint.
> - If the API supports sending limited user data, then it must be specified in `evalPattern(count)` to avoid failures.
Merging of resources is done based on the ID for each endpoint which are provided as placeholders in the pattern. For example:
```text
$response.userName$ (userName)
```
Refer to [Customizers]() and [Dataset Management]() for more information on other SaaS-only configuration capabilities.
# Connecting SailPoint and Web Services SaaS
When you add the source in SailPoint, choose whether to add it using **Standard Setup** or the **Connectivity Agent**:
- **Standard Setup**: Provide the basic configuration to create the source, then proceed with the remaining source setup.
- **Connectivity Agent**: Set up your source using an AI-based agent that provides contextual recommendations for complex configurations. Refer to [Connectivity Agent Setup]() for more information.
## Standard Setup
To connect SailPoint with Web Services, perform the following tasks:
## Adding the Source in SailPoint
To connect to SailPoint, perform the following steps. Once the connection is made, you can configure it to meet your company's needs.
> [!IMPORTANT]
>
> By default, the provisioning feature is **disabled**, and the connector only supports read-only operations. To support provisioning operations, you must manually enable the feature in the source configuration.
**To configure a new source:**
1. Sign in to SailPoint.
2. Go to **Admin \> Connections \> Sources**.
3. Select **Create New**.
4. Search for the connector by entering the name in the search box, and then select **Configure**.
5. In the **Source Name** field, enter a unique and descriptive name for your source. Source names cannot exceed 128 characters.
6. In the **Description** field, provide additional details about the source to help distinguish it from similar sources. This field allows a maximum of 2,000 characters.
7. In the **Source Owner** field, begin typing the name of an owner. Matches appear after you type two or more letters. For more information, refer to [Assigning a Source Owner]().
8. (Optional) Select a governance group to grant its members [source]() or [role]() sub-admin level oversight of the source and its access. For more information, refer to [Creating and Managing Governance Groups]().
9. If this source represents a primary system containing your organization's personnel records, select the **Authoritative Source** checkbox. For more information, refer to [Creating Identity Profiles]().
10. Select **Continue**. The source is created, and you are navigated to the **Source Setup \> Base Configuration** page. Continue to configure your connected source there.
## Base Configuration
Provide the base configuration parameters. Information you entered in the Create New Source dialog is automatically entered into the fields in the Base Configuration page. You can edit this information if necessary.
1. Enter a unique name and description for the source.
2. In the **Source Owner** dropdown list, select the identity that owns this source.
- To find a source owner, begin entering their name.
3. (Optional) If enabled for your organization, select the **Use a Credential Provider** checkbox to manage the source's authentication using a credential provider.
> **Note**
>
> To add a credential provider, go to **Admin \> Connections \> Credential Providers**. For more information about credential providers, refer to [Credential Providers]().
4. Configure the authentication to allow SailPoint to connect to the source. Refer to [Connection Settings](<#connection-settings>) for more information.
5. (Optional) In the **Governance Group for Source Management** dropdown list, select a governance group to associate with this source. For more information about governance groups, refer to [Associating Governance Groups with a Source]().
6. (Optional) Choose whether to enable or disable provisioning for the source. Provisioning is disabled by default.
- **Enable Provisioning** - Set the toggle to **Enabled** to allow the source to create, update, and deactivate accounts in the connected source system.
- **Disable Provisioning** - Set the toggle to **Disabled** to disable provisioning for the source. Disabling provisioning will prevent the creation, updating, or deactivating of accounts on this source.
7. Select **Save**.
## Connection Settings
The following information is required for SailPoint to connect and interact with Web Services SaaS.
1. Select **Connection Settings** from the menu.
2. Select an **Authentication Type**.
Select the authentication type your source uses. You can enter the supporting authentication information in the fields provided below your selection. The supporting fields that display change depending on your selected authentication type.
The SailPoint Web Services SaaS connector supports the following authentication types:
- [Basic Authentication](<#basic-authentication>)
- [API Token](<#api-token>)
- [OAuth 2.0](<#oauth-20>)
- [Custom Authentication](<#custom-authentication>)
### Basic Authentication
> [!NOTE]
>
> **Screenshot**
>
> [![Basic Authentication]()]()
1. From the **Authentication Type** dropdown list, select **Basic Authentication**.
2. In the **Base URL** field, enter the base URL to connect to the target managed system. For example:
`https://api.testurl.com`
3. Enter the **Username** and **Password** for the account with the required permissions to execute Web Services.
4. Configure the [Aggregation Settings]() and [Common Configuration]() settings that apply, then select **Save**.
### API Token
The connector can authenticate with the source using an API token. The API token you provide is saved to the `accesstoken` attribute in the application configuration. API tokens are given in the following format:
```text
token_type API_token
```
For example:
```text
Bearer ********
```
> [!NOTE]
>
> If the token type is not provided, then the connector automatically uses `Bearer`.
#### API Token Placeholders
You can reference a saved API token using a placeholder. The token placeholder can be provided as a variable across all endpoints for request components such as:
- Request URL
- HTTP Headers
- Request Body
The following is an example of an API token placeholder:
```text
$application.accesstoken$
```
You can define and use multiple API token placeholders if your configuration requires it. Refer to [Custom Authentication](<#custom-authentication>) for more information on API token placeholders.
> [!NOTE]
>
> **Screenshot**
>
> [![API Token]()]()
1. Select **API Token** as the **Authentication Type**.
2. Enter the **Base URL** to connect to the managed system. For example:
`https://api.testurl.com`
3. Enter the **API Token** specific to the managed system.
4. Configure the [Aggregation Settings]() and [Common Configuration]() settings that apply, then select **Save**.
### OAuth 2.0
For all the grant types that you can select, the following fields are common configuration. Other grant type details are described in the following subsections.
> [!NOTE]
>
> **Screenshot**
>
> [![OAuth 2.0]()]()
1. Select **OAuth 2.0** as the **Authentication Type**.
2. In the **Base URL** field, enter the base URL to connect to the target managed system. For example:
`https://api.testurl.com`
3. Enter the **Token URL**. The format is:
`https://{your domain}/token`
Web Services supports the replacement of attributes in the OAuth 2.0 token URL. For example, if you want to prepare a token URL with sensitive information such as **client\_secret**, `$application.client_secret$` can be used. The corresponding value is determined from the replaced location in the token URL.
4. For **OAuth Headers**, set up the custom headers as part of the access token. Web Services adheres to the generalized specifications of the OAuth 2.0 grant types. However, for some managed target systems, custom headers may be required to be part of the access token generation request. You can add the custom headers as an attribute.
> **Note**
>
> The Content-Type value can only be **application/x-www-form-urlencoded** when Authentication Type is selected as OAuth 2.0. If the managed system expects a Content-Type other than **application/x-www-form-urlencoded**, use Custom Authentication instead of OAuth 2.0.
5. In **OAuth Headers to Exclude**, enter the headers that you want to exclude. By default, an Authorization BASIC header with a Base64-encoded client ID and client secret is part of the access token generation request. Some managed target systems do not support this header. If there is no Authorization BASIC header required for such managed target systems, it can be excluded from the request.
6. For **OAuth Request Parameters**, set up the custom parameters for an access token. For some managed target systems, custom request parameters may be required to be part of the access token generation request. You can add the custom request parameter as an attribute.
7. For **OAuth Body Attributes to Exclude**, enter the attributes that you want to exclude. To remove any of the standard request parameters that are not supported by managed target systems' access token generation requests, configure the request parameters to exclude from the access token request.
8. Select a **Grant Type** and complete its configuration:
- [Password Grant Type](<#password-grant-type>)
- [Client Credentials](<#client-credentials>)
- [Refresh Token](<#refresh-token>)
- [JWT Bearer Token](<#jwt-bearer-token>)
- [SAML Bearer Assertion](<#saml-bearer-assertion>)
9. Configure the [Aggregation Settings]() and [Common Configuration]() settings that apply, then select **Save**.
#### Password Grant Type
For the **Password** Grant Type:
> [!NOTE]
>
> **Screenshot**
>
> [![Password Grant Type]()]()
1. Select **Password** as the **Grant Type**.
2. Enter the **Username** and **Password** to authorize with the source.
#### Client Credentials
For the **Client Credentials** Grant Type:
> [!NOTE]
>
> **Screenshot**
>
> [![Client Credentials]()]()
1. Select **Client Credentials** as the **Grant Type**.
2. Enter the **Client ID** and its associated **Client Secret**. These are the client identification and secret for OAuth 2.0 authentication.
#### Refresh Token
For the **Refresh Token** Grant Type:
> [!NOTE]
>
> **Screenshot**
>
> [![Refresh Token]()]()
1. Select **Refresh Token** as the **Grant Type**.
2. Enter the **Client ID** and the associated **Client Secret** for OAuth 2.0 authentication.
3. Enter the **Refresh Token** used to generate the access token. Web Services supports OAuth 2.0 Refresh Tokens for the managed target system. The refresh tokens either don't expire or come with a long validity period.
#### JWT Bearer Token
For the **JWT Bearer Token** Grant Type:
> [!NOTE]
>
> **Screenshot**
>
> [![JWT Bearer Token]()]()
1. Select **JWT Bearer Token** as the **Grant Type**.
2. Enter the **Private Key** and **Private Key Password** to be used for JWT authentication.
3. Enter the **Client ID** and the associated **Client Secret** for OAuth 2.0 authentication.
4. In **JWT Header**, enter the following:
- **Key** - The Key is the algorithm that is used for signing the JWT assertion. It must be the same algorithm that you use for generating the private key. For example, you can use `alg`.
- **Value** - The Value is the JWT headers key. For example, you can use the value `RS256`. If required, additional header attributes can be provided in the key-value pair mentioned above.
5. In **JWT Payload**, enter the following:
- **Key** - The Payload Key enables you to include information on the JWT Claim. For JWT authentication, it is mandatory to have the payload key for a successful test connection and other operations. The mandatory attributes are:
- `aud` (Audience)
- `exp` (Expiry of the JWT assertion)
- `iss` (Issuer)
- `sub` (Subject)
If required, additional payload attributes can be provided in this key-value pair based on the target system.
- **Value** - The value of the Payload Key.
#### SAML Bearer Assertion
For the **SAML Bearer Assertion** Grant Type:
> [!NOTE]
>
> **Screenshot**
>
> [![SAML Bearer Assertion]()]()
1. Select **SAML Bearer Assertion** as the **Grant Type**.
2. Enter the **Client ID** and the associated **Client Secret** for OAuth 2.0 authentication.
3. Enter the **SAML Assertion URL** for generating a SAML Assertion. The SAML Assertion URL supports placeholders for replacement of the source attribute dynamically. For example, if a SAML Assertion URL is required to be prepared with some sensitive information such as a password, use `$application.saml_password$`. The corresponding value is determined from the source and replaced at the appropriate location in the SAML Assertion URL.
4. Enter the **SAML Request Body** that generates a SAML Assertion. SailPoint recommends that you use `$application.saml_username$` and `$application.saml_password$` placeholders in the request body to prevent exposing any sensitive data.
5. Enter the **Username** and **Password** for the service account with required permissions to execute Web Services.
6. In **SAML Headers**, enter the **Key** and respective **Value**. These are used for SAML assertion generation.
7. Enter any **SAML Headers to Exclude** which apply. By default, an Authorization BASIC header with a Base64-encoded resource username and resource password is part of the SAML Assertion generation request. Some managed target systems do not support such a header. If there is no Authorization BASIC header requirement for such target systems, it can be excluded from the request.
### Custom Authentication
When you select **Custom Authentication** as the **Authentication Type**, Web Services aggregates the authentication details for all other endpoints.
In custom authentication, the Web Services source doesn't authenticate requests and doesn't add any authorization to the HTTP header. To accomplish this, the REST application requires a new token to authenticate the request from the Authentication Server.
> [!IMPORTANT]
>
> If an endpoint does not require authentication at all, you only need to select **Custom Authentication**. Continue to the following steps to set up custom authentication.
> [!NOTE]
>
> **Screenshot**
>
> [![Custom Authentication]()]()
1. From the **Authentication Type** dropdown list, select **Custom Authentication**.
2. In the **Base URL** field, enter the base URL to connect to the target managed system. For example:
`https://api.testurl.com`
3. (Optional) Several optional fields display which you can configure as your authentication configuration requires:
- Username
- Password
- API Token
- Resource Owner Username
- Resource Owner Password
- Private Key
- Private Key Password
- Client ID
- Client Secret
- Refresh Token
4. Select **Save**.
5. Go to **HTTP Operations**, and select **Add Operation**. Set the **Operation Type** to **Custom Authentication**. Refer to [HTTP Operations]() for more information about using the HTTP Operations fields.
6. Configure the following for endpoints:
- **Authentication URL** - From the endpoint details page, enter the full URL in the **Authentication URL** field.
> **Note**
>
> Ensure that you enter the full URL in this field, unlike the other endpoints where this field takes in the context URL.
- **Header and Body**:
1. Configure the Header and Body with the required fields for the token generation.
2. Keys for sensitive attributes updated in the Header and Body must be appended in the encrypted list in the application.
> **Caution**
>
> Don't configure sensitive attributes for the Header and Body through the configuration UI. They should be added using the SailPoint Update Source Partial REST API. Refer to [SailPoint REST API - Update Source (Partial)]() for more information.
When you add sensitive attributes to the header, ensure that the attributes are added with the suffix `_CA`. For example, to use a password in the request, add `password_CA`.
> **Note**
>
> If the attributes are not suffixed with `_CA`, the Web Services source might display unusual behavior.
For example, if the attribute updated is a password, then it must be added to the header as follows.
Before updating the encrypted list:
```json
{"encrypted":"accesstoken,password,refresh_token,oauth_token_info,client_secret,private_key,private_key_password,clientCertificate,clientKeySpec,resourceOwnerPassword,custom_auth_token_info"}
```
After updating the encrypted list:
```json
{"encrypted":"accesstoken,password,refresh_token,oauth_token_info,client_secret,private_key,private_key_password,clientCertificate,clientKeySpec,resourceOwnerPassword,custom_auth_token_info,password_CA"}
```
After the attributes are added, their values can be used as placeholders in the Header and Body. For example:
```text
$application.password_CA$
```
- Use the `password_CA` attribute key with a value such as `xyz123`.
- Add the `password_CA` key to the existing encrypted attribute (comma-separated) using the SailPoint REST API.
- Use the `encrypted` attribute key and append `,password_CA` to the existing value.
- **Response Mapping** - Configure **Response Attribute Mapping** to obtain the access details from the response. Response mapping is the same as the other endpoints; the key is added under **Response Attribute** and its respective path must be added under **Attribute Path**.
> **Note**
>
> The value under **Response Attribute** must not be present in the schema. After response parsing, the value is stored in key-value format as follows:
>
> ```json
> {"accesstoken":"access_token"}
> ```
7. The token value generated after executing the **Custom Authentication** endpoint can be utilized in all other endpoints using placeholders as follows:
```text
"$application.$"
```
For example:
```text
"$application.accesstoken$"
```
If the token type is for a **Bearer** instance, then it can be used as follows:
```text
" $application.$"
```
For example:
```text
"Bearer $application.accesstoken$"
```
8. Configure the [Aggregation Settings]() and [Common Configuration]() settings that apply, then select **Save**.
## Review and Test
Perform a test to confirm the connection to SailPoint.
1. Go to **Review and Test**.
2. Confirm that the entries in each field are correct.
If you note any mistakes, return to the section and make corrections.
3. Select **Test Connection**.
## SailPoint Application Onboarding
SailPoint application onboarding enables you to easily onboard new applications and create sources following the successful onboarding of a discovery source. To use this feature, continue to **Discovered Applications** in the SailPoint user interface.
For more information, refer to [Application Onboarding]() in the SailPoint SaaS documentation.
# Connectivity Agent Setup
Select **Connectivity Agent \> Enable and Continue**.
> [!NOTE]
>
> By selecting **Enable and Continue**, you agree to [SailPoint's AI Terms]().
> [!NOTE]
>
> **Screenshot**
>
> [![Connectivity Agent]()]()
> [!NOTE]
>
> Select **Learn more** for more information about the following:
>
> - **Recommendations** - Suggested source configuration settings in SailPoint, generated by the Connectivity Agent using available documentation. Depending on the target application, these can include endpoints, operations authentication types, and aggregation types and related settings.
> - **Confidence Levels** - The strength of the documentation backing a recommendation:
>
> - **High** - The recommendation is based on the target application's official documentation.
> - **Low** - The recommendation is based on third-party documentation rather than the target application's official documentation.
> [!IMPORTANT]
>
> - **Errors**
>
> - If an error occurs while generating suggestions, select **Retry**.
> - If the error persists, select **Switch to Standard Setup** when the Connectivity Agent displays the option.
> - Select the **gear** icon in the top-right corner to switch to Standard Setup.
> - Only REST-based APIs are supported.
> [!WARNING]
>
> Switching to Standard Setup is permanent. You cannot return to Connectivity Agent setup, even if you go to the Sources page, select your source, and attempt to resume your configuration.
## Source Setup
1. On the **Source Setup** tab, enter the source name in the **Target System Name** field.
> **Note**
>
> The name must be between 2 and 50 characters.
2. In the Connectivity Agent panel, select **Save and Continue**. Wait while the Connectivity Agent generates recommendations.
> **Note**
>
> To generate new recommendations, edit the **Target System Name** and select **Refresh**.
3. Depending on the results, perform one of the following actions:
- If a match is found, select the target system.
- If multiple target systems are listed, select one from the list.
- If no results are found, enter a different name, select **Refresh**, and select the target system. If the error persists, select Switch to Standard Setup.
4. Select **Save and Continue**. Wait while the Connectivity Agent locates the account objects associated with the target system.
5. Depending on the results, perform one of the following actions:
- If an account object is found, select the account object.
- If multiple account objects are listed, select one from the list.
6. Select **Save and Continue**. Wait while the Connectivity Agent generates the connection recommendations. You are navigated to the Connections tab.
## Connections
1. On the **Connections** tab, review the authentication types listed in the Connectivity Agent panel. The available authentication types vary based on the target system you selected.
2. Select an authentication type, and select **Save and Continue**. Wait while the Connectivity Agent configures the Test Connection endpoint.
> **Important**
>
> The Connectivity Agent does not support custom authentication.
- Once the **Test Connection** endpoint is configured, enter the authorization credentials to connect to the source.
- If you want to test the connection, select **Test Connection**. If the test connection fails, select **View Test Connection Configuration** and configure the test connection endpoint.
- If you want to configure authentication later, leave the fields blank.
3. Select **Save and Continue**. Wait while the Connectivity Agent generates recommendations for the account aggregation. You are navigated to the HTTP Operations tab.
## HTTP Operations
Review and edit how the source accounts and its child endpoints are configured and how account entitlement information is collected.
### Account Aggregation
Overview:
1. **Account**:
1. Select the **Edit** icon for each account aggregation endpoint to review the configuration and update it if required. Refer to [HTTP Operations]() for more information.
2. You can manage the [Account Schema](<#account-schema>) and [Preview](<#preview>) the account aggregation configuration.
2. Select **Save and Continue**. Wait while the Connectivity Agent creates the child endpoints.
3. **Child Endpoints** (Optional):
1. Select one or more child endpoints and select **Save and Continue**. Wait while the Connectivity Agent configures the child endpoints. Select **Skip \> Save and Continue** to skip the child endpoint configuration and proceed with the next steps.
2. Select the **Edit** icon for each child endpoint (if configured) to review the configuration and update it if required. Refer to [HTTP Operations]() for more information.
3. You can manage the [Account Schema](<#account-schema>) and [Preview](<#preview>) the account aggregation configuration.
> **Note**
>
> If an error occurs while generating suggestions, select **Retry**. If the error persists, select **Save and Continue**. You are navigated to the Entitlement Aggregation tab.
### Account Schema
1. Select the **Account Schema** tab.
2. Review and update the schema through the following actions:
- To add a new attribute, select **Add New Attribute** and fill out all required fields. Select **Save** to save your changes and **Cancel** to discard your changes.
> **Note**
>
> Account attributes cannot exceed 128 characters.
- To edit a source's Account Name and Account ID attributes, select **Edit Schema**. Under **Account ID** and **Account Name**, choose the attributes that should be used to provide those values and select **Update**.
- To edit an attribute, select **Actions \> Edit**. Select **Update** to save your changes and **Cancel** to discard your changes.
- To delete an attribute, select **Actions \> Delete**. You can also select the checkbox beside attributes in this list and select **Delete Attributes**.
### Preview
1. Select the **Preview** tab.
2. Select **Preview** to generate and review the account aggregation configuration.
- If an error occurs, review the error details and select **Learn More** to access the documentation and resolve the issue. After resolving the issue, select **Preview** again to view the updated configuration.
- While the preview is generating, you can edit the **Overview** and **Account Schema** pages and select **Preview** again to view the updated configuration.
3. Select **Save and Continue**. Wait while the Connectivity Agent performs the account's preview. You are navigated to the Entitlement Aggregation tab.
### Entitlement Aggregation
> [!NOTE]
>
> If an error occurs while generating recommendations, select **Retry**. To skip and proceed, select **Save and Continue**.
Overview:
**Entitlement Aggregations**: Select the **Edit** icon for each entitlement aggregation endpoint to review the configuration and update it if required. Refer to [HTTP Operations]() for more information.
**Entitlement Schema**:
1. Select the **Entitlement Schema** tab.
2. Review and update the schema through the following actions:
- To add a new attribute, select **Add New Attribute** and fill out all required fields. Select **Save** to save your changes and **Cancel** to discard your changes.
> **Note**
>
> Entitlement attributes cannot exceed 128 characters.
- To edit a source's Entitlement ID and Entitlement Name attributes, select **Edit Schema**. Under **Entitlement ID** and **Entitlement Name**, choose the attributes that should be used to provide those values and select **Update**.
- To edit an attribute, select **Actions \> Edit**. Select **Update** to save your changes and **Cancel** to discard your changes.
- To delete an attribute, select **Actions \> Delete**. You can also select the checkbox beside attributes in this list and select **Delete Attributes**.
**Preview**:
1. Select the **Preview** tab.
2. Select **Preview** to generate and review the entitlement aggregation configuration.
- If an error occurs, review the error details and select **Learn More** to access the documentation and resolve the issue. After resolving the issue, select **Preview** again to view the updated configuration.
- While the preview is generating, you can edit the **Overview** and **Entitlement Schema** pages and select **Preview** again to view the updated configuration.
3. Select **Save and Continue**. Wait while the Connectivity Agent performs the entitlement's preview.
> **Note**
>
> If an error occurs while generating recommendations, select **Retry**. To skip and proceed, select **Save and Continue**.
4. Your aggregation configuration is now complete. Perform one of the following actions:
- **Complete the Source Setup** and review the final configuration.
- **Enable and Configure Provisioning** to configure provisioning operations.
5. Select **Save and Continue**. Wait while the Connectivity Agent performs the action. You are navigated to the respective tab.
## Provisioning (Optional)
1. The Connectivity Agent discovers whether the application supports write capabilities and populates the matching provisioning operations based on its search results.
> **Note**
>
> If an error occurs while generating recommendations, select **Retry**. To skip and proceed, select **Save and Continue**.
2. Select one, multiple, or all provisioning operations that you want your source to support.
> **Note**
>
> To configure provisioning operations later in Standard Setup, select **Skip** and select **Save and Continue**. You are navigated to the Review tab.
3. Select **Save and Continue**. Wait while the Connectivity Agent configures the provisioning endpoints for each operation.
4. On the **Provisioning** tab, select the **Edit** icon for each endpoint to review the configuration and update it if required. Refer to [HTTP Operations]() for more information.
5. Select **Save and Continue**. Wait while the Connectivity Agent completes the provisioning configuration. You are navigated to the Review tab.
## Review
1. On the **Review** tab, review the source configuration details you configured during each step:
- Source Setup
- Connection Settings
- HTTP Operations
- Provisioning
2. Select **Finish**.
> [!NOTE]
>
> Any settings or operations you skipped during the setup process appear empty or remain hidden.
After a successful configuration, the system creates your source and prompts you to run an aggregation.
- If you want to aggregate now, select **Aggregate**. The system aggregates the account and entitlements and returns you to the Sources page.
- Go to Source, and continue with additional configuration if required.
- To see the latest account aggregation history, go to **Source \> Account Management \> Account Aggregation**.
- To see the list of aggregated source accounts, go to **Source \> Account Management \> Accounts**.
- To see the latest entitlement aggregation history, go to **Source \> Entitlement Management \> Entitlements Aggregation**.
- To see the list of aggregated entitlements, go to **Source \> Account Management \> Entitlements**.
- If you want to aggregate later, select **Cancel**. This returns you to the Sources page. Your new source is listed, but contains no accounts or aggregation history yet.
# Customizers
You can customize the Web Services SaaS connector using cloud-based connector customizers. By using a customizer, you can change a connector's input before the connector ingests the data, or you can change the connector's output before the output is sent to SailPoint.
## Prerequisites
- To use the customizers, SailPoint CLI is required. To set it up, refer to [CLI]() in the SailPoint Developer Community.
- To build and upload the SaaS connector customizer, refer to [Building and Uploading to Identity Security Cloud]() in the SailPoint Developer Community.
- To find the commands available to implement in a SaaS connector customizer, refer to [Customizer Commands]() in the SailPoint Developer Community.
> [!NOTE]
>
> **Example 1**
>
> If you want to change the input attributes before account creation, you can use the `beforeStdAccountCreate` method. Consider a use case where an attribute that is not present in the schema (`userType`) needs to be added before the account creation to determine which account type you want to create. Refer to the following template:
>
> ```typescript
> // Get connector source config
> const config = await readConfig()
>
> return createConnectorCustomizer()
>
> .beforeStdAccountCreate(async (context: Context, input: StdAccountCreateInput) => {
> logger.info(`Running before account, for account ${input.identity}`)
> input.attributes.userType = 'member';
> return input
> })
> ```
> [!NOTE]
>
> **Example 2**
>
> If you want to change the output attributes after account read, you can use the `afterStdAccountRead` method. Let's consider a use case where an attribute that is not present in the schema (active), needs to be added after the account aggregation has been performed for determining whether the user is active or not. Refer to the following template:
>
> ```typescript
> // Get connector source config
> const config = await readConfig()
>
> return createConnectorCustomizer()
>
> .afterStdAccountRead(async (context: Context, output: StdAccountReadOutput) => {
> logger.info(`Running after account read for account ${output.identity}`)
> output.attributes.isActive = true;
> return output
> })
> ```
> [!NOTE]
>
> **Example 3**
>
> If you want to change the input attributes before account aggregation, you can use the `beforeStdAccountAggregation` method. Consider a use case where you want to determine the number of accounts that were aggregated the last time aggregation was performed. Refer to the following template:
>
> ```typescript
> // Get connector source config
> const config = await readConfig()
>
> return createConnectorCustomizer()
>
> .beforeStdAccountList(async (context: Context, input: StdAccountListInput) => {
> logger.info(`Running before account list for account. State: ${input.state.last_aggregation_count}`)
> return input
> })
> ```
> [!NOTE]
>
> **Example 4**
>
> If you want to make changes in one or more operations as mentioned in the above templates, you can club them together. Refer to the following template:
>
> ```typescript
> // Get connector source config
> const config = await readConfig()
>
> return createConnectorCustomizer()
>
> .beforeStdAccountList(async (context: Context, input: StdAccountListInput) => {
> logger.info(`Running before account list for account. State: ${input.state.last_aggregation_count}`)
> return input
> })
> .afterStdAccountRead(async (context: Context, output: StdAccountReadOutput) => {
> logger.info(`Running after account read for account ${output.identity}`)
> output.attributes.isActive = true;
> return output
> })
> .beforeStdAccountCreate(async (context: Context, input: StdAccountCreateInput) => {
> logger.info(`Running before account, for account ${input.identity}`)
> input.attributes.userType = 'member';
> return input
> })
> ```
## Endpoint Customization
You can customize endpoints used by the Web Services SaaS connector. The endpoint customizations can take place before or after HTTP operations that affect a given endpoint, such as Test Connection or Aggregation. Customizations that the connector can make to an endpoint include, but aren't limited to, changes to its physical address or its behavior.
- [Configure Endpoint Customization Before Operations](<#configure-endpoint-customization-before-operations>)
- [Configure Endpoint Customization After Operations](<#configure-endpoint-customization-after-operations>)
### Objects Used in Endpoint Customization
| Object Name | Object Reference |
| --- | --- |
| Request Body | `input._requestConfig.body` |
| Request URL | `input._requestConfig.url` |
| Request Headers | `input._requestConfig.headers` |
| Request method | `input._requestConfig.httpMethodType` |
| Page Offset | `input._pagingProcessor._pageInitialOffset` |
| Page Size | `input._pagingProcessor._pageSize` |
| Application Attributes | `input.applicationAttributes` |
| Response | `input.rawResponse.response` |
| Response Code | `input.rawResponse.status` |
### Configure Endpoint Customization Before Operations
Configure the connector to make a customization to an existing endpoint before operations. The connector looks for the `isBeforeCustomizer` parameter in the endpoint. The presence of this parameter in the endpoint signals to the connector that there is a customization process that needs to take place before the operation.
To add an endpoint customization before the operation, ensure that the following prerequisites have been completed prior to running the operation:
- Add a new parameter to the endpoint using the SailPoint REST API to indicate a customization requirement:
```text
"isBeforeCustomizer":true
```
> **Note**
>
> Refer to [Best Practices: REST API Authentication]() and [REST API - Update Source (Partial)]() in the SailPoint Developer Community for more information on SailPoint's REST APIs.
- Create a customizer project that actually executes the required endpoint customization. Refer to [Customizers - Get started]() in the SailPoint Developer documentation for more information about creating a customizer project. Add the `customizedOperation` method with two parameters:
- The `uniqueNameForEndPoint` followed by a `:before` suffix (for example, `Test Connection:before`) to execute the customizer project before the endpoint
- The handler to run
#### Objects Used in Before Operation Customizations
| Object | Description |
| --- | --- |
| `application` | The application whose data file is being processed. |
| `requestEndPoint` | Current request information. It contains the header, body, context URL, method type, response attribute map, and successful response code. |
#### Examples
The following are possible example configurations for before operation configurations.
> [!NOTE]
>
> **Before Operation Customization Example \#1**
>
> In the following example, SailPoint is executing an additional API to add an access token to the headers of the Test Connection endpoint.
>
> ```typescript
> export const connectorCustomizer = async () => {
> // Get connector source config
> const config = await readConfig()
> return createConnectorCustomizer()
> .customizedOperation('Test Connection:before', async (context: Context, input: any) => {
> // The private key is a sensitive credential. Store it securely, not in code.
> const privateKeyPem = `-----BEGIN RSA PRIVATE KEY-----
> [YOUR_ENCRYPTED_PRIVATE_KEY_CONTENT_HERE]
> -----END RSA PRIVATE KEY-----`
> const decryptPrivateKey = (encryptedPem: string, password: string): string => {
> const decryptPrivateKeyWithPassword = (encryptedPem: string, password: string): string => {
> // Remove header/footer and line breaks
> const pem = encryptedPem
> .replace('-----BEGIN RSA PRIVATE KEY-----', '')
> .replace('-----END RSA PRIVATE KEY-----', '')
> .replace(/\r?\n|\r/g, '')
> .trim()
> try {
> const decryptedKey = crypto.createPrivateKey({
> key: encryptedPem,
> format: 'pem',
> passphrase: password,
> })
> return decryptedKey.export({ format: 'pem', type: 'pkcs1' }).toString()
> } catch (err) {
> throw new Error('Failed to decrypt private key: ' + err)
> }
> }
> return decryptPrivateKeyWithPassword(encryptedPem, password)
> }
>
> const generateAssertion = (decryptedKey: string): string => {
> const now = Math.floor(Date.now() / 1000)
> // Payload values are specific to your application configuration in Okta.
> const payload = {
> aud: 'https://your-okta-domain.com/oauth2/v1/token',
> sub: 'your-client-id',
> iss: 'your-client-id',
> jti: Math.random().toString(36).substring(2),
> iat: now,
> exp: now + 600, // 10 minutes
> }
> return jwt.sign(payload, decryptedKey, {
> algorithm: 'RS256',
> header: {
> typ: 'JWT',
> alg: 'RS256',
> },
> })
> }
> // The passphrase for the private key is also a secret.
> const decryptedKey = decryptPrivateKey(privateKeyPem, 'your-private-key-passphrase')
> const assertion = generateAssertion(decryptedKey)
> const authenticate = async (jwtAssertion: string): Promise => {
> const url = 'https://your-okta-domain.com/oauth2/v1/token'
> const data = new URLSearchParams({
> grant_type: 'client_credentials',
> // Scopes define the permissions your application is requesting.
> scope: 'okta.users.read okta.groups.read okta.schemas.manage',
> client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
> client_assertion: jwtAssertion,
> })
> try {
> const response = await axios.post(url, data.toString(), {
> headers: {
> 'Content-Type': 'application/x-www-form-urlencoded',
> },
> })
> const accessToken = response.data.access_token
> return accessToken
> } catch (error: any) {
> console.error('Authentication failed:', error.message)
> return null
> }
> }
> const accessToken = await authenticate(assertion)
> const headers = {
> Authorization: `Bearer ${accessToken}`,
> }
> input._requestConfig.headers = headers
> return input
> })
> }
> ```
> [!NOTE]
>
> **Before Operation Customization Example \#2**
>
> In this example, SailPoint is iterating through the user role received from the input, and then assigning them to the request object based on their type, array, or string.
>
> ```typescript
> export const connectorCustomizer = async () => {
> // Get connector source config
> const config = await readConfig()
> return createConnectorCustomizer()
> .customizedOperation('Add Entitlement:before', async (context: Context, input: any) => {
> // Custom logic for the new operation
> logger.info('Update Account:before - running ' + JSON.stringify(input._requestConfig))
> const body: Map = input._requestConfig.body
> logger.info('bodyyyyy ' + JSON.stringify(input._requestConfig.body))
> const jsonBody: string = body.get('jsonBody') as string
> logger.info('JSON body received ' + JSON.stringify(jsonBody))
> try {
> let jsonMap: any = null
> try {
> jsonMap = JSON.parse(jsonBody)
> logger.info('Parsed jsonBody successfully ' + JSON.stringify(jsonMap))
> } catch (e) {
> logger.error('Failed to parse jsonBody:', e)
> jsonMap = {}
> }
> if (jsonMap !== null) {
> let roleEntry: any = jsonMap['USER_ROLE']
> let role: string = ''
> if (roleEntry !== null && Array.isArray(roleEntry)) {
> const rolesArray: Array = roleEntry
> if (rolesArray.length > 0) {
> role = rolesArray[0] as string
> }
> } else if (roleEntry !== null) {
> role = roleEntry as string
> }
> jsonMap['USER_ROLE'] = role
> const finalBody: string = JSON.stringify(jsonMap)
> input._requestConfig.body = finalBody
> logger.info('input body ' + JSON.stringify(input._requestConfig))
> }
> } catch (ex) {
> console.error('Rule - MULE Modify Body: ' + ex)
> }
> return input
> })
> }
> ```
### Configure Endpoint Customization After Operations
Configure the connector to make a customization to an existing endpoint after operations. The connector looks for the `isAfterCustomizer` parameter in the endpoint. The presence of this parameter in the endpoint signals to the connector that there is a customization process that needs to take place after the operation is completed.
To add an endpoint customization after operation completion, ensure that the following prerequisites have been completed prior to running the operation:
- Add the `isAfterCustomizer` parameter to the endpoint via the SailPoint REST API to indicate that there is a customization requirement.
> **Note**
>
> Refer to [Best Practices: REST API Authentication]() and [REST API - Update Source (Partial)]() in the SailPoint Developer Community for more information on SailPoint's REST APIs.
- Create a customizer project that actually executes the required endpoint customization. Refer to [Customizers - Get started]() in the SailPoint Developer documentation for more information about creating a customizer project. Add the `customizedOperation` method with two parameters:
- An endpoint identifier followed by an `:after` suffix to execute the customizer project before the endpoint
- The handler to run
#### Objects Used in After Operation Customizations
| Object | Description |
| --- | --- |
| `application` | The application whose data file is being processed. |
| `requestEndPoint` | Current request information. It contains the header, body, context URL, method type, response attribute map, and successful response code. |
| `processedResponseObject` | This object is a list of map objects for accounts and groups. The map objects contain keys as identity attributes for the application schema, and the associated values are all the account and group attributes passed by the connector after parsing the respective API response. |
| `rawResponseObject` | The raw response string returned from the target system. This can be in JSON or XML format. |
#### Example
The following is a possible example for an after operation configuration.
> [!NOTE]
>
> **After Operation Customization Example**
>
> In this example, SailPoint is converting the XML object received as a raw response from the API to JSON, and then mapping the attributes to the schema.
>
> ```typescript
> export const connectorCustomizer = async () => {
> // Get connector source config
> const config = await readConfig()
>
> return createConnectorCustomizer()
> .customizedOperation('Account Aggregation:after', async (context: Context, input: any) => {
> const xml2js = require('xml2js') // Require inside an async function
> const parseStringPromise = xml2js.parseStringPromise
>
> let jsonPrettyPrintString
> let xmlJSONObj = await parseStringPromise(input.rawResponse.response, {
> explicitArray: false, // Avoid unnecessary arrays
> trim: true, // Remove whitespace
> })
> logger.info(`JSON parsed string ` + JSON.stringify(xmlJSONObj))
> jsonPrettyPrintString = JSON.stringify(xmlJSONObj)
> let response = JSON.parse(jsonPrettyPrintString)
> logger.info('Response obj : ' + JSON.stringify(response))
> let userListOutput = response.USER_LIST_OUTPUT || {}
> if (!userListOutput.USER_LIST) throw new Error('USER_LIST_OUTPUT is undefined')
> let userList = userListOutput.USER_LIST || {}
>
> if (!userList?.USER) throw new Error('USER_LIST is undefined')
>
> let finalList: {}[] = []
> if (userList.USER) {
> userList.USER.forEach(
> (user: {
> CONTACT_INFO: any
> USER_STATUS: string
> BUSINESS_UNIT: string
> USER_ROLE: string
> USER_LOGIN: string
> USER_ID: string
> }) => {
> let newmap = new Map()
> let contactInfo = user.CONTACT_INFO
> newmap.set('FIRSTNAME', contactInfo?.FIRSTNAME || 'Unknown')
> newmap.set('LASTNAME', contactInfo?.LASTNAME || 'Unknown')
> newmap.set('EMAIL', contactInfo?.EMAIL || 'Unknown')
> newmap.set('USER_STATUS', user.USER_STATUS || 'Unknown')
> newmap.set('BUSINESS_UNIT', user.BUSINESS_UNIT || 'Unknown')
> newmap.set('USER_ROLE', user.USER_ROLE || 'Unknown')
> newmap.set('USER_LOGIN', user.USER_LOGIN || 'Unknown')
> newmap.set('USER_ID', user.USER_ID || 'Unknown')
> finalList.push(newmap)
> }
> )
> }
> logger.info('final list: ' + JSON.stringify(finalList))
> const returnData = { data: finalList }
> return returnData
> })
> }
> ```
# Dataset Management
Dataset Management lets you review the object types a source collects and control how the source aggregates those objects into SailPoint. Use Dataset Management to view and manage resource attributes, datasets and their resources, enable dataset aggregation schedules, perform manual aggregation, and view aggregation history.
> [!NOTE]
>
> Datasets are also available in SailPoint Agentic Fabric. Contact your Customer Success team and refer to [SailPoint Agentic Fabric]() for more information.
For more information, refer to [Managing Datasets and Resources]() for datasets, resources, owner correlation, and aggregation.
## Datasets
A *dataset* is a named group of one or more related resources that the source aggregates together.
When aggregation runs for a dataset, the source collects all resources in that dataset from the managed system in one aggregation job. Activate or deactivate aggregation at the dataset level, not for individual resources.
> [!NOTE]
>
> Each resource belongs to exactly one dataset for that source. The source defines which resources belong to each dataset. You can enable aggregation and review associated resources, but you cannot create or delete datasets or move resources between them.
### Dataset Aggregation
Configure aggregation on the **Dataset Aggregations** tab for each dataset. Configure each dataset separately. During aggregation, your owner correlation rules are automatically applied to link machine identities to their human owners. For more information, refer to [Configuring Dataset Aggregations]().
## Resources
A resource defines an object type from the managed system. It specifies the kind of object, the attributes the source collects, and how the source identifies and displays each object. Resources form the building blocks of the data model.
In the UI, each resource appears under **Dataset Management** \> **Resources** with its schema. A resource does not run aggregation by itself. The dataset that owns the resource collects it during aggregation.
For more information, refer to [Managing Resources]().
### Owner Correlation
Configure owner correlation on each resource to link aggregated objects to human owners. If you do not configure owner correlation, or if the mapping produces no match, an owner is not assigned. For more information, refer to [Configuring Owner Correlation]().
## Web Services Datasets
A dataset is a named group of one or more related resources that SailPoint aggregates together.
> [!NOTE]
>
> Web Services is a generic source, so you create your own datasets and resources on the source. Refer to [Creating Datasets]() for more information.
Configure aggregation for each dataset separately. Refer to [Configuring Dataset Aggregations]() for more information.
## Web Services Resources
A resource represents a type of object the connector collects from Web Services, such as agents, applications, or credentials. Each resource defines the attributes collected for that object type and how each object appears in SailPoint.
Refer to [Creating Resources]() for more information on creating resources and [Configuring Owner Correlation]() for more information on linking aggregated objects to their owners.
When you create a resource, select one of the following resource types:
- Agent (`std:agent`)
- Application (`std:application`)
- Capability (`std:capability`)
- Credential (`std:credential`)
- Device (`std:device`)
- Account (`std:account`)
After you create the resource, configure the Resource Aggregation under [HTTP Operations](), then run aggregation.
# Configuring Web Services SaaS Entitlements
## Multiple Group Objects
The Web Services source supports multiple group objects. Add a new endpoint for newly introduced groups or entitlements, such as:
- Group Aggregation - ``
- Get Object - ``
- Add Entitlement - ``
- Remove Entitlement - ``
Refer to the [listSchema]() API and [createSchema]() API for more information.
> [!NOTE]
>
> **Adding a New Group Schema**
>
> To support multi groups, add the following API to add a new schema:
>
> - **Method** - `POST`
> - **URI** - `/sources//schemas`
> - **JSON Payload**:
>
> The following JSON example adds the schema for the Role that follows:
>
> ```json
> {
> "name": "Role",
> "nativeObjectType": "Role",
> "identityAttribute": "Id",
> "displayAttribute": "Name",
> "hierarchyAttribute": null,
> "includePermissions": false,
> "features": [],
> "configuration": {},
> "attributes": [
> {
> "name": "Id",
> "type": "STRING",
> "schema": null,
> "description": "Role Id.",
> "isMulti": false,
> "isEntitlement": false,
> "isGroup": false
> },
> {
> "name": "Name",
> "type": "STRING",
> "schema": null,
> "description": "Role name.",
> "isMulti": false,
> "isEntitlement": false,
> "isGroup": false
> }
> ]
> }
> ```
>
> The resulting Role:
>
> ```xml
>
>
> Role Id.
>
>
> Role name.
>
>
> ```
> [!NOTE]
>
> **Updating the Existing Account Schema**
>
> As the new group schema (for role object type) has been created, update the relevant account schema attributes to point to the new group schema by making changes in the account schema through the UI, as SailPoint allows you to add the new entitlement in the account schema.
> [!NOTE]
>
> **Add New Endpoint**
>
> Add a new endpoint for Group Aggregation, Get Object, and Add/Remove Entitlement operations. Update the `connectionParameters` attribute using the PATCH method as follows:
>
> 1. Add a new dummy endpoint such as Test Connection, Account Aggregation from the SailPoint UI and save it.
> 2. With the PATCH API, replace the required operation type with the respective operation type, such as:
>
> 1. Group Aggregation ``
> 2. Get Object ``
> 3. Add Entitlement ``
> 4. Remove Entitlement ``
>
> Method - `POST`
>
> URI - `beta/sources//schemas`
>
> JSON Payload:
>
> ```json
> [
> {"op":"add","path":"/connectorAttributes/connectionParameters/0/operationType","value":"Group Aggregation-Role"},
> {"op":"add","path":"/connectorAttributes/connectionParameters/1/operationType","value":"Get Object - Role"},
> {"op":"add","path":"/connectorAttributes/connectionParameters/2/operationType","value":"Add Entitlement-Role"},
> {"op":"add","path":"/connectorAttributes/connectionParameters/3/beforeRule","value":"Remove Entitlement-Role"}
> ]
> ```
> [!IMPORTANT]
>
> Localization is not applicable for the value of the `OperationType` attribute added from the API. If you provide the operation type in a language other than English, the Web Services source does not configure the group aggregation type (for example, Groepsaggregatie - Rol).
## Configuring Multiple Entitlement Requests
To enable the connector to send multiple entitlement requests of different enlistment types in a single request to the managed system, set the `addRemoveEntInSingleReq` parameter to `true` as follows:
```xml
true
```
You can configure the value of this attribute using the SailPoint REST API. Refer to [SailPoint REST API - Update Source (Partial)]() for more information.
The following is an example of the payload:
```json
{
"addRoleIds": $plan.addRoleIds$
}
```
- If `addRemoveEntInSingleReq` is set to `false`, then the placeholder value for the attribute marked as an entitlement is passed in separate API requests:
First request payload:
```text
jsonBody={ "addRoleIds": "9dd23398-b905-4878-b7ad-bc02d22171d9" }
```
Second request payload:
```text
jsonBody={ "addRoleIds": "8defe39c0-54f6-47b4-8a15-fcc2622923sk" }
```
- If `addRemoveEntInSingleReq` is set to `true`, then the placeholder value for the attribute marked as an entitlement is passed as an array and is executed in a single request:
Single request payload:
```text
jsonBody={ "addRoleIds": ["97ee39c0-54f6-47b4-8a15-fcc262292386","8defe39c0-54f6-47b4-8a15-fcc2622923sk"] }
```
## Child Hierarchy
The Web Services SaaS connector supports child hierarchy for entitlements. To achieve this, perform the following:
1. Add the `hierarchyAttribute` property to the entitlementSchemas.
2. Add the `childHierarchy: true` property to the child entitlement.
Refer to the API [Uploads source entitlements schema]() and [Update Source Schema (Partial)]() in the SailPoint Developer Community for more information.
> [!NOTE]
>
> **Sample Schema**
>
> The following example marks the `roles` attribute on a Role entitlement schema as supporting a child hierarchy:
>
> ```xml
>
>
> List of roles contained within the role
>
>
>
>
>
> ```
## Direct Permissions
The Web Services SaaS connector can read direct permissions for accounts. Configure direct permissions using after list account operations in customizers. Refer to [Customizers]() for more information.
To add direct permissions for accounts, add the desired object to the `permissions` attribute under `StdAccountListOutput` as follows:
```typescript
.afterStdAccountList(async (context: Context, output: StdAccountListOutput) => {
const permissions = [] as unknown as Permission[];
const permission = {} as Permission;
permission.annotation = 'annotationValue';
permission.rights = 'rightsValue';
permission.target = 'targetValue';
output.permissions = permissions;
return output
})
```
> [!NOTE]
>
> Configuring direct permissions requires additional processing, which may result in an increased duration of time to complete aggregation processes.
# HTTP Operations
In **HTTP Operations**, you can add, edit, delete, and reorder HTTP operations.
The connector supports the following operations:
- Test Connection
- Account Aggregation
- Account Delta Aggregation
- Group Aggregation
- Resource Aggregation - {resourceName}
- Get Object
- Get Object-Group
- Create Account
- Update Account
- Delete Account
- Enable Account
- Disable Account
- Unlock Account
- Change Password
- Add Entitlement
- Remove Entitlement
- Custom Authentication
- Pass-Through Authentication
> [!NOTE]
>
> **Notes**
>
> - For Entitlement Aggregation, you need to configure the schema manually using the REST APIs. Contact SailPoint Support for assistance.
> - For the Web Services source, you can configure the native identity in the provisioning plan using a placeholder such as `$plan.planNativeIdentity$`.
> - Access to ExternalDTD is disabled during XML parsing.
## Support for Cookies
The Web Services source supports cookies for HTTP requests.
The Web Services source supports cookies for multiple endpoints configuration. The source manages the cookies internally for the endpoints configured for the same operation. Cookies from the previous endpoints can be used in all the subsequent endpoints of the same operation type.
The Web Services source supports the JSON array as a top element in the HTTP requests.
By default, the Web Services source supports cookies. Cookies can be disabled by adding the `disableCookies` attribute key with `true` as a value. This is not applicable for the authentication API call operation.
## Add Operations
Configure one or more HTTP operations to manage your source data. The options available to configure the operation vary, depending on your selected **Operation Type**. To add a new HTTP operation, select **Add Operation**.
> [!NOTE]
>
> **Screenshot**
>
> [![Add Operations]()]()
The following topics describe the different configuration tabs that may appear when configuring an operation.
### General Information
Enter basic configuration information for the HTTP operation.
> [!NOTE]
>
> **Screenshot**
>
> [![General Information]()]()
1. In the **Operation Name** field, enter a unique name for the operation that you want to execute. You can change the name of an operation later if needed.
> **Note**
>
> SailPoint recommends that you create a unique name for the operation to help you distinguish it from other operations. For example, if you have two account aggregation endpoints for your source, you can name them "Account Aggregation-1" and "Account Aggregation-2".
2. In the **Operation Type** dropdown list, select the name of the operation that you want to execute.
> **Note**
>
> You must configure a Partitioned Account Aggregation operation to support partitioning for static and dynamic. Additionally, to support dynamic partitioning you must also configure a Get Partition operation.
3. Select the **Request Type** from the dropdown.
If your configuration requires cURL, refer to [Add an Operation with cURL](<#add-an-operation-with-curl>).
If your configuration requires GraphQL, refer to [Add an Operation with GraphQL](<#add-an-operation-with-graphql>).
4. In the **Context URL** field, enter the authentication (Context) URL specific to your operation. The connector appends the context URL to the source's Base URL. This can be empty depending on the endpoint of the managed system. For example:
`/2/team/members/list`
The following are a few keywords that are used in the Context URL along with the placeholder `$`:
- `plan`
- `response`
- `application`
- `getobject`
- `authenticate`
5. In the **HTTP Method** field, select the appropriate method from the dropdown list. HTTP method is supported by the respective operation. For example, you can select **GET**, **PUT**, **POST**, **DELETE**, or **PATCH**.
6. Select **Save**.
#### Add an Operation with cURL
The endpoint cURL command for an operation which contains the complete request URL, HTTP Method, Header, and Body is provided in the following example:
```text
curl --location --request POST 'https://api.dropbox.com/2/team/members/list' \
--header 'Authorization: $application.accesstoken$' \
--header 'Content-Type: application/json' \
--data-raw '{"limit":1}'
```
In this example, consider the following:
- Complete request URL: `https://api.dropbox.com/2/team/members/list`
> **Note**
>
> The URL must be in `http://` or `https://` format. You can add a placeholder URL, but it must have `http://` or `https://` at the beginning of the URL string. You can't use a placeholder URL on its own.
- HTTP Method:
```text
POST
--header 'Authorization: $application.accesstoken$' \
--header 'Content-Type: application/json' \
```
- Header
- Body:
```text
--data-raw '{"limit":1}'
```
#### Add an Operation with GraphQL
If you select `GraphQL` as the **Request Type**, the options for **Context URL** and **HTTP Method** are removed, and you only need to provide the **Query** and **GraphQL Variables**.
> [!NOTE]
>
> The connector only supports velocity and placeholder expressions for GraphQL variables.
> [!NOTE]
>
> **Screenshot**
>
> [![Add an Operation with GraphQL]()]()
The GraphQL for an operation which contains a query and variables is provided in the following example.
##### Query
```text
query ListOrganizationMembers($org: String!, $cursor: String, $first: Int = 100) {
viewer {
organization(login: $org) {
viewerIsAMember
viewerCanCreateTeams
membersWithRole(after: $cursor, first: $first) {
totalCount
edges {
node {
login
name
id
email
databaseId
}
}
}
}
}
}
```
##### Variables
```json
{
"org": "sailpoint-sandbox"
}
```
In this example, consider the following:
- The URL is constant throughout the system.
- The HTTP Method is always POST.
- GraphQL supports cursor-based pagination.
### Header
The header holds the key and value for a given HTTP operation that you want to execute. The connector sends these key-value pairs as part of the header in HTTP requests.
> [!NOTE]
>
> **Screenshot**
>
> [![Header]()]()
The following example displays a sample key-value pair, where `Authorization` is the header **Key** and `$application.accesstoken$` is the **Value**.
```text
Authorization - $application.accesstoken$
Content-Type - application/json
```
> [!NOTE]
>
> **Notes**
>
> - If you don't provide the content type in the Header, the source sets Content-Type as `application/json`.
> - If you wish to exclude the default Content-Type header from the requests, add `removeDefaultHeaderFromRequest:true` in the connectionParameter object of those requests using the [put-source]() SailPoint Developer Community API.
1. Enter the header **Key** and **Value** used for the operation.
2. Select **Save**.
#### Content Types
- JSON request, JSON response: `Content-Type= application/json (optional), Accept (optional)`
### Body
This is the standard HTTP body used for posting the data with a request. The Body can be configured as one of two types, **Form Data** or **Raw**. Either of these is used for a specific operation.
> [!NOTE]
>
> **Screenshot**
>
> [![Body]()]()
#### Form Data
1. Select **Form Data**.
2. Add the respective data **Key** and **Value**. The Web Services source will not display an error when an endpoint's body type is selected as **Form Data** and the form entries are empty. The key-value pairs are sent as part of the Body in JSON format. XML does not support form data.
#### Raw
1. Select **Raw**.
2. Enter the data in the **Body** field. Select **Save**.
> **JSON Example**
>
> You can use this entry without a placeholder:
>
> ```json
> {
> "limit": 10,
> "cursor": "abcd1234"
> }
> ```
>
> You can use this entry with a placeholder:
>
> ```json
> {
> "group_id" : "$plan.groups$",
> "permission":"$plan.permission$",
> "roles": "$plan.roles$"
> }
> ```
#### Additional Information for Body
The following keywords are used in the Body along with the placeholder `$`:
- `plan`
- `response`
- `application`
- `getobject`
- `authenticate`
#### Handling the "$" Character in the URL and Body
The Web Services source correctly extracts and handles the `$` character in the URL and Body, along with the placeholders.
#### Placeholder Details
##### The JSON Request with the Placeholder in the Body/Payload
If the body contains a placeholder that is not present in the provisioning plan, response, or source, the source removes the key value from the JSON payload. For example:
```json
{
"type": "$plan.type$",
"id": "$plan.nativeIdentity$",
"title": "$plan.title$",
"externalid": "12345"
}
```
If the plan does not contain the title attribute request, the source removes the title key and value. For example:
```json
{
"type": "student",
"id": "STUD121",
"externalid": "12345"
}
```
##### URL
If the URL contains a placeholder that is not present in the provisioning plan, response, or source, the source removes the value from the Request URL.
##### Header
If the header contains a value that is not present in the provisioning plan, response, or source, the source removes the key value from the Request Header.
#### Handling the "$$" Character in the URL and Body
The Web Services connector correctly extracts and handles `$$` as a singular velocity operations character in the URL, Body, and Pagination operations.
#### Velocity Details
##### The JSON Request with the Velocity Operations in the Body/Payload
```json
{
"type": "$$plan.type$$",
"id": "$$plan.nativeIdentity$$",
"title": "$$plan.title$$",
"externalid": "12345"
}
```
> [!NOTE]
>
> Velocity operations can't be configured in XML format.
### Response Information
Response Information has a **Root Path** and a **Success Code**.
> [!NOTE]
>
> **Screenshot**
>
> [![Response Information]()]()
The Root Path must be common for all the attributes mentioned in the Response Attribute Mapping for a particular operation.
The Success Code is the successful HTTP response code expected by respective Web Service operations. The Success Code field accepts HTTP status codes in CSV format.
For example, consider the HTTP response code `200, 201, 203`. If the list does not contain any value, the status codes from `200` to `299` are checked. Successful status codes start with `2`.
You can provide `2**` as a Success Code. The Web Services source supports a `null` HTTP response body with custom error messages. For Web Services SaaS, the pagination with a `null` Root Path in Response Mapping works correctly. The default value for root path is `$`.
1. Enter the **Root Path**. This is the common path present in the JSON response. For example:
- **JSON** - `$.members.profile`
2. Enter the **Success Code**. This is the HTTP success code that serves as a response to the request.
3. Select **Save**.
### Response Mapping
Response Mapping is a response attribute returned in JSON/XML format from the managed system for specific operations like create user, update user, or account aggregation.
> [!NOTE]
>
> **Screenshot**
>
> [![Response Mapping]()]()
1. Enter the **Schema Attribute** expected in the JSON response from the URL as a part of the schema.
2. Enter the JSON **Attribute Path** of the particular attribute in the returned response. The Root Path is prefixed with this path. For example:
- **JSON** - `members[*].profile.member_id`
3. Select **Save**.
In the Web Services source, you have to add the schema attributes manually for the respective Web Services-based target system. The source accurately handles any incorrect JSON attribute paths in the endpoint's response mapping configuration.
### XPath Namespace Mapping
Configure the XML **Namespace Prefix** and its corresponding **Namespace URL**, which identify uniquely named elements and attributes in XML requests and responses.
> [!NOTE]
>
> **Screenshot**
>
> [![XPath Namespace Mapping]()]()
> [!NOTE]
>
> **Notes**
>
> - Absence of non-standard XML Namespaces results in errors while response parsing.
> - If any non-standard XML Namespace exists in the response, configure the same in the XML Namespace mapping where the **Key** is the Namespace Prefix and the **Value** is the Namespace URL.
> - If a default Namespace is present, add a temporary Namespace Prefix with the default Namespace URL in the XML Namespace mappings. Use this temporary prefix in the XPath elements within the scope of the default Namespace.
1. Add the **Namespace Prefix** and **Namespace URL** pair to be used in the XML operation. Use the **Add Another** and **Recycle Bin** options, as needed.
2. Select **Save**.
### Update Considerations
For existing sources, go to the **General Information** tab, select `cURL` from the **Request Type** dropdown if you have configured the cURL Command, otherwise select **API** and then **Save**.
# Integrating SailPoint with Web Services SaaS
The Web Services SaaS connector allows you to configure any Web Services supported managed system that can read and write on the managed system. Web Services SaaS supports REST, SOAP, and GraphQL for read and write.
This document is designed to give specific information about the requirements and fields needed to successfully configure an instance of the Web Services SaaS source.
> [!NOTE]
>
> To view the latest features, enhancements, and fixes for all SaaS connectors, refer to the [SaaS Release Notes]() page.
## Supported Managed Systems
The SailPoint Web Services SaaS connector supports SOAP, REST, and GraphQL web services with XML and JSON response format.
## Prerequisites
- Web Services must be accessible.
## Required Permissions
The user/administrator must have the required permissions to call the Web Services API of the managed system.
## Supported Features
The Web Services SaaS connector supports the following features:
- Account Aggregation
- Account Delta Aggregation
- Partitioning Account Aggregation
- [Child Hierarchy]()
- [Customizers]()
- Entitlement Aggregation
- Resource Aggregation - {resourceName}
- Get Object
- Multiple Group Objects
- Provisioning
- Create Account
- Add/Remove Entitlement
- Update Account
- Enable Account
- Disable Account
- Delete Account
- Unlock Account
- Change Password
### Authentication
For the Web Services SaaS source, credentials are required to connect to the managed system. The following authentication methods are supported:
- Basic Authentication
- OAuth 2.0 Authentication
- API Token
> **Note**
>
> This source does not generate OAuth tokens based on a Client ID and Client Secret Key. You must provide the API token as an access token.
- No/Custom Authentication
- Pass-through authentication
### Multiple Group Objects
The Web Services SaaS source supports multiple group objects. Refer to [Multiple Group Objects]() for more information.
# Keywords
The Web Service source supports the following keywords for various configuration attributes such as Authentication URL, Headers, Body (JSON and Form-data) for a single or multiple endpoints.
## plan
Used for configuring the provisioning operations such as create account and update account. For example:
Authentication URL - `/api/core/v3/people/$plan.nativeIdentity$`
**JSON Body example for plan**:
```json
{"new_members": [
{
"email": "$plan.email$",
"first_name": "$plan.first_name$",
"surname": "$plan.surname$",
"send_welcome_email": $plan.send_welcome_email$,
"role": {
".tag": "member_only"
}
}
]
}
```
## response
Used for multiple endpoints, where the response from the first endpoint is provided as an input for the second endpoint. For example, there are two endpoints for account aggregation:
- The first endpoint returns a response as a list of `member_ids` that is an input for the second endpoint.
- The second endpoint's JSON body is: `{"members_info":[{"member_id":"$response.member_id$"}]}`
## application
Used to get other configuration attributes from the current source. For example:
```text
"$application.$",
```
Where `` is a source configuration attribute.
## getobject
Used while performing the `Aggregate Account` operation (get a single account details). The `$getobject` allows you to use any attribute of the account. For example, `$getObject.lastLoginDate$`.
- JSON body:
```json
{"members": [
{
".tag": "member_id",
"member_id": "$getobject.nativeIdentity$"
}
]
}
```
- Authentication URL for get object:
```text
/api/v4/admin/$getobject.nativeIdentity$
```
## nativeIdentity
Indicates the `AccountID` identity attribute in the plan or during the `getobject` operation. For example, `nativeIdentity` is used along with the keyword as follows:
- **getobject** - `$getobject.nativeIdentity$`
- **plan** - `$plan.nativeIdentity$`
> [!NOTE]
>
> There may be instances where `nativeIdentity` is present in the account request for account creation. In such cases, `nativeIdentity` may occasionally reflect different values.
## planNativeIdentity
Represents the Plan's `nativeIdentity` in the Provisioning plan. For example, `planNativeIdentity` is used along with the keyword as follows:
- **plan** - `$plan.planNativeIdentity$`
Web Services can be configured with the native identity from the provisioning plan using the placeholder `$plan.planNativeIdentity$`.
> [!NOTE]
>
> There is a possibility that `nativeIdentity` may be present in the account creation request. It may sometimes correspond to different values.
## authenticate
To provide the username and password in the endpoint configuration, use the following placeholders:
```text
$authenticate.username$
$authenticate.password$
```
Refer to [Pass-Through Authentication]() for more information on configuration.
> [!NOTE]
>
> SailPoint recommends using a placeholder in the body and URL rather than adding sensitive information directly. For example:
>
> ```text
> https://TESTMACHINE:9096/users/user/$application.accesstoken$
> ```
>
> Attributes mapped to a raw JSON response may contain formatted values similar to `".tag": "member_id"`, such as:
>
> ```text
> ['.tag']
> ['@etag']
> ['@@test']
> ['complex.name']
> ['role name']
> ['role_name']
> ```
# JSON and XML Response Examples
This section provides specific examples of the following format responses or inputs for the supported fields or the operations on the Web Services source:
- [JSON Response Examples](<#json-operations>)
- [XML Response Examples](<#xml-operations>)
## JSON Operations
This section provides examples of JSON responses for the supported operations.
### Test Connection
> [!NOTE]
>
> SailPoint recommends that you have a single endpoint set up for test connections because there may be timeout issues for multiple endpoints in test connections.
This topic provides an example of a JSON response for a test connection operation.
> [!NOTE]
>
> **Test Connection Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Test Connection (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Test Connection**.
> 3. In the **Context URL** field, enter the URL specific to the test connection.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Test Connection General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs are sent as part of the header in the HTTP request.
>
> [![Test Connection Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for a test connection.
>
> In the **Raw** field, enter the JSON payload for the test connection.
>
> [![Test Connection Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Test Connection Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Below is an example of a schema that is mapped to JSON response. Refer to [Configuration for Response]() for more information.
>
> [![Test Connection Response Mapping]()]()
### Aggregation
This topic provides an example of a JSON response for an account aggregation operation.
#### Account Aggregation - 1
Using the Web Services SaaS source, you can have multiple account aggregation operations.
For example: Aggregation - 1 and Aggregation - 2.
You can aggregate two attributes from EndPoint1 and three more attributes from EndPoint2.
When you configure multiple operations, the response of first operation can be used as an input in the second operation.
> [!NOTE]
>
> **Account Aggregation - 1 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Account Aggregation - 1 (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Account Aggregation**.
> 3. In the **Context URL** field, enter the URL specific to the account aggregation.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Account Aggregation - 1 General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Account Aggregation - 1 Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for an account aggregation.
>
> In the **Raw** field, enter the JSON payload for the account aggregation.
>
> [![Account Aggregation - 1 Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Account Aggregation - 1 Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Refer to [Configuration for Response]() for more information about the raw JSON response on which the **Response Information** schema is mapped.
>
> [![Account Aggregation - 1 Response Mapping]()]()
#### Account Aggregation - 2
For example, during aggregation of Dropbox, the response of the first endpoint will return the `id`, `Username`, `firstName`, among others.
This response must be provided as an input to the second endpoint. This can be provided with the help of a keyword "response" (`$response.team_member_id$`), where `team_member_id` is the value fetched from Account Aggregation -1 and it is an identity attribute in the source schema.
> [!NOTE]
>
> **Account Aggregation - 2 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Account Aggregation - 2 (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Account Aggregation**.
> 3. In the **Context URL** field, enter the URL specific to the account aggregation.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Account Aggregation - 2 General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Account Aggregation - 2 Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for an account aggregation.
>
> In the **Raw** field, enter the JSON payload for the account aggregation.
>
> To fetch additional attributes from another endpoint, use the id (identity attribute) from the previous response. Add these attributes in **Schema Attribute** section of **Response Mapping** of the first end point (Account Aggregation - 1).
>
> In the following screenshot, `$response.team_member_id$` represents the identity that was aggregated in the Account Aggregation-1 and is mentioned previously in the schema mapping section of Account Aggregation -1.
>
> [![Account Aggregation - 2 Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Account Aggregation - 2 Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Below is an example of a schema that is mapped to XML response. Refer to [Configuration for Response]() for more information.
>
> [![Account Aggregation - 2 Response Mapping]()]()
>
> On the **Parent Endpoint** tab:
>
> In the following example, Account Aggregation -1 (JSON) is the parent endpoint and Account Aggregation - 2(JSON) is its child endpoint.
>
> From the **Parent Endpoint Name** dropdown list, select **Account Aggregation - 1 (JSON)**, as shown below.
>
> [![Account Aggregation - 2 Parent Endpoint]()]()
#### Account Aggregation - 3
For example, to aggregate users using GraphQL:
> [!NOTE]
>
> **Account Aggregation - 3 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Account Aggregation (GraphQL)`.
> 2. From the **Operation Type** dropdown list, select **Account Aggregation**.
> 3. In the **Request Type** field, select **GraphQL**.
> 4. In the **Query** and **GraphQL Variables** sections, enter the query and variables specific to the account aggregation.
>
> [![Account Aggregation - 3 General Information]()]()
>
> On the **Header** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Account Aggregation - 3 Header]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** are the successful HTTP response codes expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Account Aggregation - 3 Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Enter the **Schema Attribute** and **Attribute Path** for JSON response. Refer to [Configuration for Response]() for more information.
>
> [![Account Aggregation - 3 Response Mapping]()]()
>
> On the **XPath Namespace Mapping** tab:
>
> Enter the **Namespace Prefix** and **Namespace URL** for JSON response.
>
> [![Account Aggregation - 3 XPath Namespace Mapping]()]()
>
> On the **Parent Endpoint** tab:
>
> From the **Parent Endpoint** dropdown list, select **Account Aggregation(GraphQL)**.
>
> [![Account Aggregation - 3 Parent Endpoint]()]()
>
> On the **Paging** tab:
>
> Enter the cursor-based pagination values.
>
> [![Account Aggregation - 3 Paging]()]()
### Create Account
This topic provides examples of a JSON response for the create account operation.
#### Create Account - 1
> [!NOTE]
>
> **Create Account - 1 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Create Account (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Create Account**.
> 3. In the **Context URL** field, enter the URL specific to the create account operation.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Create Account - 1 General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Create Account - 1 Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for account creation.
>
> In the **Raw** field, enter the JSON payload for the account creation.
>
> In the following screenshot, the `$plan` keyword represents the provisioning plan that is passed to the provision method. For example, `$plan.member_email$` checks for the email in the attribute request and updates in the body after it is found.
>
> [![Create Account - 1 Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Create Account - 1 Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Refer to [Configuration for Response]() for more information about the raw JSON response on which the **Response Information** schema is mapped.
>
> [![Create Account - 1 Response Mapping]()]()
#### Create Account - 2
For example, to aggregate users using GraphQL:
> [!NOTE]
>
> **Create Account - 2 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Create Account(GraphQL)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Create Account**.
> 3. In the **Request Type** field, select **GraphQL**.
> 4. Enter the **Query** and **GraphQL Variables** specific to the account aggregation.
>
> [![Create Account - 2 General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Create Account - 2 Header and Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Create Account - 2 Response Information]()]()
>
> On the **Response Mapping** tab:
>
> The following is an example of a schema that is mapped to the JSON response. For more information, refer to to [Configuration for Response]().
>
> [![Create Account - 2 Response Mapping]()]()
>
> On the **XPath Namespace Mapping** tab:
>
> Enter the **Namespace Prefix** and **Namespace URL** for JSON response.
>
> [![Create Account - 2 XPath Namespace Mapping]()]()
### Add Entitlement
This topic provides an example of a JSON response for an add entitlement operation.
> [!NOTE]
>
> **Add Entitlement Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Add Entitlement (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Add Entitlement**.
> 3. In the **Context URL** field, enter the URL specific to the entitlement.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Add Entitlement General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Add Entitlement Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for adding entitlements.
>
> In the **Raw** field, enter the JSON payload for the entitlement.
>
> In the following screenshot, the `plan.nativeIdentity` keyword signifies the AccountID (identity attribute) in the account request of the plan. If the plan contains the identity attribute of an account, it can be updated in the payload with `$plan.nativeIdentity$`.
>
> [![Add Entitlement Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Add Entitlement Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Refer to [Configuration for Response]() for more information about the raw JSON response on which the **Response Information** schema is mapped.
>
> [![Add Entitlement Response Mapping]()]()
### Remove Entitlement
This topic provides an example of a JSON response for a remove entitlement operation.
> [!NOTE]
>
> **Remove Entitlement Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Remove Entitlement (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Remove Entitlement**.
> 3. In the **Context URL** field, enter the URL specific to the entitlement.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Remove Entitlement General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Remove Entitlement Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for removing entitlements.
>
> In the **Raw** field, enter the JSON payload for the entitlement.
>
> In the following screenshot, the `plan.nativeIdentity` keyword signifies the AccountID (identity attribute) in the account request of the plan. If the plan contains the identity attribute of an account, it can be updated in the payload with `$plan.nativeIdentity$`.
>
> [![Remove Entitlement Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Remove Entitlement Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Refer to [Configuration for Response]() for more information about the raw JSON response on which the **Response Information** schema is mapped.
>
> [![Remove Entitlement Response Mapping]()]()
### Update Account
This topic provides an example of a JSON response for an update account operation.
> [!NOTE]
>
> **Update Account Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Update Account (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Update Account**.
> 3. In the **Context URL** field, enter the URL specific to the account.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Update Account General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Update Account Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for updating accounts.
>
> In the **Raw** field, enter the JSON payload for the account.
>
> [![Update Account Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Update Account Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Refer to [Configuration for Response]() for more information about the raw JSON response on which the **Response Information** schema is mapped.
>
> [![Update Account Response Mapping]()]()
### Get Object
This topic provides an example of a JSON response for a get object operation.
> [!NOTE]
>
> **Get Object Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Get Object (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Get Object**.
> 3. In the **Context URL** field, enter the URL specific to the get object.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Get Object General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Get Object Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for get object.
>
> In the **Raw** field, enter the JSON payload for get object.
>
> In the following screenshot, the `$nativeIdentity$` signifies the AccountID (identity attribute) in the plan or during getObject operation. For example, `nativeIdentity` is used along with the keyword as follows:
>
> getobject: getObject.nativeIdentity
>
> This `$nativeIdentity$` can be used in the Authentication URL.
>
> [![Get Object Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Get Object Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Refer to [Configuration for Response]() for more information about the raw JSON response on which the **Response Information** schema is mapped.
>
> [![Get Object Response Mapping]()]()
### Enable Account
This topic provides an example of a JSON response for an enable account operation.
#### Enable Account - 1
To enable an account using the Web Services SaaS source you may set two operations such as Enable Account -1 and Enable Account - 2. In the first operation (Enable Account -1), the get object can be done and the returned response object is used as the input for the second operation (Enable Account - 2). Refer to the Header and Body of [Enable Account - 2](<#enable-account-2>).
> [!NOTE]
>
> **Enable Account - 1 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Enable Account - 1 (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Enable Account**.
> 3. In the **Context URL** field, enter the URL specific to the account.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Enable Account - 1 General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Enable Account - 1 Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for enabling an account.
>
> In the **Raw** field, enter the JSON payload for the account.
>
> [![Enable Account - 1 Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Enable Account - 1 Response Information]()]()
>
> On the **Response Mapping** tab:
>
> Refer to [Configuration for Response]() for more information about the raw JSON response on which the **Response Information** schema is mapped.
>
> [![Enable Account - 1 Response Mapping]()]()
#### Enable Account - 2
> [!NOTE]
>
> **Enable Account - 2 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Enable Account - 2 (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Enable Account**.
> 3. In the **Context URL** field, enter the URL specific to the account.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Enable Account - 2 General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Enable Account - 2 Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for enabling an account.
>
> In the **Raw** field, enter the JSON payload for the account.
>
> [![Enable Account - 2 Body]()]()
>
> On the **Response Information** tab:
>
> The **Root Path** is the common path present in the JSON response. The **Success Code** is the successful HTTP response code expected by the respective Web Service operation. By default, the success code is `2**`.
>
> [![Enable Account - 2 Response Information]()]()
### Disable Account
This topic provides an example of a JSON response for a disable account operation.
#### Disable Account - 1
To disable an account using the Web Services SaaS source you must set two operations such as Disable Account -1 and Disable Account - 2. In the first operation (Disable Account -1), the get object is done and the returned object is used as the input for the second operation (Disable Account - 2). Refer to the Header and Body of [Disable Account - 2](<#disable-account-2>).
> [!NOTE]
>
> **Disable Account - 1 Example**
>
> On the **General Information** tab:
>
> 1. In the **Operation Name** field, enter `Disable Account - 1 (JSON)` as the operation name.
> 2. From the **Operation Type** dropdown list, select **Disable Account**.
> 3. In the **Context URL** field, enter the URL specific to the account.
> 4. In the **HTTP Method** dropdown list, select **POST**.
>
> [![Disable Account - 1 General Information]()]()
>
> On the **Header and Body** tab:
>
> The Header has the data keys and their corresponding values. These key value pairs will be sent as part of the Header in the HTTP Request.
>
> [![Disable Account - 1 Header]()]()
>
> The HTTP body is used for posting the data with a request. The body has two data entry types, **Form Data** and **Raw**. You can use either of them for disabling an account.
>
> In the **Raw** field, enter the JSON payload for the account.
>
> [![Disable Account - 1 Body](