PingDirectory API Reference

Update Replace One or More User Attributes

PATCH {{apiPath}}/scim/v2/Users/{{id}}

The PATCH /scim/v2/Users/{{id}} endpoint is used to add, modify, or remove one or more specific attributes. Unlike PUT, a complete representation is not specified.

PATCH requests always include an Operations attribute in the body. This is an array of the changes to make.

Field Type Required? Description

schemas

array

yes

The SCIM schema of the session resource. Always has the value urn:ietf:params:scim:api:messages:2.0:Patch0p.

Operations

array

yes

An array of modification operations to perform on the resource.

Each modification operation contains the following fields:

Field Type Required? Description

op

string

yes

Specifies the type of modification. Valid values are add, remove, and replace.

path

string

no

The attribute path targeted by the operation. If unspecified, then the root of the resource is targeted. To target a specific member of a multivalued complex attribute when performing a replace, the attribute path may include a filter, such as addresses[type eq "work"]. A sub-attribute may be targeted using a dotted attribute.sub-attribute notation, such as addresses[type eq "work"].value

value

any

no

The attribute value to set when the op value is add or replace. May not be provided when the op value is remove. Any SCIM data type may potentially be used; the validity of the value is dependent on the path.

The combination of op, path, and value gives the client a tremendous amount of expressive power in forming varied modification requests. Because the path used may potentially select any node of the resource, the client must take care to specify a value of the appropriate type. For example, the path addresses[type eq "work"] selects the member of a multivalued complex attribute, so the corresponding value must be an object. The path addresses[type eq "work"].value, meanwhile, selects a specific sub-attribute of the same object, and its corresponding value must be a string.

The SCIM PATCH request format is described in detail by RFC 7644.

The sample replaces the value of a sub-attribute of a complex attribute.

The User resource and its attributes are defined in RFC 7643, Section 4.1.

Headers

Authorization      Bearer {{accessToken}}

Content-Type      application/scim+json

Accept      application/scim+json

Body

raw ( application/scim+json )

