Performing RESTful OperationsHTTPJSONREST
OpenDJ lets you access directory data as
JSON
resources over HTTP.
OpenDJ maps JSON resources onto LDAP entries.
As a result, REST clients perform many of the same operations as LDAP clients
with directory data.
This chapter demonstrates RESTful client operations
by using the default configuration and sample directory data
imported into OpenDJ
from
Example.ldif.
In this chapter, you will learn how to use the OpenDJ REST API
that provides access to directory data over HTTP.
In particular, you will learn how to:
Create a resource that does not yet exist
Read a single resource
Update an existing resource
Delete an existing resource
Patch part of an existing resource
Perform a predefined action
Query a set of resources
Before trying the examples, enable HTTP access to
OpenDJ directory server as described in
the Administration Guide procedure,
To Set Up REST Access to OpenDJ Directory Server.
The examples in this chapter use HTTP,
but the procedure also shows how to set up HTTPS access to the server.
Interface stability:
Evolving
The OpenDJ REST API is built on a common ForgeRock HTTP-based REST API
for interacting with JSON Resources.
All APIs built on this common layer let you perform the following operations.
Failed to include common content ../shared/sec-about-crest.xml.
Authenticating Over REST
When you first try to read a resource
that can be read as an LDAP entry with an anonymous search,
you learn that you must authenticate as shown in the following example.
$ curl http://opendj.example.com:8080/users/bjensen{
"code" : 401,
"reason" : "Unauthorized",
"message" : "Unauthorized"
}
HTTP status code 401 indicates that the request requires user authentication.
To prevent OpenDJ directory server from requiring authentication,
set the HTTP connection handler property
authentication-required to false,
as in the following example.
$ dsconfig \
set-connection-handler-prop \
--hostname opendj.example.com \
--port 4444 \
--bindDN "cn=Directory Manager" \
--bindPassword password \
--handler-name "HTTP Connection Handler" \
--set authentication-required:false \
--no-prompt \
--trustAll
By default, both the HTTP Connection Handler and also the REST LDAP gateway
allow HTTP Basic authentication and HTTP header-based authentication
in the style of OpenIDM.
The authentication mechanisms translate HTTP authentication
to LDAP authentication to the directory server.
When you install OpenDJ either with generated sample user entries
or with data from
Example.ldif,
the relative distinguished name (DN) attribute for sample user entries
is the user ID (uid) attribute.
For example, the DN and user ID for Babs Jensen are:
dn: uid=bjensen,ou=People,dc=example,dc=com
uid: bjensen
Given this pattern in the user entries,
the default REST to LDAP configuration translates
the HTTP user name to the LDAP user ID.
User entries are found directly under
ou=People,dc=example,dc=com.
In general, REST to LDAP mappings require
that LDAP entries mapped to JSON resources
be immediate subordinates of the mapping's baseDN.
In other words, Babs Jensen authenticates as bjensen
(password: hifalutin) over HTTP.
The corresponding LDAP bind DN is
uid=bjensen,ou=People,dc=example,dc=com.
HTTP Basic authentication works as shown in the following example.
$ curl \
--user bjensen:hifalutin \
http://opendj.example.com:8080/users/bjensen{
"_rev" : "0000000016cbb68c",
...
}
The alternative HTTP Basic
username:password@ form
in the URL works as shown in the following example.
$ curl \
http://bjensen:hifalutin@opendj.example.com:8080/users/bjensen{
"_rev" : "0000000016cbb68c",
...
}
HTTP header based authentication works as shown in the following example.
$ curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: hifalutin" \
http://opendj.example.com:8080/users/bjensen{
"_rev" : "0000000016cbb68c",
...
}
If the directory data is laid out differently
or if the user names are email addresses rather than user IDs, for example,
then you must update the configuration in order for authentication to work.
The REST LDAP gateway can also translate
HTTP user name and password authentication to LDAP PLAIN SASL authentication.
Likewise, the gateway falls back to proxied authorization as necessary,
using a root DN authenticated connection to LDAP servers.
See the Reference appendix,
REST LDAP Configuration
for details on all configuration choices.
Creating Resources
There are two alternative ways to create resources.
To create a resource using an ID that you specify,
perform an HTTP PUT request with headers
Content-Type: application/json and
If-None-Match: *,
and the JSON content of your resource.
The following example shows you how to create
a new user entry with ID newuser.
$ curl \
--request PUT \
--user kvaughan:bribery \
--header "Content-Type: application/json" \
--header "If-None-Match: *" \
--data '{
"_id": "newuser",
"contactInformation": {
"telephoneNumber": "+1 408 555 1212",
"emailAddress": "newuser@example.com"
},
"name": {
"familyName": "New",
"givenName": "User"
},
"displayName": "New User",
"manager": [
{
"_id": "kvaughan",
"displayName": "Kirsten Vaughan"
}
]
}' \
http://opendj.example.com:8080/users/newuser{
"_rev" : "000000005b337348",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1212",
"emailAddress" : "newuser@example.com"
},
"_id" : "newuser",
"name" : {
"familyName" : "New",
"givenName" : "User"
},
"userName" : "newuser@example.com",
"displayName" : "New User",
"meta" : {
"created" : "2013-04-11T09:58:27Z"
},
"manager" : [ {
"_id" : "kvaughan",
"displayName" : "Kirsten Vaughan"
} ]
}
To create a resource in a way that lets the server choose the ID,
perform an HTTP POST with _action=create
as described in .
Reading a Resource
To read a resource, perform an HTTP GET as shown in the following example.
$ curl \
--request GET \
--user kvaughan:bribery \
http://opendj.example.com:8080/users/newuser{
"_rev" : "000000005b337348",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1212",
"emailAddress" : "newuser@example.com"
},
"_id" : "newuser",
"name" : {
"familyName" : "New",
"givenName" : "User"
},
"userName" : "newuser@example.com",
"displayName" : "New User",
"meta" : {
"created" : "2013-04-11T09:58:27Z"
},
"manager" : [ {
"_id" : "kvaughan",
"displayName" : "Kirsten Vaughan"
} ]
}Updating Resources
To update a resource, perform an HTTP PUT with the changes to the resource.
For read-only fields, either include unmodified versions,
or omit them from your updated version.
The following example adds a manager for Sam Carter.
$ curl \
--request PUT \
--user kvaughan:bribery \
--header "Content-Type: application/json" \
--data '{
"contactInformation": {
"telephoneNumber": "+1 408 555 4798",
"emailAddress": "scarter@example.com"
},
"name": {
"familyName": "Carter",
"givenName": "Sam"
},
"userName": "scarter@example.com",
"displayName": "Sam Carter",
"groups": [
{
"_id": "Accounting Managers"
}
],
"manager": [
{
"_id": "trigden",
"displayName": "Torrey Rigden"
}
]
}' \
http://opendj.example.com:8080/users/scarter{
"_rev" : "00000000a1923db2",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 4798",
"emailAddress" : "scarter@example.com"
},
"_id" : "scarter",
"name" : {
"familyName" : "Carter",
"givenName" : "Sam"
},
"userName" : "scarter@example.com",
"displayName" : "Sam Carter",
"manager" : [ {
"_id" : "trigden",
"displayName" : "Torrey Rigden"
} ],
"meta" : {
"lastModified" : "2013-04-12T07:42:34Z"
},
"groups" : [ {
"_id" : "Accounting Managers"
} ]
}
To update a resource only if the resource matches a particular version,
use an If-Match: revision header
as shown in the following example.
$ curl \
--user kvaughan:bribery \
http://opendj.example.com:8080/users/scarter?_fields=_rev{"_rev":"00000000b017c5b8"}
$ curl \
--request PUT \
--user kvaughan:bribery \
--header "If-Match: 00000000b017c5b8" \
--header "Content-Type: application/json" \
--data '{
"contactInformation": {
"telephoneNumber": "+1 408 555 1212",
"emailAddress": "scarter@example.com"
},
"name": {
"familyName": "Carter",
"givenName": "Sam"
},
"userName": "scarter@example.com",
"displayName": "Sam Carter",
"groups": [
{
"_id": "Accounting Managers"
}
],
"manager": [
{
"_id": "trigden",
"displayName": "Torrey Rigden"
}
]
}' \
http://opendj.example.com:8080/users/scarter{
"_rev" : "00000000a1ee3da3",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1212",
"emailAddress" : "scarter@example.com"
},
"_id" : "scarter",
"name" : {
"familyName" : "Carter",
"givenName" : "Sam"
},
"userName" : "scarter@example.com",
"displayName" : "Sam Carter",
"meta" : {
"lastModified" : "2013-04-12T07:47:45Z"
},
"groups" : [ {
"_id" : "Accounting Managers"
} ],
"manager" : [ {
"_id" : "trigden",
"displayName" : "Torrey Rigden"
} ]
}Deleting Resources
To delete a resource, perform an HTTP DELETE on the resource URL.
The operation returns the resource you deleted as shown in the following example.
$ curl \
--request DELETE \
--user kvaughan:bribery \
http://opendj.example.com:8080/users/newuser{
"_rev" : "000000003a5f3cb2",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1212",
"emailAddress" : "newuser@example.com"
},
"_id" : "newuser",
"name" : {
"familyName" : "New",
"givenName" : "User"
},
"userName" : "newuser@example.com",
"displayName" : "New User",
"meta" : {
"created" : "2013-04-11T09:58:27Z"
},
"manager" : [ {
"_id" : "kvaughan",
"displayName" : "Kirsten Vaughan"
} ]
}
To delete a resource only if the resource matches a particular version,
use an If-Match: revision header
as shown in the following example.
$ curl \
--user kvaughan:bribery \
http://opendj.example.com:8080/users/newuser?_fields=_rev{"_rev":"000000006d8d7358"}
$ curl \
--request DELETE \
--user kvaughan:bribery \
--header "If-Match: 000000006d8d7358" \
http://opendj.example.com:8080/users/newuser{
"_rev" : "00000000383f3cae",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1212",
"emailAddress" : "newuser@example.com"
},
"_id" : "newuser",
"name" : {
"familyName" : "New",
"givenName" : "User"
},
"userName" : "newuser@example.com",
"displayName" : "New User",
"meta" : {
"created" : "2013-04-11T12:48:48Z"
},
"manager" : [ {
"_id" : "kvaughan",
"displayName" : "Kirsten Vaughan"
} ]
}
To delete a resource and all of its children,
you must change the configuration,
get the REST LDAP gateway or HTTP Connection Handler to reload its configuration,
and perform the operation as a user who has the access rights required.
The following steps show one way to do this with the HTTP Connection Handler.
In this example, the LDAP view of the user to delete shows two child entries
as seen in the following example.
$ ldapsearch --port 1389 --baseDN uid=nbohr,ou=people,dc=example,dc=com "(&)" dndn: uid=nbohr,ou=People,dc=example,dc=com
dn: cn=quantum dot,uid=nbohr,ou=People,dc=example,dc=com
dn: cn=qubit generator,uid=nbohr,ou=People,dc=example,dc=com
In the configuration file for the HTTP Connection Handler,
by default /path/to/opendj/config/http-config.json,
set "useSubtreeDelete" : true.
After this change, only users who have access to request a tree delete
can delete resources.
Force the HTTP Connection Handler to reread its configuration
as shown in the following dsconfig commands.
$ dsconfig \
set-connection-handler-prop \
--hostname opendj.example.com \
--port 4444 \
--bindDN "cn=Directory Manager" \
--bindPassword password \
--handler-name "HTTP Connection Handler" \
--set enabled:false \
--no-prompt
$ dsconfig \
set-connection-handler-prop \
--hostname opendj.example.com \
--port 4444 \
--bindDN "cn=Directory Manager" \
--bindPassword password \
--handler-name "HTTP Connection Handler" \
--set enabled:true \
--no-prompt
Request the delete as a user who has rights
to perform a subtree delete on the resource
as shown in the following example.
$ curl \
--request DELETE \
--user kvaughan:bribery \
http://opendj.example.com:8080/users/nbohr{
"_rev" : "000000003d912113",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1212",
"emailAddress" : "nbohr@example.com"
},
"_id" : "nbohr",
"name" : {
"familyName" : "Bohr",
"givenName" : "Niels"
},
"userName" : "nbohr@example.com",
"displayName" : "Niels Bohr"
}Patching Resources
OpenDJ lets you patch JSON resources,
updating part of the resource rather than replacing it.
For example, you could change Babs Jensen's email address
by issuing an HTTP PATCH request as in the following example.
$ curl \
--user kvaughan:bribery \
--request PATCH \
--header "Content-Type: application/json" \
--data '[
{
"operation": "replace",
"field": "/contactInformation/emailAddress",
"value": "babs@example.com"
}
]' \
http://opendj.example.com:8080/users/bjensen{
"_rev" : "00000000f3fdd370",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1862",
"emailAddress" : "babs@example.com"
},
"_id" : "bjensen",
"name" : {
"familyName" : "Jensen",
"givenName" : "Barbara"
},
"userName" : "babs@example.com",
"displayName" : "Barbara Jensen",
"meta" : {
"lastModified" : "2013-05-13T14:35:31Z"
},
"manager" : [ {
"_id" : "trigden",
"displayName" : "Torrey Rigden"
} ]
}
Notice in the example that the data sent specifies
the type of patch operation, the field to change,
and a value that depends on the field you change and on the operation.
A single-valued field takes an object, boolean, string, or number
depending on its type,
whereas a multi-valued field takes an array of values.
Getting the type wrong results in an error.
Also notice that the patch data is itself an array.
This makes it possible to patch more than one part of the resource
by using a set of patch operations in the same request.
OpenDJ supports four types of patch operations:
add
The add operation ensures that the target field contains the value provided,
creating parent fields as necessary.
If the target field is single-valued and a value already exists,
then that value is replaced with the value you provide.
Note that you do not get an error when adding a value
to a single-valued field that already has a value.
A single-valued field is one whose value is not an array
(an object, string, boolean, or number).
If the target field is multi-valued,
then the array of values you provide is merged
with the set of values already in the resource.
New values are added, and duplicate values are ignored.
A multi-valued field takes an array value.
remove
The remove operation ensures that the target field
does not contain the value provided.
If you do not provide a value, the entire field is removed
if it already exists.
If the target field is single-valued and a value is provided,
then the provided value must match the existing value to remove,
otherwise the field is left unchanged.
If the target field is multi-valued,
then values in the array you provide are removed
from the existing set of values.
replace
The replace operation removes existing values on the target field,
and replaces them with the values you provide.
It is equivalent to performing a remove on the field,
then an add with the values you provide.
increment
The increment operation increments or decrements
the value or values in the target field by the amount you specify,
which is positive to increment and negative to decrement.
The target field must take a number or a set of numbers.
The value you provide must be a single number.
One key nuance in how a patch works with OpenDJ concerns multi-valued fields.
Although JSON resources represent multi-valued fields
as arrays,
OpenDJ treats those values as sets.
In other words, values in the field are unique,
and the ordering of an array of values is not meaningful
in the context of patch operations.
If you reference array values by index, OpenDJ returns an error.
OpenDJ does allow use of a hyphen to add an element to a set.
Include the hyphen as the last element
of the field JSON pointer path.
For example:
curl --user kvaughan:bribery --request PATCH --header "Content-Type:
application/json" --data '[{ "operation" : "add", "field" : "/members/-",
"value" : { "_id" : "bjensen" } }]'
http://opendj.example.com:8080/groups/Directory%20Administrators.
Perform patch operations as if arrays values were sets.
The following example includes Barbara Jensen in a group
by adding her to the set of members.
$ curl \
--user kvaughan:bribery \
--request PATCH \
--header "Content-Type: application/json" \
--data '[
{
"operation": "add",
"field": "/members",
"value": [
{
"_id": "bjensen"
}
]
}
]' \
http://opendj.example.com:8080/groups/Directory%20Administrators{
"_rev" : "00000000b70c881a",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"_id" : "Directory Administrators",
"displayName" : "Directory Administrators",
"meta" : {
"lastModified" : "2013-05-13T16:40:23Z"
},
"members" : [ {
"_id" : "kvaughan",
"displayName" : "Kirsten Vaughan"
}, {
"_id" : "rdaugherty",
"displayName" : "Robert Daugherty"
}, {
"_id" : "bjensen",
"displayName" : "Barbara Jensen"
}, {
"_id" : "hmiller",
"displayName" : "Harry Miller"
} ]
}
The following example removes Barbara Jensen from the group.
$ curl \
--user kvaughan:bribery \
--request PATCH \
--header "Content-Type: application/json" \
--data '[
{
"operation": "remove",
"field": "/members",
"value": [
{
"_id": "bjensen"
}
]
}
]' \
http://opendj.example.com:8080/groups/Directory%20Administrators{
"_rev" : "00000000e241797e",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"_id" : "Directory Administrators",
"displayName" : "Directory Administrators",
"meta" : {
"lastModified" : "2013-05-13T16:40:55Z"
},
"members" : [ {
"_id" : "kvaughan",
"displayName" : "Kirsten Vaughan"
}, {
"_id" : "rdaugherty",
"displayName" : "Robert Daugherty"
}, {
"_id" : "hmiller",
"displayName" : "Harry Miller"
} ]
}
To change the value of more than one attribute in a patch operation,
include multiple operations in the body of the JSON patch,
as shown in the following example.
$ curl \
--user kvaughan:bribery \
--request PATCH \
--header "Content-Type: application/json" \
--data '[
{
"operation": "replace",
"field": "/contactInformation/telephoneNumber",
"value": "+1 408 555 9999"
},
{
"operation": "add",
"field": "/contactInformation/emailAddress",
"value": "barbara.jensen@example.com"
}
]' \
http://opendj.example.com:8080/users/bjensen{
"contactInformation": {
"emailAddress": "barbara.jensen@example.com",
"telephoneNumber": "+1 408 555 9999"
},
"displayName": "Barbara Jensen",
"manager": [
{
"displayName": "Torrey Rigden",
"_id": "trigden"
}
],
"meta": {
"lastModified": "2015-04-07T10:19:41Z"
},
"schemas": [
"urn:scim:schemas:core:1.0"
],
"_rev": "00000000e68ef438",
"name": {
"givenName": "Barbara",
"familyName": "Jensen"
},
"_id": "bjensen",
"userName": "barbara.jensen@example.com"
}
Notice that for a multi-valued attribute,
the value field takes an array,
whereas the value field takes
a single value for a single-valued field.
Also notice that for single-valued fields,
an add operation has the same effect
as a replace operation.
You can use resource revision numbers
in If-Match: revision headers
to patch the resource only if the resource matches a particular version,
as shown in the following example.
$ curl \
--user kvaughan:bribery \
http://opendj.example.com:8080/users/bjensen?_fields=_rev{
"_rev" : "00000000c1b6d4c7"
}
$ curl \
--user kvaughan:bribery \
--request PATCH \
--header "If-Match: 00000000c1b6d4c7" \
--header "Content-Type: application/json" \
--data '[
{
"operation": "add",
"field": "/contactInformation/emailAddress",
"value": "babs@example.com"
}
]' \
http://opendj.example.com:8080/users/bjensen{
"_rev" : "00000000f946d377",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1862",
"emailAddress" : "babs@example.com"
},
"_id" : "bjensen",
"name" : {
"familyName" : "Jensen",
"givenName" : "Barbara"
},
"userName" : "babs@example.com",
"displayName" : "Barbara Jensen",
"meta" : {
"lastModified" : "2013-05-13T16:56:33Z"
},
"manager" : [ {
"_id" : "trigden",
"displayName" : "Torrey Rigden"
} ]
}
The resource revision changes when the patch is successful.
Using Actions
OpenDJ implements an action that lets the server
set the resource ID on creation.
To use this action, perform an HTTP POST
with header Content-Type: application/json,
_action=create in the query string,
and the JSON content of the resource.
The following example creates a new user entry.
$ curl \
--request POST \
--user kvaughan:bribery \
--header "Content-Type: application/json" \
--data '{
"_id": "newuser",
"contactInformation": {
"telephoneNumber": "+1 408 555 1212",
"emailAddress": "newuser@example.com"
},
"name": {
"familyName": "New",
"givenName": "User"
},
"displayName": "New User",
"manager": [
{
"_id": "kvaughan",
"displayName": "Kirsten Vaughan"
}
]
}' \
http://opendj.example.com:8080/users?_action=create{
"_rev" : "0000000034a23ca7",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1212",
"emailAddress" : "newuser@example.com"
},
"_id" : "newuser",
"name" : {
"familyName" : "New",
"givenName" : "User"
},
"userName" : "newuser@example.com",
"displayName" : "New User",
"meta" : {
"created" : "2013-04-11T11:19:08Z"
},
"manager" : [ {
"_id" : "kvaughan",
"displayName" : "Kirsten Vaughan"
} ]
}Querying Resource Collections
To query resource collections, perform an HTTP GET with a
_queryFilter=expression parameter
in the query string.
The following listing summarizes the string representation
for the filter expression.
Expr = OrExpr
OrExpr = AndExpr ( 'or' AndExpr ) *
AndExpr = NotExpr ( 'and' NotExpr ) *
NotExpr = '!' PrimaryExpr | PrimaryExpr
PrimaryExpr = '(' Expr ')' | ComparisonExpr | PresenceExpr | LiteralExpr
ComparisonExpr = Pointer OpName JsonValue
PresenceExpr = Pointer 'pr'
LiteralExpr = 'true' | 'false'
Pointer = JSON pointer
OpName = 'eq' | # equal to
'co' | # contains
'sw' | # starts with
'lt' | # less than
'le' | # less than or equal to
'gt' | # greater than
'ge' | # greater than or equal to
STRING # extended operator
JsonValue = NUMBER | BOOLEAN | '"' UTF8STRING '"'
STRING = ASCII string not containing white-space
UTF8STRING = UTF-8 string possibly containing white-space
The following table shows some LDAP search filters
with corresponding examples of query filter expressions.
For query operations, the filter expression
is constructed from the following building blocks.
Make sure you URL-encode the filter expressions,
which are shown here without URL encoding to make them easier to read.
In filter expressions, the simplest json-pointer
is a field of the JSON resource,
such as userName or id.
A json-pointer can also point to nested elements
as described in the
JSON Pointer Internet-Draft.
Comparison expressions
Build filters using the following comparison expressions:
json-pointer eq json-value
Matches when the pointer equals the value, as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName+eq+"bjensen@example.com"'{
"result" : [ {
"_rev" : "00000000315fb731",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"manager" : [ {
"_id" : "trigden",
"displayName" : "Torrey Rigden"
} ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 1862",
"emailAddress" : "bjensen@example.com"
},
"_id" : "bjensen",
"name" : {
"familyName" : "Jensen",
"givenName" : "Barbara"
},
"userName" : "bjensen@example.com",
"displayName" : "Barbara Jensen"
} ],
"resultCount" : 1,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}json-pointer co json-value
Matches when the pointer contains the value, as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName+co+"jensen"&_fields=userName'{
"result" : [ {
"userName" : "ajensen@example.com"
}, {
"userName" : "bjensen@example.com"
}, {
"userName" : "gjensen@example.com"
}, {
"userName" : "jjensen@example.com"
}, {
"userName" : "kjensen@example.com"
}, {
"userName" : "rjensen@example.com"
}, {
"userName" : "tjensen@example.com"
} ],
"resultCount" : 7,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}json-pointer sw json-value
Matches when the pointer starts with the value, as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName+sw+"ab"&_fields=userName'{
"result" : [ {
"userName" : "abarnes@example.com"
}, {
"userName" : "abergin@example.com"
} ],
"resultCount" : 2,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}json-pointer lt json-value
Matches when the pointer is less than the value, as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName+lt+"ac"&_fields=userName'{
"result" : [ {
"userName" : "abarnes@example.com"
}, {
"userName" : "abergin@example.com"
} ],
"resultCount" : 2,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}json-pointer le json-value
Matches when the pointer is less than or equal to the value,
as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName+le+"ad"&_fields=userName'{
"result" : [ {
"userName" : "abarnes@example.com"
}, {
"userName" : "abergin@example.com"
}, {
"userName" : "achassin@example.com"
} ],
"resultCount" : 3,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}json-pointer gt json-value
Matches when the pointer is greater than the value,
as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName+gt+"tt"&_fields=userName'{
"result" : [ {
"userName" : "ttully@example.com"
}, {
"userName" : "tward@example.com"
}, {
"userName" : "wlutz@example.com"
} ],
"resultCount" : 3,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}json-pointer ge json-value
Matches when the pointer is greater than or equal to the value,
as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName+ge+"tw"&_fields=userName'{
"result" : [ {
"userName" : "tward@example.com"
}, {
"userName" : "wlutz@example.com"
} ],
"resultCount" : 2,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}Presence expressionjson-pointer pr
matches any resource on which
the json-pointer is present,
as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=userName%20pr'{
"result" : [ {
"_rev" : "000000002210a544",
"schemas" : [ "urn:scim:schemas:core:1.0" ],
"manager" : [ {
"_id" : "scarter",
"displayName" : "Sam Carter"
} ],
"contactInformation" : {
"telephoneNumber" : "+1 408 555 9445",
"emailAddress" : "abarnes@example.com"
},
"_id" : "abarnes",
"name" : {
"familyName" : "Barnes",
"givenName" : "Anne-Louise"
},
"userName" : "abarnes@example.com",
"displayName" : "Anne-Louise Barnes"
},… many entries omitted …
"_id" : "newuser",
"name" : {
"familyName" : "New",
"givenName" : "User"
},
"userName" : "newuser@example.com",
"displayName" : "New User",
"meta" : {
"created" : "2013-03-26T10:52:42Z"
}
} ],
"resultCount" : 152,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}Literal expressionstrue matches any resource in the collection.
false matches no resource in the collection.
In other words, you can list all resources in a collection
as in the following example.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/groups?_queryFilter=true&_fields=displayName'{
"result" : [ {
"displayName" : "Accounting Managers"
}, {
"displayName" : "Directory Administrators"
}, {
"displayName" : "HR Managers"
}, {
"displayName" : "PD Managers"
}, {
"displayName" : "QA Managers"
} ],
"resultCount" : 5,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}Complex expressions
Combine expressions using boolean operators
and, or, and ! (not),
and by using parentheses (expression)
with group expressions.
The following example queries resources with last name Jensen
and manager name starting with Bar.
$ curl \
--user kvaughan:bribery \
'http://opendj.example.com:8080/users?_queryFilter=\
(userName+co+"jensen"+and+manager/displayName+sw+"Sam")&_fields=displayName'{
"result" : [ {
"displayName" : "Jody Jensen"
}, {
"displayName" : "Ted Jensen"
} ],
"resultCount" : 2,
"pagedResultsCookie" : null,
"remainingPagedResults" : -1
}
Notice that the filters use the JSON pointers
name/familyName
and manager/displayName
to identify the fields nested inside the
name and manager objects.
You can page through search results using the following query string parameters.
_pagedResultsCookie=string
Opaque cookie used by the server to keep track of the position
in the search results.
In the request also set _pageSize greater than zero.
You receive the cookie value from the server on the first request,
and then supply the cookie value in subsequent requests
until the server returns a null cookie,
meaning that the final page of results has been returned.
_pagedResultsOffset=integer
When _pageSize is greater than zero,
use this as an index in the result set indicating the page to return.
When the value of _pagedResultsOffset is 1 or more,
the server returns the page starting from the specified index.
When _pagedResultsCookie is also set,
the starting point is the position tracked by the cookie.
Otherwise, the offset is relative to the beginning of the result set.
For example, _pageSize=2&_pagedResultsOffset=1
returns the third and fourth entries of the results.
_pageSize=3&_pagedResultsOffset=2&_pagedResultsCookie=cookie
returns the seventh, eighth, and ninth entries
counting from the position tracked by the cookie.
When _pageSize is not set,
or when the value of _pagedResultsOffset is 0 or less,
the setting has no effect.
If other _pageSize is set,
but the offset points to a page beyond the last of the search results,
the result set returned is empty.
_pageSize=integer
Return query results in pages of this size,
where integer should be greater than zero.
Page sizes of zero or less have no effect,
with the outcome that all results are returned,
and _pagedResultsCookie is null
in the response.
After the initial request, use _pagedResultsCookie
to page through the results.
The following example demonstrates how paged results are used.
$ curl \
--user bjensen:hifalutin \
"http://opendj.example.com:8080/users?_queryFilter=true&_fields=userName&_pageSize=5"{
"result" : [ {
"userName" : "abarnes@example.com"
}, {
"userName" : "abergin@example.com"
}, {
"userName" : "achassin@example.com"
}, {
"userName" : "ahall@example.com"
}, {
"userName" : "ahel@example.com"
} ],
"resultCount" : 5,
"pagedResultsCookie" : "AAAAAAAAAA8=",
"remainingPagedResults" : -1
}
$ curl \
--user bjensen:hifalutin \
"http://opendj.example.com:8080/users?_queryFilter=true&_fields=userName&_pageSize=5\
&_pagedResultsCookie=AAAAAAAAAA8="{
"result" : [ {
"userName" : "ahunter@example.com"
}, {
"userName" : "ajensen@example.com"
}, {
"userName" : "aknutson@example.com"
}, {
"userName" : "alangdon@example.com"
}, {
"userName" : "alutz@example.com"
} ],
"resultCount" : 5,
"pagedResultsCookie" : "AAAAAAAAABQ=",
"remainingPagedResults" : -1
}
$ curl \
--user bjensen:hifalutin \
"http://opendj.example.com:8080/users?_queryFilter=true&_fields=userName&_pageSize=5\
&_pagedResultsCookie=AAAAAAAAAA8=&_pagedResultsOffset=10"{
"result" : [ {
"userName" : "gtriplet@example.com"
}, {
"userName" : "gtyler@example.com"
}, {
"userName" : "hmiller@example.com"
}, {
"userName" : "jbourke@example.com"
}, {
"userName" : "jbrown@example.com"
} ],
"resultCount" : 5,
"pagedResultsCookie" : "AAAAAAAAAEY=",
"remainingPagedResults" : -1
}
The first call requests five results per page, and retrieves the first page.
The next call provides the cookie to request the next five results.
The final call provides the cookie and requests the 10th page of results
after the last page of results specified by the cookie.
Notice that "remainingPagedResults" : -1 in each case,
meaning that the number of remaining results is not known.