---
title: Resource mapping
description: A synchronization mapping specifies a relationship between objects and their attributes in two data stores. The following example shows a typical attribute mapping, between objects in an external LDAP directory and an IDM managed user data store:
component: pingidm
version: 8.1
page_id: pingidm:synchronization-guide:mappings
canonical_url: https://docs.pingidentity.com/pingidm/8.1/synchronization-guide/mappings.html
keywords: ["Synchronization", "Resource", "Mappiings"]
section_ids:
  sync-mapping-paging: Paging synchronization mapping results
  specifying-default-fields: Specifying default fields
  when_to_specify: When to specify
  when_not_to_specify: When not to specify
---

# Resource mapping

A synchronization mapping specifies a relationship between objects and their attributes in two data stores. The following example shows a typical attribute mapping, between objects in an external LDAP directory and an IDM managed user data store:

```
"source": "lastName",
"target": "sn"
```

In this case, the `lastName` source attribute is mapped to the `sn` (surname) attribute in the target LDAP directory.

The core synchronization configuration is defined in the mapping configuration *(tooltip: You can manage the mapping configuration over REST at the config/sync endpoint, directly in the conf/sync.json file, or in individual conf/mapping-\<mappingName>.json files.)*.

You can define a single file with all your mappings (`conf/sync.json`), or a separate file per mapping. Individual mapping files are named `mapping-mappingName.json`; for example, `mapping-managedUser_systemCsvfileAccounts.json`. Individual mapping files can be useful if your deployment includes many mappings that are difficult to manage in a single file. You can also use a combination of individual mapping files and a monolithic `sync.json` file, particularly if you are adding mappings to an existing deployment.

If you use a single `sync.json` file, mappings are processed in the order in which they appear within that file. If you use multiple mapping files, mappings are processed according to the `syncAfter` property in the mapping. The following example indicates that this particular mapping must be processed after the `managedUser_systemCsvfileAccount` mapping:

```json
  "source" : "managed/user",
  "target" : "system/csvfile/account",
  "syncAfter" : [ "managedUser_systemCsvfileAccount" ],
```

If you use a combination of `sync.json` and individual mapping files, the synchronization engine processes the mappings in `sync.json` first (in order), and then any mappings specified in the individual mapping files, according to the `syncAfter` property in each mapping.

For a list of *all* mappings, use the following request:

```
curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/sync/mappings?_queryFilter=true"
```

This call returns the mappings in the order in which they will be processed.

|   |                                                                                                                                                        |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | The admin UI only shows the mappings configured in the `sync.json` file. Don't use the admin UI to add or change mappings in individual mapping files. |

Mappings are always defined from a *source* resource to a *target* resource. To configure bidirectional synchronization, you must define two mappings. For example, to configure bidirectional synchronization between an LDAP server and an IDM repository, you would define the following two mappings:

* LDAP Server > IDM Repository

* IDM Repository > LDAP Server

Bidirectional mappings can include a `links` property that lets you reuse the links established between objects, for both mappings. For more information, refer to [Reuse Links Between Mappings](reusing-links.html).

You can update a mapping while the server is running. To avoid inconsistencies between data stores, don't update a mapping while a reconciliation is in progress *for that mapping*.

## Paging synchronization mapping results

With many synchronization mappings, use paging to retrieve the results in manageable chunks to avoid overwhelming the client. The `sync/mappings` endpoint supports paging with the `_pageSize` parameter and either cookies (`_pagedResultsCookie`) or offsets (`_pagedResultsOffset`).

Example: Cookie-based paging

1. To get the first page of results, with a page size of 2, send a request like this:

   ```
   curl \
   --header "X-OpenIDM-Username: openidm-admin" \
   --header "X-OpenIDM-Password: openidm-admin" \
   --header "Accept-API-Version: resource=1.0" \
   --request GET \
   "http://localhost:8080/openidm/sync/mappings?_queryFilter=/source+eq+'source1'&_pageSize=2"
   ```

   The response includes a `pagedResultsCookie` that you can use to retrieve the next page:

   ```json
   {
     "result": [
       {
         "_id": "mapping1",
         "source": "source1",
         "target": "target1",
         "name": "mapping1",
         "sourceRouteReady": false,
         "targetRouteReady": false
       },
       {
         "_id": "mapping4",
         "source": "source1",
         "target": "target0",
         "name": "mapping4",
         "sourceRouteReady": false,
         "targetRouteReady": false
       }
     ],
     "resultCount": 2,
     "pagedResultsCookie": "mapping7",
     "totalPagedResultsPolicy": "EXACT",
     "totalPagedResults": 2,
     "remainingPagedResults": -1
   }
   ```

