> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withampersand.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Object and field mapping

Ampersand supports object mapping and field mapping. This allows you to either pre-define a set of mappings, or prompt your users to define their own mappings via Ampersand's UI components.

## Predefined mapping

### Object mapping

You can map an object from a provider API to a label of your choice. This can help you with any naming/semantic conventions that you need, or even help you build a unified API across different API providers.

For example, if you map the `account` object from **Salesforce** and the `companies` object from **HubSpot** to a unified label like `company`, your read action results will be delivered under the object name of `company`. The original object name will still be available in the response's `rawObjectName` key.

If you wish to write data to `company`, you can [inherit the mapping](/write-actions#sharing-mappings-with-read-actions) from the read action.

Here's an example of a Salesforce integration that maps the `account` object to `company`:

```YAML theme={null}
  - name: salesforce-integration
    displayName: My Salesforce integration
    provider: salesforce
    read:
      objects:
        - objectName: account
          mapToName: company
          # Additional configuration
    write:
      objects:
        - objectName: account
          inheritMapping: true
```

### Field mapping

You can map individual fields to labels of your choosing. This can help you enforce naming conventions, or standardize field names across API providers.

For example, you could map a `mobilephone` field to `phone`. Read results will deliver the field under the `phone` key, and when you make a call to the Write API, you can use `phone` to update the original `mobilePhone` field if the write action inherits the mapping.

```YAML theme={null}
  - name: hubspot-integration
    displayName: My HubSpot integration
    provider: hubspot
    module: crm
    read:
      objects:
        - objectName: contacts
          requiredFields:
            - fieldName: mobilephone
              mapToName: phone
    write:
      objects:
        - objectName: contacts
          inheritMapping: true
```

## User-defined mapping

User-defined mappings allow your end users (or consumers, in [Ampersand terminology](/terminology)) to define mappings. Currently, only user-defined field mappings are supported, not object mappings yet.

### Field mapping

Your end users may have a custom field to add notes to an Account object. You can ask your consumers to define this mapping at the time of installation, and receive data across different consumers under a single unified field like `notes`.

**Example**:

* You define a `notes` field in your integration.
* **User A** stores notes in `field_a`, while **User B** uses `field_b`.
* The UI library will ask each user to identify which field to map, and Ampersand delivers them under `notes`, accommodating custom fields unique to each consumer.
* You can write back to each user's specific fields by writing to the `notes` field, if you inherit the mapping.

Field mappings can either be inside `requiredFields` or `optionalFields`, you'll specify:

* **mapToName:** when Ampersand delivers the data from this field to you, this is the name that will be used to identify the field.
* **mapToDisplayName:** the text to display to the user in the UI component when asking them to select a field.
* **default** (optional): the default field, you should only use standard fields as defaults.
* **prompt** (optional): additional context that you want to show your user in the UI Component about this field, in a tooltip.

```YAML theme={null}
  - name: salesforce-integration
    provider: salesforce
    read:
      objects:
        - objectName: account
          optionalFields:
            # There is no fieldName for user-mapped fields
            - mapToName: notes
              mapToDisplayName: Account notes
              prompt: Please select the field that contains notes for this account
          # Additional configuration
    write:
      objects:
        - objectName: account
          inheritMapping: true
```

If you have an optional field mapping, and the user chose not to map the field (because they do not have a field that corresponds to notes), you can still make Write API calls with `notes` populated, and Ampersand will automatically strip it from the request before writing to the provider API to prevent errors.

### Dynamic field mappings

With regular field mappings, you can define a set of fields that all your users need to map. Sometimes, you may want different users to map different sets of fields.

> For example: SampleApp is using Ampersand to integrate with their customer's HubSpot.
> SampleApp needs to ask the customer to map their SampleApp fields to their HubSpot fields, and different customers can have different sets of fields in SampleApp.

To achieve this, you can pass in the mapping configuration in the `fieldMapping` property of the `InstallIntegration` component:

```TYPESCRIPT theme={null}
function MyComponent() {
  const mapping = {
    // You'd likely construct this dynamically based on your business logic
    // of determining which fields the user need to map.
    // The example is static for simplicity.
    contacts: [
      {
        mapToName: 'source',
        // Both mapToDisplayName and prompt are optional.
        mapToDisplayName: 'Source',
        prompt: 'Which field do you use to track the source of a contact?',
      },
      {
        mapToName: 'priority',
        mapToDisplayName: 'Priority',
        prompt: 'Which field do you use to track the priority of a contact?',
      }
    ],
    // Field mapping for the companies object
    companies: [
      {
        mapToName: 'AccountID',
        mapToDisplayName: 'Sales Territory',
        prompt: 'Which field do you use to track the sales territory of a company?',
      }
    ]
  }
  return (<InstallIntegration
    integration = "myHubSpotIntegration"
    consumerRef = {userId}
    consumerName = {userFullName}
    groupRef = {teamId}
    groupName = {teamName}
    fieldMapping = {mapping}
  />);
}

```

<Tip>Dynamic mappings are considered optional for a user to set, i.e, your users can install the integration without explicitly mapping a field. </Tip>

Note you can also use this configuration in tandem with static field mappings (the ones defined in `amp.yaml`):

```YAML theme={null}
specVersion: 1.0.0
integrations:
  - name: myHubSpotIntegration
    provider: hubspot
    module: crm
    read:
      objects:
        # contacts also has a static field mapping
        - objectName: contacts
          optionalFields:
            - mapToName: pronoun
              mapToDisplayName: Pronoun
              prompt: We will use this word when addressing this person in emails we send out.
          ...
        - objectName: companies
          ...
```

When the webhook message is delivered, both statically mapped fields (defined in `amp.yaml`) and dynamically mapped fields (defined in the UI component) will be present in `result.mappedFields`

```JSON theme={null}
{
 ...
 "objectName": "Contact",
 "result": [
  {
    "fields": {
      ... // non-mapped fields
    },
    "mappedFields": {
      "pronoun": "she", // statically mapping
      "source": "LinkedIn", // dynamically mapped
      "priority": "high", // dynamically mapped
    },
    "raw": {
      ...
    }
  }
 ]
}
```

### Mapping values

Ampersand platform also offers the flexibility of mapping values of fields from your app to a provider like HubSpot.

These might be for fields that are mapped either in a user-defined fashion or have a pre-defined mapping defined.

Lets take an example:

* SampleApp is using Ampersand to integrate with their customer's HubSpot.
* SampleApp needs to ask the customer to map their SampleApp fields to their HubSpot fields.
* For a certain field, such as `Priority`,
  SampleApp has the values  `Very High`, `High`, `Medium`, `Low` while HubSpot has the values
  `P1`, `P2`, `P3`, and `P4`. SampleApp would like the user to map the correlation between the SampleApp values and HubSpot values.

To achieve this you can define the SampleApp side of the values that need to be mapped in `InstallIntegration` component like below:

```TYPESCRIPT theme={null}
const mapping = {
    deals: [
      {
        mapToName: 'priority',
        mapToDisplayName: 'Priority',
        prompt: 'Which field do you use to track the priority of a deal?',
        // Mapping values for a field that's mapped by a user
        mappedValues: [
          {
            mappedValue: 'veryhigh',
            mappedDisplayValue: 'Very High'
          },
          {
            mappedValue: 'high',
            mappedDisplayValue: 'High'
          },{
            mappedValue: 'medium',
            mappedDisplayValue: 'Medium'
          },{
            mappedValue: 'low',
            mappedDisplayValue: 'Low'
          },
        ]
      },
      {
        fieldName: 'stage',
        /**
        ** Here `stage` only needs the values to be mapped.
        ** The users will not need to map the field.
        **/
        mappedValues: [
          {
            mappedValue: 'open',
            mappedDisplayValue: 'Open'
          },{
            mappedValue: 'closedWon',
            mappedDisplayValue: 'Closed Won'
          },{
            mappedValue: 'closedLost',
            mappedDisplayValue: 'Closed Lost'
          },
        ],
      },
    ],
    companies: [
      {
        mapToName: 'territory', // No mapping of values on this field
        mapToDisplayName: 'Sales Territory',
        prompt: 'Which field do you use to track the sales territory of a company?',
      }
    ]
  }
...
return (<InstallIntegration
   integration="myHubSpotIntegration"
   fieldMapping={mapping}
   groupRef={groupRef}
   ...
/>);

```

This will ensure that your users see a mapping UI where they can select the values from the HubSpot side to be mapped to the app side values defined here.

<Tip> We only allow one-to-one mapping of values </Tip>

## Nested field mapping

Some provider APIs may have nested structures. Ampersand supports mapping from and to nested fields using [JSONPath's](https://www.rfc-editor.org/rfc/rfc9535.html) bracket notation, allowing you to extract values from nested objects or write values into nested structures.

Nested field paths use the format `$['parentField']['childField']`. Bracket notation ensures that field names containing dots, spaces, or other special characters are correctly parsed. For example, `$['parentField']['childField$With.Special"Characters"']` is valid.

Value mappings also support bracket notation.

<Note>
  When you call the [Get Object Metadata](/reference/objects-&-fields/get-object-metadata-via-connection) API, some providers may return nested fields such as `$['parentField']['childField']`. These field names can be used directly in your `amp.yaml` configuration.
</Note>

### Reading nested data

When a provider API returns nested data, you can use field mappings to extract nested values into mapped fields. Here is an example:

**Provider returns:**

```JSON theme={null}
{
  "userInfo": {
    "email": "john@example.com",
    "name": "John Doe"
  },
  "status": "active"
}
```

**With this pre-defined field mapping in `amp.yaml`:**

```YAML theme={null}
    read:
      objects:
        - objectName: contacts
          requiredFields:
            - mapToName: contactEmail
              fieldName: $['userInfo']['email']
            - mapToName: contactName
              fieldName: $['userInfo']['name']
            - mapToName: $['moreInfo']['currentStatus']
              fieldName: status
```

**Your destination receives:**

```JSON theme={null}
{
  "mappedFields": {
    "contactEmail": "john@example.com",
    "contactName": "John Doe",
    "moreInfo": {
      "currentStatus": "active"
    }
  }
}
```

### Writing nested data

The same mappings will be applied in reverse when writing to a provider using the [Write API](/write-actions).

**Your app sends:**

```JSON theme={null}
{
  "contactEmail": "john@example.com",
  "contactName": "John Doe",
  "moreInfo": {
    "currentStatus": "deleted"
  }
}
```

**Provider receives:**

```JSON theme={null}
{
  "userInfo": {
    "email": "john@example.com",
    "name": "John Doe"
  },
  "status": "deleted"
}
```

## Full example

To see a full example of how to define object and field mappings, check out the [unified CRM example](https://github.com/amp-labs/samples/blob/main/unifiedCRM/amp.yaml) in our samples repository.
