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

# CRM Settings

> Manage CRM integration settings for your organization

This endpoint allows you to manage CRM integration settings for your organization. You can retrieve current settings, connect a new CRM provider, or disconnect an existing CRM integration.

## Authentication

All endpoints require authentication. The `orgId` must be present in the authenticated session.

<Note>
  Requests without valid authentication will receive a `400 Bad Request`
  response with the message "Organization ID required".
</Note>

***

## Get CRM Settings

<api method="GET" endpoint="/api/v1/operations/crm/settings" />

Retrieve the current CRM settings for your organization. Returns connection status, provider type, and a masked API key for security.

### Response

<ResponseField name="connected" type="boolean" required>
  Indicates whether a CRM is currently connected and enabled for the
  organization.
</ResponseField>

<ResponseField name="provider" type="string | null" required>
  The CRM provider currently configured. Returns `null` if no CRM is connected.

  **Allowed values:**

  * `close` - Close CRM
  * `bullhorn` - Bullhorn CRM
  * `null` - No CRM connected
</ResponseField>

<ResponseField name="connectedAt" type="string">
  ISO-8601 timestamp of when the CRM was connected. Only present if a CRM is
  connected. **Example:** `2024-01-15T10:30:00.000Z`
</ResponseField>

<ResponseField name="apiKeyMasked" type="string | null">
  A masked version of the API key showing only the last 4 characters for
  verification purposes. Returns `null` if no API key is configured.
  **Example:** `********************abc1`
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://app.lance.so/api/v1/operations/crm/settings" \
    -H "Authorization: Bearer <token>"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("/api/v1/operations/crm/settings", {
    method: "GET",
    headers: {
      Authorization: "Bearer <token>",
    },
  });

  const data = await response.json();
  ```

  ```typescript TypeScript theme={null}
  interface CrmSettingsResponse {
    connected: boolean;
    provider: "close" | "bullhorn" | null;
    connectedAt?: string;
    apiKeyMasked?: string | null;
  }

  const response = await fetch("/api/v1/operations/crm/settings", {
    method: "GET",
    headers: {
      Authorization: "Bearer <token>",
    },
  });

  const data: CrmSettingsResponse = await response.json();
  ```
</RequestExample>

<ResponseExample>
  ```json Connected Response theme={null}
  {
    "connected": true,
    "provider": "bullhorn",
    "connectedAt": "2024-01-15T10:30:00.000Z",
    "apiKeyMasked": "********************abc1"
  }
  ```

  ```json Not Connected Response theme={null}
  {
    "connected": false,
    "provider": null
  }
  ```

  ```json Error Response (Authentication) theme={null}
  {
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Organization ID required"
    }
  }
  ```
</ResponseExample>

***

## Save CRM Settings

<api method="POST" endpoint="/api/v1/operations/crm/settings" />

Connect a CRM provider to your organization by saving the provider type and API credentials.

### Request

<ParamField body="provider" type="string" required>
  The CRM provider to connect. **Allowed values:** - `close` - Close CRM -
  `bullhorn` - Bullhorn CRM
</ParamField>

<ParamField body="apiKey" type="string" required>
  The API key or authentication token for the CRM provider. Must be a non-empty string.

  <Warning>
    Store API keys securely. They are stored in Clerk organization metadata and only the masked version is returned in GET responses.
  </Warning>
</ParamField>

### Response

<ResponseField name="success" type="boolean" required>
  Indicates the settings were saved successfully. Always `true` for successful
  responses.
</ResponseField>

<ResponseField name="provider" type="string" required>
  The CRM provider that was configured. **Allowed values:** `close`, `bullhorn`
</ResponseField>

<ResponseField name="connectedAt" type="string" required>
  ISO-8601 timestamp of when the CRM was connected. **Example:**
  `2024-01-15T10:30:00.000Z`
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://app.lance.so/api/v1/operations/crm/settings" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer <token>" \
    -d '{
      "provider": "bullhorn",
      "apiKey": "your-api-key-here"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("/api/v1/operations/crm/settings", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer <token>",
    },
    body: JSON.stringify({
      provider: "bullhorn",
      apiKey: "your-api-key-here",
    }),
  });

  const data = await response.json();
  ```

  ```typescript TypeScript theme={null}
  interface SaveCrmSettingsRequest {
    provider: "close" | "bullhorn";
    apiKey: string;
  }

  interface SaveCrmSettingsResponse {
    success: boolean;
    provider: "close" | "bullhorn";
    connectedAt: string;
  }

  const response = await fetch("/api/v1/operations/crm/settings", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer <token>",
    },
    body: JSON.stringify({
      provider: "bullhorn",
      apiKey: "your-api-key-here",
    } satisfies SaveCrmSettingsRequest),
  });

  const data: SaveCrmSettingsResponse = await response.json();
  ```
</RequestExample>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "success": true,
    "provider": "bullhorn",
    "connectedAt": "2024-01-15T10:30:00.000Z"
  }
  ```

  ```json Error Response (Missing API Key) theme={null}
  {
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "API key is required"
    }
  }
  ```

  ```json Error Response (Invalid Provider) theme={null}
  {
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Invalid enum value. Expected 'close' | 'bullhorn', received 'salesforce'"
    }
  }
  ```
</ResponseExample>

***

## Disconnect CRM

<api method="DELETE" endpoint="/api/v1/operations/crm/settings" />

Disconnect the CRM integration from your organization. This removes all CRM settings including the stored API key.

### Response

<ResponseField name="success" type="boolean" required>
  Indicates the CRM was successfully disconnected. Always `true` for successful
  responses.
</ResponseField>

<ResponseField name="disconnected" type="boolean" required>
  Confirms the CRM has been disconnected. Always `true` for successful
  responses.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X DELETE "https://app.lance.so/api/v1/operations/crm/settings" \
    -H "Authorization: Bearer <token>"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("/api/v1/operations/crm/settings", {
    method: "DELETE",
    headers: {
      Authorization: "Bearer <token>",
    },
  });

  const data = await response.json();
  ```

  ```typescript TypeScript theme={null}
  interface DisconnectCrmResponse {
    success: boolean;
    disconnected: boolean;
  }

  const response = await fetch("/api/v1/operations/crm/settings", {
    method: "DELETE",
    headers: {
      Authorization: "Bearer <token>",
    },
  });

  const data: DisconnectCrmResponse = await response.json();
  ```
</RequestExample>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "success": true,
    "disconnected": true
  }
  ```

  ```json Error Response (Authentication) theme={null}
  {
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Organization ID required"
    }
  }
  ```
</ResponseExample>

***

## Error Codes

| Status Code | Error Code         | Description                                                              |
| ----------- | ------------------ | ------------------------------------------------------------------------ |
| `400`       | `VALIDATION_ERROR` | Invalid request body, missing required fields, or missing authentication |
| `500`       | `INTERNAL_ERROR`   | Server error while processing the request                                |

## Supported CRM Providers

| Provider | Value      | Description                                     |
| -------- | ---------- | ----------------------------------------------- |
| Close    | `close`    | Close CRM - Sales communication platform        |
| Bullhorn | `bullhorn` | Bullhorn CRM - Staffing and recruiting software |

## Notes

* CRM settings are stored in Clerk organization private metadata
* API keys are never returned in full - only masked versions are available via the GET endpoint
* Disconnecting a CRM removes all settings; you'll need to reconfigure if reconnecting
* Each organization can only have one CRM provider connected at a time
