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

# Set Owner Field Mappings

> Choose which CRM fields hold the account owner, the CS owner and a connector's owner

Sets which property of one connected CRM holds each owner, and which side may change it. Send
only the owners you want to change; an owner you leave out keeps what is saved. Admin only.

* `company`: the account owner. Attack competitor alerts mention it.
* `contact`: a connector's owner.
* `company_cs`: the CS owner of a company. Defense competitor alerts mention it. It has no
  default field on any CRM, and it is only ever read from the CRM.

Every field is checked against the CRM's live schema: it must exist, and it must hold a CRM user
(unless `allowAnyField`). For `company` and `contact`, it must also be writable when the
direction lets Clustr write to it. A changed field starts a sync, so owners reflect the new
field without waiting for the nightly one (`resync` in the response). Competitor alerts read the
mapped fields live from the CRM when they are sent, so they use a new field straight away.

## CS owner from an associated object

On HubSpot, the CS owner can live on another record than the company: a custom object
associated with it, such as a "communities" object. Set `object` on `company_cs` to that
object's type, and `field` to its owner property (`hubspot_owner_id` when you leave it empty).
When a company has several associated records with an owner, the oldest record's owner is
used. Clustr reads this owner on every sync and never writes it, so the direction is saved as
`crm_owns`.

```json theme={null}
{"company_cs": {"object": "p_communities", "field": "hubspot_owner_id"}}
```

Reading a custom object needs the HubSpot connection to include the custom object scopes.

## Errors

| Status | Code | When |
| - | - | - |
| 400 | | A field is not on the CRM, does not hold a user, is read-only for a direction that writes, or a direction is invalid. Also when `object` is sent for another owner than `company_cs` or another CRM than HubSpot |
| 403 | `ADMIN_REQUIRED` | The caller is not a workspace admin |
| 404 | `CRM_NOT_CONNECTED` | That CRM is not connected for this workspace |

```bash cURL theme={null}
curl -X PUT "https://api.clustr-ai.com/api/public/crm/owner-field-mappings?provider=hubspot" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"company_cs": {"field": "customer_success_manager", "direction": "crm_owns"}}'
```

```python Python theme={null}
import requests

requests.put(
    "https://api.clustr-ai.com/api/public/crm/owner-field-mappings",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    params={"provider": "hubspot"},
    json={"company_cs": {"field": "customer_success_manager", "direction": "crm_owns"}},
)
```

```javascript JavaScript theme={null}
await fetch("https://api.clustr-ai.com/api/public/crm/owner-field-mappings?provider=hubspot", {
  method: "PUT",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ company_cs: { field: "customer_success_manager", direction: "crm_owns" } }),
});
```

```json 200 theme={null}
{
  "success": true,
  "data": {
    "provider": "hubspot",
    "company": { "field": "hubspot_owner_id", "direction": "both", "isDefault": true, "defaultField": "hubspot_owner_id" },
    "contact": { "field": "hubspot_owner_id", "direction": "both", "isDefault": true, "defaultField": "hubspot_owner_id" },
    "company_cs": { "field": "customer_success_manager", "direction": "crm_owns", "isDefault": false, "defaultField": "" },
    "resync": "triggered"
  }
}
```

```json 403 theme={null}
{
  "success": false,
  "error": {
    "message": "Only workspace admins can change CRM settings",
    "code": "ADMIN_REQUIRED"
  }
}
```


## OpenAPI