2. To get the next page of results, use the `_pagedResultsCookie` from the previous response:

   ```
   curl \
   --header "X-OpenIDM-Username: openidm-admin" \
   --header "X-OpenIDM-Password: openidm-admin" \
   --header "Accept-API-Version: resource=1.0" \
   --request GET \
   "http://localhost:8080/openidm/sync/mappings?_queryFilter=/source+eq+'source1'&_pageSize=2&_pagedResultsCookie=mapping7"
   {
     "result": [
       {
         "_id": "mapping7",
         "source": "source1",
         "target": "target3",
         "name": "mapping7",
         "sourceRouteReady": false,
         "targetRouteReady": false
       }
     ],
     "resultCount": 1,
     "pagedResultsCookie": null,
     "totalPagedResultsPolicy": "EXACT",
     "totalPagedResults": 1,
     "remainingPagedResults": -1
   }
   ```

Example: Offset-based paging

1. To get the first page of results, with a page size of 2 and an offset of 0:

   ```
   curl \
   --header "X-OpenIDM-Username: openidm-admin" \
   --header "X-OpenIDM-Password: openidm-admin" \
   --header "Accept-API-Version: resource=1.0" \
   --request GET \
   "http://localhost:8080/openidm/sync/mappings?_queryFilter=/source+eq+'source1'&_pageSize=2&_pagedResultsOffset=0"
   {
     "result": [
       {
         "_id": "mapping1",
         "source": "source1",
         "target": "target1",
         "name": "mapping1",
         "sourceRouteReady": false,
         "targetRouteReady": false
       },
       {
         "_id": "mapping4",
         "source": "source1",
         "target": "target0",
         "name": "mapping4",
         "sourceRouteReady": false,
         "targetRouteReady": false
       }
     ],
     "resultCount": 2,
     "pagedResultsCookie": "mapping7",
     "totalPagedResultsPolicy": "EXACT",
     "totalPagedResults": 2,
     "remainingPagedResults": -1
   }
   ```

2. To get the second page of results, set the `_pagedResultsOffset` to the number of results already retrieved (in this case, 2):

   ```
   curl \
   --header "X-OpenIDM-Username: openidm-admin" \
   --header "X-OpenIDM-Password: openidm-admin" \
   --header "Accept-API-Version: resource=1.0" \
   --request GET \
   "http://localhost:8080/openidm/sync/mappings?_queryFilter=/source+eq+'source1'&_pageSize=2&_pagedResultsOffset=2"
   {
     "result": [
       {
         "_id": "mapping7",
         "source": "source1",
         "target": "target3",
         "name": "mapping7",
         "sourceRouteReady": false,
         "targetRouteReady": false
       }
     ],
     "resultCount": 1,
     "pagedResultsCookie": null,
     "totalPagedResultsPolicy": "EXACT",
     "totalPagedResults": 1,
     "remainingPagedResults": -1
   }
   ```

## Specifying default fields

The `defaultSourceFields` and `defaultTargetFields` optional fields allow more control over which attributes are fetched during read operations during synchronization and reconciliation.

### When to specify

1. During synchronization reads: If IDM needs to read a source or target object while executing a synchronization operation because the object isn't already loaded in memory for that specific task, it will include the attributes listed in `defaultSourceFields` or `defaultTargetFields` in the read request.

   |   |                                                                                                                                                                                                                                                                                                                                                                                              |
   | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   |   | This is an efficiency feature. If an object was already loaded into memory earlier in the same overall transaction (for instance, during reconciliation) before the sync operation needs it, IDM won't automatically reread the object to add the attributes specified in these default fields. The fields are primarily used when a *new* read is initiated during the sync process itself. |

2. During reconciliation queries: If you *don't* specify an explicit list of attributes in the `sourceQuery` or `targetQuery` configuration, IDM will fall back to using `defaultSourceFields` or `defaultTargetFields` respectively. This can be more helpful than the older behavior, where some default queries might only retrieve the object's `_id`.

If you define a list of attributes within the `sourceQuery` or `targetQuery` settings, that specific list always takes precedence. The `defaultSourceFields` and `defaultTargetFields` only act as defaults when no specific list is provided in those contexts.

### When not to specify

There are a couple of situations where these fields won't dictate the attributes loaded for a source object during a synchronization operation:

* Implicit synchronization: In implicit sync scenarios, the source object that triggered the event is usually already loaded, so IDM doesn't perform a new read using `defaultSourceFields`.

* Object already loaded using explicit query: If the source or target object was already fully loaded during reconciliation because specific attributes were requested using the higher-priority `sourceQuery` or `targetQuery` settings, then `defaultSourceFields` or `defaultTargetFields` won't cause another read.
