---
title: Managed objects reference
description: A managed object is an object that represents the identity-related data managed by IDM. Managed objects are stored in the IDM repository. All managed objects are JSON-based data structures.
component: pingidm
version: 8.1
page_id: pingidm:objects-guide:appendix-managed-objects
canonical_url: https://docs.pingidentity.com/pingidm/8.1/objects-guide/appendix-managed-objects.html
keywords: ["Data Object Model", "Schema", "Triggers", "Scripts"]
section_ids:
  managed-object-schema: Managed object schema
  managed-object-data-consistency: Data consistency
  managed-object-triggers: Managed object triggers
  managed-object-state-triggers: State triggers
  managed-object-storage-triggers: Object storage triggers
  managed-object-property-storage-triggers: Property storage triggers
  managed-object-storage-trigger-sequences: Storage trigger sequences
  managed-object-encryption: Managed object encryption
  managed-object-configuration: Managed object configuration
  managed_object_config_object_properties: Managed-object-config object properties
  managed-object-property-config-properties: Property configuration properties
  script_object_properties: Script Object Properties
  property_encryption_object: Property Encryption Object
  property_hash_object: Property Hash Object
  custom-managed-objects: Custom managed objects
  managed-objects-setup: Set up a managed object type
  managed-objects-declarative: Manipulate managed objects declaratively
  managed-objects-programmatic: Manipulate managed objects programmatically
  managed-objects-programmatic-create: Create objects
  managed-objects-programmatic-update: Update objects
  managed-objects-programmatic-patch: Patch objects
  managed-objects-programmatic-delete: Delete objects
  managed-objects-programmatic-read: Read objects
  managed-objects-programmatic-query: Query object sets
  managed-objects-access-rest: Access managed objects through the REST API
---

# Managed objects reference

A *managed object* is an object that represents the identity-related data managed by IDM. Managed objects are stored in the IDM repository. All managed objects are JSON-based data structures.

## Managed object schema

IDM provides a default schema for typical managed object types, such as users and roles, but does not control the structure of objects that you store in the repository. You can modify or extend the schema for the default object types, and you can set up a new managed object type for any item that can be collected in a data set.

The `_rev` property of a managed object is reserved for internal use, and is not explicitly part of its schema. This property specifies the revision of the object in the repository. This is the same value that is exposed as the object's ETag through the REST API. The content of this attribute is not defined. No consumer should make any assumptions of its content beyond equivalence comparison. This attribute may be provided by the underlying data store.

Schema validation is performed by the [policy service](policies.html) and can be configured according to the requirements of your deployment.

Properties can be defined to be strictly derived from other properties within the object. This allows computed and composite values to be created in the object. Such properties are named *virtual properties*. The value of a virtual property is computed only when that property is retrieved.

## Data consistency

Single-object operations are consistent within the scope of the operation performed, limited by the capabilities of the underlying data store. Bulk operations have no consistency guarantees. IDM does not expose any transactional semantics in the managed object access API.