{
    "Operations": [
        {
            "op": "replace",
            "path": "name.familyName",
            "value": "Chip"
        }
    ],
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ]
}

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff --request PATCH '{{apiPath}}/scim/v2/Users/{{id}}' \
--header 'Content-Type: application/scim+json' \
--header 'Accept: application/scim+json' \
--header 'Authorization: Bearer {{accessToken}}' \
--data '{
    "Operations": [
        {
            "op": "replace",
            "path": "name.familyName",
            "value": "Chip"
        }
    ],
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ]
}'
var options = new RestClientOptions("{{apiPath}}/scim/v2/Users/{{id}}")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Patch);
request.AddHeader("Content-Type", "application/scim+json");
request.AddHeader("Accept", "application/scim+json");
request.AddHeader("Authorization", "Bearer {{accessToken}}");
var body = @"{" + "\n" +
@"    ""Operations"": [" + "\n" +
@"        {" + "\n" +
@"            ""op"": ""replace""," + "\n" +
@"            ""path"": ""name.familyName""," + "\n" +
@"            ""value"": ""Chip""" + "\n" +
@"        }" + "\n" +
@"    ]," + "\n" +
@"    ""schemas"": [" + "\n" +
@"        ""urn:ietf:params:scim:api:messages:2.0:PatchOp""" + "\n" +
@"    ]" + "\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}}/scim/v2/Users/{{id}}"
  method := "PATCH"

  payload := strings.NewReader(`{
    "Operations": [
        {
            "op": "replace",
            "path": "name.familyName",
            "value": "Chip"
        }
    ],
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ]
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/scim+json")
  req.Header.Add("Accept", "application/scim+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))
}
PATCH /scim/v2/Users/{{id}} HTTP/1.1
Host: {{apiPath}}
Content-Type: application/scim+json
Accept: application/scim+json
Authorization: Bearer {{accessToken}}

{
    "Operations": [
        {
            "op": "replace",
            "path": "name.familyName",
            "value": "Chip"
        }
    ],
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ]
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/scim+json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"Operations\": [\n        {\n            \"op\": \"replace\",\n            \"path\": \"name.familyName\",\n            \"value\": \"Chip\"\n        }\n    ],\n    \"schemas\": [\n        \"urn:ietf:params:scim:api:messages:2.0:PatchOp\"\n    ]\n}");
Request request = new Request.Builder()
  .url("{{apiPath}}/scim/v2/Users/{{id}}")
  .method("PATCH", body)
  .addHeader("Content-Type", "application/scim+json")
  .addHeader("Accept", "application/scim+json")
  .addHeader("Authorization", "Bearer {{accessToken}}")
  .build();
Response response = client.newCall(request).execute();
var settings = {
  "url": "{{apiPath}}/scim/v2/Users/{{id}}",
  "method": "PATCH",
  "timeout": 0,
  "headers": {
    "Content-Type": "application/scim+json",
    "Accept": "application/scim+json",
    "Authorization": "Bearer {{accessToken}}"
  },
  "data": JSON.stringify({
    "Operations": [
      {
        "op": "replace",
        "path": "name.familyName",
        "value": "Chip"
      }
    ],
    "schemas": [
      "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ]
  }),
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var options = {
  'method': 'PATCH',
  'url': '{{apiPath}}/scim/v2/Users/{{id}}',
  'headers': {
    'Content-Type': 'application/scim+json',
    'Accept': 'application/scim+json',
    'Authorization': 'Bearer {{accessToken}}'
  },
  body: JSON.stringify({
    "Operations": [
      {
        "op": "replace",
        "path": "name.familyName",
        "value": "Chip"
      }
    ],
    "schemas": [
      "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ]
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests
import json

url = "{{apiPath}}/scim/v2/Users/{{id}}"

payload = json.dumps({
  "Operations": [
    {
      "op": "replace",
      "path": "name.familyName",
      "value": "Chip"
    }
  ],
  "schemas": [
    "urn:ietf:params:scim:api:messages:2.0:PatchOp"
  ]
})
headers = {
  'Content-Type': 'application/scim+json',
  'Accept': 'application/scim+json',
  'Authorization': 'Bearer {{accessToken}}'
}

response = requests.request("PATCH", url, headers=headers, data=payload)

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{apiPath}}/scim/v2/Users/{{id}}');
$request->setMethod('PATCH');
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/scim+json',
  'Accept' => 'application/scim+json',
  'Authorization' => 'Bearer {{accessToken}}'
));
$request->setBody('{\n    "Operations": [\n        {\n            "op": "replace",\n            "path": "name.familyName",\n            "value": "Chip"\n        }\n    ],\n    "schemas": [\n        "urn:ietf:params:scim:api:messages:2.0:PatchOp"\n    ]\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}}/scim/v2/Users/{{id}}")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Patch.new(url)
request["Content-Type"] = "application/scim+json"
request["Accept"] = "application/scim+json"
request["Authorization"] = "Bearer {{accessToken}}"
request.body = JSON.dump({
  "Operations": [
    {
      "op": "replace",
      "path": "name.familyName",
      "value": "Chip"
    }
  ],
  "schemas": [
    "urn:ietf:params:scim:api:messages:2.0:PatchOp"
  ]
})

response = http.request(request)
puts response.read_body
let parameters = "{\n    \"Operations\": [\n        {\n            \"op\": \"replace\",\n            \"path\": \"name.familyName\",\n            \"value\": \"Chip\"\n        }\n    ],\n    \"schemas\": [\n        \"urn:ietf:params:scim:api:messages:2.0:PatchOp\"\n    ]\n}"
let postData = parameters.data(using: .utf8)

var request = URLRequest(url: URL(string: "{{apiPath}}/scim/v2/Users/{{id}}")!,timeoutInterval: Double.infinity)
request.addValue("application/scim+json", forHTTPHeaderField: "Content-Type")
request.addValue("application/scim+json", forHTTPHeaderField: "Accept")
request.addValue("Bearer {{accessToken}}", forHTTPHeaderField: "Authorization")

request.httpMethod = "PATCH"
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

{
    "emails": [
        {
            "primary": true,
            "type": "work",
            "value": "pat.conley@runciter.com"
        }
    ],
    "id": "76b4c133-87a7-4b2f-8058-4716e78b0fd4",
    "meta": {
        "created": "2016-07-30T00:05:29.968Z",
        "lastModified": "2016-07-30T00:11:37.147Z",
        "location": "https://example.com:443/scim/v2/Users/76b4c133-87a7-4b2f-8058-4716e78b0fd4",
        "resourceType": "Users"
    },
    "name": {
        "familyName": "Chip",
        "formatted": "Pat Conley",
        "givenName": "Pat"
    },
    "schemas": [
        "urn:pingidentity:schemas:sample:profile:1.0",
        "urn:pingidentity:schemas:User:1.0"
    ],
    "urn:pingidentity:schemas:sample:profile:1.0": {
        "birthDate": "1948-07-13"
    },
    "userName": "pconley"
}