Create Rule
POST {{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules
The POST {{apiPath}}/environments/{{envID}}/propagation/rules operation adds a new propagation rule resource to the specified environment resource.
The property populationExpression is a SCIM filter applied to any user attribute of the source identity store.
Supported operators include sw (starts with), ew (ends with), co (contains), and eq (equals).
Refer to SCIM operators for a full list of operators and supported attributes.
For example, you can define a SCIM filter for a Workday inbound rule as:
"populationExpression": "supervisoryOrg eq \"Human Resources\""
and the rule will synchronize all users from Workday that have a supervisoryOrg of Human Resources.
Available user attributes for any store can be obtained with the appropriate request
found in Propagation Store Metadata
and looking under userAttributes.
Prerequisites
-
Refer to Identity Propagation (Provisioning) for important overview information.
-
Create a propagation plan to get a
planIDfor the endpoint and the body. Refer also to Identity Propagation (Provisioning), especially Propagation Plans. -
Create source and target propagation stores to get a
sourceStoreIDandtargetStoreIDfor the body. Refer also to Identity Propagation (Provisioning), especially Propagation Stores. -
Create a population to get a
popIDfor the body. Refer also to Populations.
Request Model
Refer to Propagation rule data model for full property descriptions.
| Property | Type | Required? |
|---|---|---|
|
Boolean |
Optional |
|
Object |
Required/Optional |
|
Boolean |
Optional |
|
String |
Optional |
|
Object[] |
Optional |
|
String |
Required |
|
String |
Required |
|
String |
Required |
|
String |
Optional |
|
String[] |
Optional |
|
String |
Required |
|
String |
Required |
The configuration object is required for outbound LDAP Gateway stores (type LdapGateway) and inbound LDAP Gateway stores (where users are provisioned into PingOne), optional for all others and ignored if used.
|
This outbound LDAP configuration object is required for outbound LDAP Gateway stores (type LdapGateway).
| Property | Type | Required? |
|---|---|---|
|
String |
Required |
|
String |
Required |
This inbound LDAP configuration object is required for inbound LDAP Gateway stores (where users are provisioned into PingOne).
If AUTHENTICATE_VIA_AD_LDAP is false, then the GATEWAY_USER_TYPE_* configuration attributes are optional and ignored if used. Note that USERS_BASE_DN is always required and unaffected by the value of AUTHENTICATE_VIA_AD_LDAP.
AUTHENTICATE_VIA_AD_LDAP can only be true if a userTypes object is configured in the gateway as returned by Read One Gateway. The remaining configuration attributes are required and must exactly match the corresponding attribute in the userTypes array object.
The userTypes object must not have a newUserLookup property if it is to be used with AUTHENTICATE_VIA_AD_LDAP as true.
|
| Property | Type | Required? |
|---|---|---|
|
Boolean |
Required |
|
Boolean |
Required/Optional |
|
String |
Required/Optional |
|
String |
Required/Optional |
|
String |
Required/Optional |
|
String |
Required/Optional |
|
String |
Required |
Body
raw ( application/json )
{
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": true,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
}
Example Request
-
cURL
-
C#
-
Go
-
HTTP
-
Java
-
jQuery
-
NodeJS
-
Python
-
PHP
-
Ruby
-
Swift
curl --location --globoff '{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{accessToken}}' \
--data '{
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": true,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
}'
var options = new RestClientOptions("{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules")
{
MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer {{accessToken}}");
var body = @"{" + "\n" +
@" ""plan"": {" + "\n" +
@" ""id"": ""{{planID}}""" + "\n" +
@" }," + "\n" +
@" ""environment"": {" + "\n" +
@" ""id"": ""{{envID}}""" + "\n" +
@" }," + "\n" +
@" ""sourceStore"": {" + "\n" +
@" ""id"": ""{{sourceStoreID}}""" + "\n" +
@" }," + "\n" +
@" ""targetStore"": {" + "\n" +
@" ""id"": ""{{targetStoreID}}""" + "\n" +
@" }," + "\n" +
@" ""groups"": [" + "\n" +
@" {" + "\n" +
@" ""id"": ""{{groupID}}""" + "\n" +
@" }" + "\n" +
@" ]," + "\n" +
@" ""deprovision"": true," + "\n" +
@" ""name"": ""rule name""," + "\n" +
@" ""description"": ""rule description""," + "\n" +
@" ""populationExpression"": ""population.id eq \""{{popID}}\""""" + "\n" +
@"}";
request.AddStringBody(body, DataFormat.Json);
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules"
method := "POST"
payload := strings.NewReader(`{
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": true,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
}`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer {{accessToken}}")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
POST /environments/{{envID}}/propagation/plans/{{planID}}/rules HTTP/1.1
Host: {{apiPath}}
Content-Type: application/json
Authorization: Bearer {{accessToken}}
{
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": true,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
}
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"plan\": {\n \"id\": \"{{planID}}\"\n },\n \"environment\": {\n \"id\": \"{{envID}}\"\n },\n \"sourceStore\": {\n \"id\": \"{{sourceStoreID}}\"\n },\n \"targetStore\": {\n \"id\": \"{{targetStoreID}}\"\n },\n \"groups\": [\n {\n \"id\": \"{{groupID}}\"\n }\n ],\n \"deprovision\": true,\n \"name\": \"rule name\",\n \"description\": \"rule description\",\n \"populationExpression\": \"population.id eq \\\"{{popID}}\\\"\"\n}");
Request request = new Request.Builder()
.url("{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer {{accessToken}}")
.build();
Response response = client.newCall(request).execute();
var settings = {
"url": "{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules",
"method": "POST",
"timeout": 0,
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {{accessToken}}"
},
"data": JSON.stringify({
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": true,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
}),
};
$.ajax(settings).done(function (response) {
console.log(response);
});
var request = require('request');
var options = {
'method': 'POST',
'url': '{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules',
'headers': {
'Content-Type': 'application/json',
'Authorization': 'Bearer {{accessToken}}'
},
body: JSON.stringify({
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": true,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules"
payload = json.dumps({
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": True,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
})
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {{accessToken}}'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Type' => 'application/json',
'Authorization' => 'Bearer {{accessToken}}'
));
$request->setBody('{\n "plan": {\n "id": "{{planID}}"\n },\n "environment": {\n "id": "{{envID}}"\n },\n "sourceStore": {\n "id": "{{sourceStoreID}}"\n },\n "targetStore": {\n "id": "{{targetStoreID}}"\n },\n "groups": [\n {\n "id": "{{groupID}}"\n }\n ],\n "deprovision": true,\n "name": "rule name",\n "description": "rule description",\n "populationExpression": "population.id eq \\"{{popID}}\\""\n}');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
require "uri"
require "json"
require "net/http"
url = URI("{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules")
http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer {{accessToken}}"
request.body = JSON.dump({
"plan": {
"id": "{{planID}}"
},
"environment": {
"id": "{{envID}}"
},
"sourceStore": {
"id": "{{sourceStoreID}}"
},
"targetStore": {
"id": "{{targetStoreID}}"
},
"groups": [
{
"id": "{{groupID}}"
}
],
"deprovision": true,
"name": "rule name",
"description": "rule description",
"populationExpression": "population.id eq \"{{popID}}\""
})
response = http.request(request)
puts response.read_body
let parameters = "{\n \"plan\": {\n \"id\": \"{{planID}}\"\n },\n \"environment\": {\n \"id\": \"{{envID}}\"\n },\n \"sourceStore\": {\n \"id\": \"{{sourceStoreID}}\"\n },\n \"targetStore\": {\n \"id\": \"{{targetStoreID}}\"\n },\n \"groups\": [\n {\n \"id\": \"{{groupID}}\"\n }\n ],\n \"deprovision\": true,\n \"name\": \"rule name\",\n \"description\": \"rule description\",\n \"populationExpression\": \"population.id eq \\\"{{popID}}\\\"\"\n}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "{{apiPath}}/environments/{{envID}}/propagation/plans/{{planID}}/rules")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer {{accessToken}}", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
print(String(data: data, encoding: .utf8)!)
}
task.resume()
Example Response
201 Created
{
"id": "66cc421f-8b1e-4b82-8f0b-20a1b7eec998",
"environment": {
"id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
},
"createdAt": "2023-05-22T18:08:32.784Z",
"updatedAt": "2023-05-22T18:08:32.784Z",
"plan": {
"id": "9b0f46a7-1987-4c80-8dfd-b4f34a96d216"
},
"sourceStore": {
"id": "01f31fb7-6e39-4678-9420-e3b2e7358fdd"
},
"targetStore": {
"id": "d43ab23a-0c41-46b7-9468-66b52561636e"
},
"name": "rule name",
"description": "rule description",
"active": false,
"populationExpression": "population.id eq \"cb3ef0a0-0ff5-4f60-ae82-4ae65d9d0e3a\"",
"deprovision": true,
"groups": [
{
"id": "1da23f50-4258-43e4-93cd-a7e9e9c5e167"
}
],
"_links": {
"create": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/propagation/plans/9b0f46a7-1987-4c80-8dfd-b4f34a96d216/rules"
},
"self": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/propagation/rules/66cc421f-8b1e-4b82-8f0b-20a1b7eec998"
},
"update": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/propagation/rules/66cc421f-8b1e-4b82-8f0b-20a1b7eec998"
},
"delete": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/propagation/rules/66cc421f-8b1e-4b82-8f0b-20a1b7eec998"
}
}
}