For information on conditional header access through the REST API, refer to [Conditional Operations](../rest-api-reference/rest-structure.html#rest-conditional-operations).

## Managed object triggers

*Triggers* are user-definable functions that validate or modify object or property state.

### State triggers

Managed objects are resource-oriented. A set of triggers is defined to intercept the supported request methods on managed objects. Such triggers are intended to perform authorization, redact, or modify objects before the action is performed. The object being operated on is in scope for each trigger, meaning that the object is retrieved by the data store before the trigger is fired.

If retrieval of the object fails, the failure occurs before any trigger is called. Triggers are executed before any optimistic concurrency mechanisms are invoked. The reason for this is to prevent a potential attacker from getting information about an object (including its presence in the data store) before authorization is applied.

* onCreate

  Called upon a request to create a new object. Throwing an exception causes the create to fail.

* postCreate

  Called after the creation of a new object is complete.

* onRead

  Called upon a request to retrieve a whole object or portion of an object. Throwing an exception causes the object to not be included in the result. This method is also called when lists of objects are retrieved via requests to its container object; in this case, only the requested properties are included in the object. Allows for uniform access control for retrieval of objects, regardless of the method in which they were requested.

* onUpdate

  Called upon a request to store an object. The `oldObject` and `newObject` variables are in-scope for the trigger. The `oldObject` represents a complete object, as retrieved from the data store. The trigger can elect to change `newObject` properties. If, as a result of the trigger, the values of the `oldObject` and `newObject` are identical (that is, update is reverted), the update ends prematurely, but successfully. Throwing an exception causes the update to fail.

* postUpdate

  Called after an update request is complete.

* onDelete

  Called upon a request to delete an object. Throwing an exception causes the deletion to fail.

* postDelete

  Called after an object is deleted.

* onSync

  Called when a managed object is changed, and the change triggers an implicit synchronization operation. The implicit synchronization operation is triggered by calling the sync service, which attempts to go through all the configured managed-system [mappings](../synchronization-guide/mappings.html). The sync service returns either a response or an error. For both the response and the error, the script that is referenced by the `onSync` hook is called.

  You can use this hook to inject business logic when the sync service either fails or succeeds to synchronize all applicable mappings. For an example of how the `onSync` hook is used to revert partial successful synchronization operations, refer to [Synchronization Failure Compensation](../synchronization-guide/chap-implicit-live-sync.html#sync-failure-compensation).

### Object storage triggers

An object-scoped trigger applies to an entire object. Unless otherwise specified, the object itself is in scope for the trigger.

* onValidate

  Validates an object prior to its storage in the data store. If an exception is thrown, the validation fails and the object is not stored.

* onStore

  Called just prior to when an object is stored in the data store. Typically used to transform an object just prior to its storage (for example, encryption).

### Property storage triggers

A property-scoped trigger applies to a specific property within an object. Only the property itself is in scope for the trigger. No other properties in the object should be accessed during execution of the trigger. Unless otherwise specified, the order of execution of property-scoped triggers is intentionally left undefined.

* onValidate

  Validates a given property value after its retrieval from and prior to its storage in the data store. If an exception is thrown, the validation fails and the property is not stored.

- onRetrieve

  Called on all requests that return a single object: read, create, update, patch, and delete.

  `onRetrieve` is called on queries only if `executeOnRetrieve` is set to `true` in the query request parameters. If `executeOnRetrieve` is not passed, or if it is `false`, the query returns previously persisted values of the requested fields. This behavior avoids performance problems when executing the script on all results of a query.

- onStore

  Called before an object is stored in the data store. Typically used to transform a given property before its object is stored.

### Storage trigger sequences

Triggers are executed in the following order:

* Object Retrieval Sequence

  1. Retrieve the raw object from the data store

  2. The `executeOnRetrieve` boolean is used to check whether property values should be recalculated. The sequence continues if the boolean is set to `true`.

  3. Call object `onRetrieve` trigger

  4. Per-property within the object, call property `onRetrieve` trigger

* Object Storage Sequence

  1. Per-property within the object:

     * Call property `onValidate` trigger

     * Call object `onValidate` trigger

  2. Per-property trigger within the object:

     * Call property `onStore` trigger

     * Call object `onStore` trigger

     * Store the object with any resulting changes to the data store

## Managed object encryption

Sensitive object properties can be encrypted prior to storage, typically through the property `onStore` trigger. The trigger has access to configuration data, which can include arbitrary attributes that you define, such as a symmetric encryption key. Such attributes can be decrypted during retrieval from the data store through the property `onRetrieve` trigger.

## Managed object configuration

Configuration of managed objects is provided through an array of managed object configuration objects.

```json
{
  "objects": [ managed-object-config object, ... ]
}
```

* objects

  array of managed-object-config objects, required

  Specifies the objects that the managed object service manages.

### Managed-object-config object properties

Specifies the configuration of each managed object.

```json
{
  "name"      : string,
  "actions"   : script object,
  "onCreate"  : script object,
  "onDelete"  : script object,
  "onRead"    : script object,
  "onRetrieve": script object,
  "onStore"   : script object,
  "onSync"    : script object,
  "onUpdate"  : script object,
  "onValidate": script object,
  "postCreate": script object,
  "postDelete": script object,
  "postUpdate": script object,
  "schema"    : {
    "id"        : urn,
    "icon"      : string,
    "mat-icon"  : string,
    "order"     : [ list of properties],
    "properties": { property-configuration objects },
    "$schema"   : "http://json-schema.org/draft-03/schema",
    "title"     : "User",
    "viewable"  : true
  }
}
```

* name

  string, required

  The name of the managed object. Used to identify the managed object in URIs and identifiers.

* actions

  script object, optional

  A custom script that initiates an action on the managed object. For more information, refer to [Register custom scripted actions](../scripting-guide/custom-scripted-actions.html).

* onCreate

  script object, optional

  A script object to trigger when the creation of an object is being requested. The object to be created is provided in the root scope as an `object` property. The script can change the object. If an exception is thrown, the create aborts with an exception.

* onDelete

  script object, optional

  A script object to trigger when the deletion of an object is being requested. The object being deleted is provided in the root scope as an `object` property. If an exception is thrown, the deletion aborts with an exception.

* onRead

  script object, optional

  A script object to trigger when the read of an object is being requested. The object being read is provided in the root scope as an `object` property. The script can change the object. If an exception is thrown, the read aborts with an exception.

* onRetrieve

  script object, optional

  A script object to trigger when an object is retrieved from the repository. The object that was retrieved is provided in the root scope as an `object` property. The script can change the object. If an exception is thrown, then object retrieval fails.

* onStore

  script object, optional

  A script object to trigger when an object is about to be stored in the repository. The object to be stored is provided in the root scope as an `object` property. The script can change the object. If an exception is thrown, then object storage fails.

* onSync

  script object, optional

  A script object to trigger when a change to a managed object triggers an implicit synchronization operation. The script has access to the `syncResults` object, the `request` object, the state of the object before the change (`oldObject`) and the state of the object after the change (`newObject`). The script can change the object.

* onUpdate

  script object, optional

  A script object to trigger when an update to an object is requested. The old value of the object being updated is provided in the root scope as an `oldObject` property. The new value of the object being updated is provided in the root scope as a `newObject` property. The script can change the `newObject`. If an exception is thrown, the update aborts with an exception.

* onValidate

  script object, optional

  A script object to trigger when the object requires validation. The object to be validated is provided in the root scope as an `object` property. If an exception is thrown, the validation fails.

* postCreate

  script object, optional

  A script object to trigger after an object is created, but before any targets are synchronized.

* postDelete

  script object, optional

  A script object to trigger after a delete of an object is complete, but before any further synchronization. The value of the deleted object is provided in the root scope as an `oldObject` property.

* postUpdate

  script object, optional

  A script object to trigger after an update to an object is complete, but before any targets are synchronized. The value of the object before the update is provided in the root scope as an `oldObject` property. The value of the object after the update is provided in the root scope as a `newObject` property.

* schema

  json-schema object, optional

  The schema to use to validate the structure and content of the managed object, and how the object is displayed in the UI. The schema-object format is defined by the JSON Schema specification.

  The `schema` property includes the following additional elements:

  * icon

    string, optional

    The name of the Font Awesome icon to display for this object in the UI. Only applies to standalone IDM.

  * mat-icon

    string, optional

    []()The name of the [Material Design Icon](https://fonts.google.com/icons/) to display for this object in the UI. Only applies to IDM as part of the Ping Identity Platform.

  * id

    urn, optional

    The URN of the managed object, for example, `urn:jsonschema:org:forgerock:openidm:managed:api:Role`.

  * order

    list of properties, optional

    The order in which properties of this managed object are displayed in the UI.

  * properties

    list of property configuration objects, optional

    A list of property specifications. For more information, refer to [Property Configuration Properties](#managed-object-property-config-properties).

  * $schema

    url, optional

    Link to the JSON schema specification.

  * title

    string, optional

    The title of this managed object in the UI.

  * viewable

    boolean, optional

    Whether this object is visible in the UI.

### Property configuration properties

Each managed object property, identified by its `property-name`, can have the following configurable properties:

```json
"property-name" : {
  "comparison"      : string,
  "description"     : string,
  "encryption"      : property-encryption object,
  "isPersonal"      : boolean true/false,
  "isProtected"     : boolean true/false,
  "isVirtual"       : boolean true/false,
  "items"           : {
     "id"                  : urn,
     "properties"          : property-config object,
     "resourceCollection"  : property-config object,
     "reversePropertyName" : string,
     "reverseRelationship" : boolean true/false,
     "title"               : string,
     "type"                : string,
     "validate"            : boolean true/false,
  },
  "onRetrieve"      : script object,
  "onStore"         : script object,
  "onValidate"      : script object,
  "pattern"         : string,
  "policies"        : policy object,
  "required"        : boolean true/false,
  "returnByDefault" : boolean true/false,
  "scope"           : string,
  "searchable"      : boolean true/false,
  "secureHash"      : property-hash object,
  "title"           : string,
  "type"            : data type,
  "usageDescription": string,
  "userEditable"    : boolean true/false,
  "viewable"        : boolean true/false,
}
```

* description

  string, optional

  A brief description of the property.

* encryption

  property-encryption object, optional

  Specifies the configuration for encryption of the property in the repository. If omitted or null, the property isn't encrypted.

* isPersonal

  boolean, true/false

  Designed to highlight personally identifying information. By default, `isPersonal` is set to `true` for `userName` and `postalAddress`.

* isProtected

  boolean, true/false

  Specifies whether reauthentication is required if the value of this property changes.

* isVirtual

  boolean, true/false

  Specifies whether the property takes a static value or whether its value is calculated dynamically as the result of a script.

  The most recently calculated value of a virtual property is persisted by default. The persistence of virtual property values allows PingIDM to compare the new value of the property against the last calculated value to detect change events during synchronization.

  Virtual property values aren't persisted by default if you're using an explicit mapping.

* items

  property-configuration object, optional

  For `array` type properties, defines the elements in the array and can include the following sub-properties:

  * id

    urn, optional

    The URN of the property, for example, `urn:jsonschema:org:forgerock:openidm:managed:api:Role:members:items`.

  * properties

    property configuration object, optional

    A list of properties and their configuration that make up the item array. For example, for a `relationship` type property:

    ```json
    "properties" : {
        "_ref" : {
            "description" : "References a relationship from a managed object",
            "type" : "string"
        },
        "_refProperties" : {
            "description" : "Supports metadata within the relationship",
            ...
        }
    }
    ```

  * resourceCollection

    property configuration object, optional

    The collection of resources or objects on which this relationship is based. For example, `managed/user` objects.

  * reversePropertyName

    string, optional

    For `relationship` type properties, `reversePropertyName` specifies the corresponding property name in a reverse relationship. For example, a `roles` property could have a `reversePropertyName` of `members`.

  * reverseRelationship

    boolean, true or false.

    For `relationship` type properties, specifies whether the relationship exists in both directions.

  * title

    string, optional

    The title of array items displayed in the UI. For example, `Role Members Items`.

  * type

    string, optional

    The array type, for example `relationship`.

  * validate

    boolean, true/false

    For reverse relationships, `validate` specifies whether the relationship should be validated.

* onRetrieve

  script object, optional

  A script object to trigger after a property is retrieved from the repository. That property may be one of two related variables: `property` and `propertyName`. The property that was retrieved is provided in the root scope as the `propertyName` variable. Its value is provided as the `property` variable. If an exception is thrown, then object retrieval fails.

  |   |                                                                                    |
  | - | ---------------------------------------------------------------------------------- |
  |   | For virtual properties, only run `onRetrieve` scripts for top-level object fields. |

* onStore

  script object, optional

  A script object to trigger when a property is about to be stored in the repository. That property may be one of two related variables: `property` and `propertyName`. The property that was retrieved is provided in the root scope as the `propertyName` variable. Its value is provided as the `property` variable. If an exception is thrown, then object storage fails.

* onValidate

  script object, optional

  A script object to trigger when the property requires validation. The value of the property to be validated is provided in the root scope as the `property` property. If an exception is thrown, validation fails.

* comparison

  string, optional

  Specifies whether to use [array ordered or unordered comparison](../synchronization-guide/chap-implicit-live-sync.html#array-comparison) for synchronization. The value can be either `"ordered"` or `"unordered"`. The `"ordered"` value indicates that the array order matters with regard to detecting changes for sync. The `"unordered"` value indicates that the array order does not matter with regard to detecting changes for sync.

  Relationship and virtual property array fields default to unordered comparisons. All other fields default to ordered comparisons.

  If you are using [explicit mappings with a DS repository](explicit-generic-mapping-ds.html#explicit-mappings-ds), you can't use ordered array comparisons.

* pattern

  string, optional

  Any specific pattern to which the value of the property must adhere. For example, a property whose value is a date could require a specific date format. Patterns specified here must follow regular expression syntax.

* policies

  policy object, optional

  Any policy validation that must be applied to the property.

* required

  boolean, true/false

  Specifies whether the property must be supplied when this type of object is created.

* returnByDefault

  boolean, true/false

  For virtual properties, `returnByDefault` specifies whether the property will be returned in the results of a query on this object type if it's not explicitly requested. Virtual attributes aren't returned by default.

* scope

  string, optional

  Specifies whether the property should be filtered from HTTP or external calls. The value can be either `"public"` or `"private"`. The `"private"` value indicates that the property should be filtered. The `"public"` value indicates no filtering. If no value is set, it's assumed the property is public and not filtered.

  |   |                                                                                                                         |
  | - | ----------------------------------------------------------------------------------------------------------------------- |
  |   | Ensure you use the scope `"private"` value to remove *only* sensitive fields, such as passwords, from the API response. |

* searchable

  boolean, true/false

  Specifies whether `searchable` can be used in a search query on the managed object. A searchable property is visible in the end-user UI. This property is `false` by default.

  |   |                                                                                                                           |
  | - | ------------------------------------------------------------------------------------------------------------------------- |
  |   | The end-user UI is not bundled with PingIDM. Learn more in [Install the end-user UI](../setup-guide/idm-enduser-ui.html). |

* secureHash

  property-hash object, optional

  Specifies the configuration for hashing the property value in the repository. If omitted or null, the property is not hashed.

* title

  string, required

  A human-readable string, used to display the property in the UI.

* type

  data type, required

  The data type for the property value, which can be a string, array, boolean, number, object, or resource collection.

* usageDescription

  string, optional

  Designed to help end users understand the sensitivity of a property, such as a telephone number.

* userEditable

  boolean, true/false

  Specifies whether users can edit the property value in the UI. This property applies in the context of the end-user UI where users are able to edit certain properties of their own accounts. The `userEditable` property is `false` by default.

* viewable

  boolean, true/false

  Specifies whether this property is viewable in the object's profile in the UI. The `viewable` property is `true` by default.

### Script Object Properties

```json
{
  "type"  : "text/javascript",
  "source": string
}
```

* type

  string, required

  IDM supports `"text/javascript"` and `"groovy"`.

* source, file

  string, required (only one, source or file is required)

  Specifies the source code of the script to be executed (if the keyword is "source"), or a pointer to the file that contains the script (if the keyword is "file").

### Property Encryption Object

```json
{
  "cipher": string,
  "key"   : string
}
```

* cipher

  string, optional

  The cipher transformation used to encrypt the property. If omitted or null, the default cipher of `"AES/CBC/PKCS5Padding"` is used.

* key

  string, required

  The alias of the key in the IDM cryptography service keystore used to encrypt the property.

### Property Hash Object

```json
{
    "algorithm" : string,
    "type" : string
}
```

* algorithm

  string, required

  The algorithm that should be used to hash the value.

  For a list of supported hash algorithms, refer to [Salted Hash Algorithms](../security-guide/encoding-attribute-values.html#encoding-salted-hash).

* type

  string, optional

  The type of hashing. Currently only salted hash is supported. If this property is omitted or null, the default `"salted-hash"` is used.

## Custom managed objects

Managed objects are inherently fully user definable and customizable. Like all objects, managed objects can maintain relationships to each other in the form of links. Managed objects are intended for use as targets and sources for synchronization operations to represent domain objects, and to build up virtual identities. The name *managed objects* comes from the intention that IDM stores and manages these objects, as opposed to system objects that are present in external systems.

IDM can synchronize and map directly between external systems (system objects), without storing intermediate managed objects. Managed objects are appropriate, however, as a way to cache the data—for example, when mapping to multiple target systems, or when decoupling the availability of systems—to more fully report and audit on all object changes during reconciliation, and to build up views that are different from the original source, such as transformed and combined or virtual views. Managed objects can also be allowed to act as an authoritative source if no other appropriate source is available.

Other object types exist for other settings that should be available to a script, such as configuration or look-up tables that do not need audit logging.

### Set up a managed object type

To set up a managed object, you define the object in your project's managed object configuration *(tooltip: You can edit the managed object configuration over REST at the config/managed endpoint, or directly in the conf/managed.json file.)*. This simple example adds a `foobar` object declaration after the `user` object type:

```json
{
    "objects": [
        {
            "name": "user"
        },
        {
            "name": "foobar"
        }
    ]
}
```

### Manipulate managed objects declaratively

By mapping an object to another object, either an external system object or another internal managed object, you automatically tie the object life cycle and property settings to the other object. For more information, refer to [Resource mapping](../synchronization-guide/mappings.html).

### Manipulate managed objects programmatically

You can address managed objects as resources using URLs or URIs with the `managed/` prefix. This works whether you address the managed object internally as a script running in IDM or externally through the REST interface.

You can use all resource API functions in script objects for create, read, update, delete operations, and also for arbitrary queries on the object set, but not currently for arbitrary actions. For more information, refer to [Scripting](../scripting-guide/preface.html).

IDM supports concurrency through a multi version concurrency control (MVCC) mechanism. Each time an object changes, IDM assigns it a new revision.

Objects can be arbitrarily complex as long as they use supported types, such as maps, lists, numbers, strings, and booleans as defined in [JSON](https://www.json.org).

#### Create objects

The following script example creates an object type.

```javascript
openidm.create("managed/foobar", "myidentifier", mymap)
```

#### Update objects

The following script example updates an object type.

```javascript
var expectedRev = origMap._rev
openidm.update("managed/foobar/myidentifier", expectedRev, mymap)
```

The MVCC mechanism requires that `expectedRev` be set to the expected revision of the object to update. You obtain the revision from the object's `_rev` property. If something else changes the object concurrently, IDM rejects the update, and you must either retry or inspect the concurrent modification.

#### Patch objects

You can partially update a managed or system object using the patch method, which changes only the specified properties of the object.

The following script example updates an object type.

```javascript
openidm.patch("managed/foobar/myidentifier", rev, value)
```

The patch method supports a revision of `"null"`, which effectively disables the MVCC mechanism, that is, changes are applied, regardless of revision. In the REST interface, this matches the `If-Match: "*"` condition supported by patch. Alternatively, you can omit the "If-Match: \*" header.

For managed objects, the API supports patch by query, so the caller does not need to know the identifier of the object to change.

```
curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '[
  {
    "operation": "replace",
    "field": "/password",
    "value": "Passw0rd"
  }
]' \
"http://localhost:8080/openidm/managed/user?_action=patch&_queryFilter=userName+eq+'DDOE'"
```

#### Delete objects

The following script example deletes an object type.

```javascript
var expectedRev = origMap._rev
openidm.delete("managed/foobar/myidentifier", expectedRev)
```

The MVCC mechanism requires that `expectedRev` be set to the expected revision of the object to update. You obtain the revision from the object's `_rev` property. If something else changes the object concurrently, IDM rejects deletion, and you must either retry or inspect the concurrent modification.

#### Read objects

The following script example reads an object type.

```javascript
val = openidm.read("managed/foobar/myidentifier")
```

#### Query object sets

You can query managed objects using common query filter syntax. The following script example queries managed user objects whose `userName` is smith.

```javascript
var qry = {
    "_queryFilter" : "/userName eq \"smith\""
};
val = openidm.query("managed/user", qry);
```

For more information, refer to [Define and call data queries](queries.html).

## Access managed objects through the REST API

IDM exposes all managed object functionality through the REST API unless you configure a policy to prevent such access. In addition to the common REST functionality of create, read, update, delete, patch, and query, the REST API also supports patch by query. For more information, refer to the [REST API reference](../rest-api-reference/preface.html).

IDM requires authentication to access the REST API. The authentication configuration is specified in your project's `conf/authentication.json` file. The default authorization filter script is `openidm/bin/defaults/script/router-authz.js`. For more information, refer to [Authorization and roles](../auth-guide/authorization-and-roles.html).