````yaml PUT /crm/owner-field-mappings
openapi: 3.1.0
info:
  title: Clustr Public API
  description: >
    Programmatic access to your Clustr network: import connectors, search warm
    intros (opportunities), and manage target accounts.


    ## Authentication

    All endpoints require a Bearer token (API key) in the `Authorization`
    header.


    ```

    Authorization: Bearer <your_api_key>

    ```


    API keys can be created and managed from the [API settings
    page](https://app.clustr-ai.com/api).
  version: '1.0'
  contact:
    name: Clustr Support
    url: https://clustr-ai.com
servers:
  - url: https://api.clustr-ai.com/api/public
    description: Production
security:
  - BearerAuth: []
paths:
  /crm/owner-field-mappings:
    parameters:
      - name: provider
        in: query
        required: true
        description: >-
          The CRM to read or change: `hubspot`, `salesforce` or `attio`. That
          CRM must be connected to your workspace.
        schema:
          type: string
          enum:
            - hubspot
            - salesforce
            - attio
        example: hubspot
    put:
      tags:
        - Owners
      summary: Set Owner Field Mappings
      description: >
        Chooses which property of one connected CRM holds each owner, and which
        side may change

        it. Send only the owners you want to change: an owner you leave out
        keeps its saved

        mapping. Admin only.


        Each field is checked against your CRM's live schema. It must exist on
        the CRM and hold

        a CRM user, unless you set `allowAnyField`. For `company` and `contact`,
        the field must

        also be writable when the direction lets Clustr write to it.


        When a field changes, Clustr starts a CRM sync so your owners reflect
        the new field

        right away, and `resync` in the response reports how that went.
        Competitor alerts read

        the mapped fields live from your CRM when they are sent, so they use a
        new field

        straight away.
      operationId: setOwnerFieldMappings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                company:
                  allOf:
                    - $ref: '#/components/schemas/OwnerFieldMappingInput'
                  description: The account owner, on a CRM company.
                contact:
                  allOf:
                    - $ref: '#/components/schemas/OwnerFieldMappingInput'
                  description: A connector's owner, on a CRM contact.
                company_cs:
                  allOf:
                    - $ref: '#/components/schemas/OwnerFieldMappingInput'
                  description: >-
                    The CS owner, on a CRM company. It is always read from your
                    CRM, so its direction is `crm_owns` or `off`: `both` and an
                    omitted direction are saved as `crm_owns`, and `clustr_owns`
                    answers 400. Send `field: ""` to unmap it.
                allowAnyField:
                  type: boolean
                  default: false
                  description: >-
                    Accept a field that holds something other than a CRM user.
                    The field must still exist on the CRM.
                  example: false
            examples:
              cs_owner:
                summary: Map the CS owner to a custom HubSpot property
                value:
                  company_cs:
                    field: customer_success_manager
                    direction: crm_owns
              account_owner:
                summary: Let Clustr own the account owner on Salesforce
                value:
                  company:
                    field: OwnerId
                    direction: clustr_owns
      responses:
        '200':
          description: The saved owner field mappings
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                  - data
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    allOf:
                      - $ref: '#/components/schemas/OwnerFieldMappings'
                      - type: object
                        properties:
                          resync:
                            type: string
                            enum:
                              - triggered
                              - already_running
                              - unchanged
                              - skipped
                            description: >-
                              What happened to the CRM sync after the save.
                              `triggered`: a sync started to read owners from
                              the new field. `already_running`: a sync was
                              already in progress. `unchanged`: every field
                              stayed the same, so the saved owners are already
                              current. `skipped`: the next scheduled sync reads
                              the new field.
                            example: triggered
              example:
                success: true
                data:
                  provider: hubspot
                  company:
                    field: hubspot_owner_id
                    direction: both
                    isDefault: true
                    defaultField: hubspot_owner_id
                  contact:
                    field: hubspot_owner_id
                    direction: both
                    isDefault: true
                    defaultField: hubspot_owner_id
                  company_cs:
                    field: customer_success_manager
                    direction: crm_owns
                    isDefault: false
                    defaultField: ''
                  resync: triggered
        '400':
          description: >-
            `provider` is invalid, a field is missing from the CRM, holds
            something other than a CRM user, or is read-only for a direction
            that writes to it, or a direction is invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  message: 'company_cs: cs_owner__c is not a field on this CRM'
                  code: BAD_REQUEST
        '401':
          description: Invalid or missing API key
        '403':
          description: The caller is not a workspace admin (code `ADMIN_REQUIRED`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  message: Only workspace admins can change CRM settings
                  code: ADMIN_REQUIRED
        '404':
          description: >-
            That CRM is not connected to your workspace (code
            `CRM_NOT_CONNECTED`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    OwnerFieldMappingInput:
      type: object
      description: Which CRM property holds one owner, and which side may change it.
      properties:
        field:
          type: string
          description: >-
            The CRM property's API name. An empty string removes the owner's
            mapping.
          example: hubspot_owner_id
        direction:
          type: string
          enum:
            - both
            - crm_owns
            - clustr_owns
            - 'off'
          default: both
          description: >-
            Which side may change the owner. `both`: a change in your CRM
            updates Clustr, and a change in Clustr is written to your CRM when
            the person making it chooses to. `crm_owns`: a change in your CRM
            updates Clustr, and changes made in Clustr stay in Clustr.
            `clustr_owns`: every change made in Clustr is written to your CRM,
            and Clustr keeps its own value. `off`: the mapping is kept and
            paused.
          example: both
        object:
          type: string
          description: >-
            For `company_cs` on HubSpot only. The custom object whose records
            are associated with your companies and hold the CS owner, by object
            type (for example `p_communities` or `2-1234567`). `field` is then
            that object's owner property, `hubspot_owner_id` by default. Clustr
            reads this owner and never writes it, so the direction is saved as
            `crm_owns`. Leave it empty to read a company property.
          example: p_communities
    OwnerFieldMappings:
      type: object
      required:
        - provider
        - company
        - contact
        - company_cs
      properties:
        provider:
          type: string
          enum:
            - hubspot
            - salesforce
            - attio
          example: hubspot
        company:
          allOf:
            - $ref: '#/components/schemas/OwnerFieldMapping'
          description: >-
            The account owner, on a CRM company. Attack competitor alerts name
            it.
        contact:
          allOf:
            - $ref: '#/components/schemas/OwnerFieldMapping'
          description: A connector's owner, on a CRM contact.
        company_cs:
          allOf:
            - $ref: '#/components/schemas/OwnerFieldMapping'
          description: >-
            The CS owner, on a CRM company, always read from your CRM. Defense
            competitor alerts name it.
    ErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          example: false
        error:
          type: object
          properties:
            message:
              type: string
              example: Invalid request body
            code:
              type: string
              example: BAD_REQUEST
    OwnerFieldMapping:
      type: object
      description: One owner's effective mapping.
      properties:
        field:
          type: string
          description: >-
            The CRM property's API name. An empty string means no field is
            mapped.
          example: hubspot_owner_id
        direction:
          type: string
          enum:
            - both
            - crm_owns
            - clustr_owns
            - 'off'
          description: Which side may change the owner; `off` means the mapping is paused.
          example: both
        isDefault:
          type: boolean
          description: >-
            true when no mapping is saved for this owner and the value shown is
            the CRM's default.
          example: true
        defaultField:
          type: string
          description: >-
            The CRM's standard owner field: `hubspot_owner_id` on HubSpot,
            `OwnerId` on Salesforce, and an empty string on Attio and for
            `company_cs`.
          example: hubspot_owner_id
        object:
          type: string
          description: >-
            The custom object the owner is read from, when it is not the company
            itself. Only `company_cs` on HubSpot.
          example: p_communities
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: The API key you created on the API settings page of the Clustr app.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.