# Zoho CRM

Zoho CRM is a cloud-based customer relationship management platform that helps businesses manage leads, contacts, accounts, deals, and more across the entire sales lifecycle. The Sling Zoho CRM connector extracts data from the Zoho CRM REST API v6, supporting core CRM modules (leads, contacts, accounts, deals), activity data (tasks, meetings, calls), and additional objects like campaigns, products, notes, quotes, and vendors.

{% hint style="success" %}
**CLI Pro Required**: APIs require a [CLI Pro token](https://docs.slingdata.io/sling-cli/cli-pro) or [Platform Plan](https://docs.slingdata.io/sling-platform/platform).
{% endhint %}

## Setup

The following credentials and inputs are accepted:

**Secrets:**

* `client_id` **(required)** -> Your Zoho OAuth2 Client ID
* `client_secret` **(required)** -> Your Zoho OAuth2 Client Secret
* `soid` **(required)** -> Your Zoho CRM Organization ID (format: `ZohoCRM.<org_id>`)
* `accounts_url` (optional) -> Zoho Accounts URL for your data center (default: `https://accounts.zoho.com`). See [Multi-DC Support](#multi-dc-support) below.
* `api_domain` (optional) -> Zoho API domain for your data center (default: `https://www.zohoapis.com`). See [Multi-DC Support](#multi-dc-support) below.

**Inputs:**

* `anchor_date` (optional) -> The starting date for historical data extraction (default: 1 year ago). Format: `YYYY-MM-DD`

### Getting Your Credentials

Zoho CRM uses **OAuth2 Client Credentials** for API authentication. You need to create a Self Client application:

1. Go to the [Zoho API Console](https://api-console.zoho.com/)
2. Click **Add Client** and select **Self Client**
3. Give your client a name (e.g., "Sling Integration") and click **Create**
4. You will see your **Client ID** and **Client Secret** -- copy both

**Finding your Organization ID (SOID):**

1. Log in to [Zoho CRM](https://crm.zoho.com/)
2. Go to **Setup** > **Developer Space** > **APIs**
3. Your Organization ID is displayed on the API dashboard
4. The SOID format is `ZohoCRM.<org_id>` (e.g., `ZohoCRM.12345678`)

**Required OAuth Scopes:**

The connector requests the following scopes automatically:

* `ZohoCRM.modules.ALL` -- Read access to all CRM modules
* `ZohoCRM.settings.ALL` -- Read access to CRM settings
* `ZohoCRM.users.ALL` -- Read access to CRM users
* `ZohoCRM.org.ALL` -- Read access to organization data
* `ZohoSearch.securesearch.READ` -- Read access for search operations

{% hint style="info" %}
**Self Client apps** use the Client Credentials grant type, which means no user interaction is required for token generation. Sling handles token refresh automatically.
{% endhint %}

### Using `sling conns`

{% code overflow="wrap" %}

```bash
sling conns set ZOHO_CRM type=api spec=zoho-crm secrets='{ client_id: your_client_id, client_secret: your_client_secret, soid: "ZohoCRM.12345678" }'
```

{% endcode %}

### Environment Variable

See [here](https://docs.slingdata.io/sling-cli/environment#dot-env-file-.env.sling) to learn more about the `.env.sling` file.

{% code overflow="wrap" %}

```bash
export ZOHO_CRM='{ type: api, spec: zoho-crm, secrets: { client_id: "your_client_id", client_secret: "your_client_secret", soid: "ZohoCRM.12345678" } }'
```

{% endcode %}

### Sling Env File YAML

See [here](https://docs.slingdata.io/sling-cli/environment#sling-env-file-env.yaml) to learn more about the sling `env.yaml` file.

```yaml
connections:
  ZOHO_CRM:
    type: api
    spec: zoho-crm
    secrets:
      client_id: "your_client_id"
      client_secret: "your_client_secret"
      soid: "ZohoCRM.12345678"
```

**With anchor date for historical data:**

```yaml
connections:
  ZOHO_CRM:
    type: api
    spec: zoho-crm
    secrets:
      client_id: "your_client_id"
      client_secret: "your_client_secret"
      soid: "ZohoCRM.12345678"
    inputs:
      anchor_date: "2020-01-01"
```

## Multi-DC Support

Zoho operates data centers in multiple regions. By default, the connector uses the US data center (`accounts.zoho.com` / `www.zohoapis.com`). If your Zoho account is hosted in a different region, set the `accounts_url` and `api_domain` secrets accordingly:

| Region    | `accounts_url`                        | `api_domain`                         |
| --------- | ------------------------------------- | ------------------------------------ |
| US        | `https://accounts.zoho.com` (default) | `https://www.zohoapis.com` (default) |
| EU        | `https://accounts.zoho.eu`            | `https://www.zohoapis.eu`            |
| India     | `https://accounts.zoho.in`            | `https://www.zohoapis.in`            |
| Australia | `https://accounts.zoho.com.au`        | `https://www.zohoapis.com.au`        |
| Japan     | `https://accounts.zoho.jp`            | `https://www.zohoapis.jp`            |
| Canada    | `https://accounts.zohocloud.ca`       | `https://www.zohoapis.ca`            |

**Example for EU data center:**

```yaml
connections:
  ZOHO_CRM:
    type: api
    spec: zoho-crm
    secrets:
      client_id: "your_client_id"
      client_secret: "your_client_secret"
      soid: "ZohoCRM.12345678"
      accounts_url: "https://accounts.zoho.eu"
      api_domain: "https://www.zohoapis.eu"
```

## Replication

Here's an example replication configuration to sync Zoho CRM data to a PostgreSQL database:

```yaml
source: ZOHO_CRM
target: MY_POSTGRES

defaults:
  mode: incremental
  object: zoho_crm.{stream_name}

streams:
  # Core CRM objects with incremental sync
  leads:
  contacts:
  accounts:
  deals:

  # Activity data with incremental sync
  tasks:
  meetings:
  calls:

  # Reference data (full-refresh recommended)
  users:
    mode: full-refresh
  modules:
    mode: full-refresh
```

**Sync all endpoints:**

```yaml
source: ZOHO_CRM
target: MY_POSTGRES

defaults:
  mode: incremental
  object: zoho_crm.{stream_name}

streams:
  # Sync all available endpoints
  '*':

  # Override mode for metadata endpoints
  users:
    mode: full-refresh
  modules:
    mode: full-refresh
```

## Endpoints

### Core CRM Objects

| Endpoint   | Description             | Incremental |
| ---------- | ----------------------- | ----------- |
| `leads`    | CRM leads               | Yes         |
| `contacts` | CRM contacts            | Yes         |
| `accounts` | CRM accounts/companies  | Yes         |
| `deals`    | CRM deals/opportunities | Yes         |

### Activities

| Endpoint   | Description          | Incremental |
| ---------- | -------------------- | ----------- |
| `tasks`    | CRM tasks/activities | Yes         |
| `meetings` | CRM meetings/events  | Yes         |
| `calls`    | CRM call logs        | Yes         |

### Sales & Marketing

| Endpoint    | Description      | Incremental |
| ----------- | ---------------- | ----------- |
| `campaigns` | CRM campaigns    | Yes         |
| `products`  | Product catalog  | Yes         |
| `quotes`    | Quotes/proposals | Yes         |
| `vendors`   | Vendor records   | Yes         |

### Other

| Endpoint  | Description                              | Incremental |
| --------- | ---------------------------------------- | ----------- |
| `users`   | All CRM users in the organization        | No          |
| `notes`   | Notes attached to records                | Yes         |
| `modules` | Metadata about all available CRM modules | No          |

To discover available endpoints:

```bash
sling conns discover ZOHO_CRM
```

## Incremental Sync

The Zoho CRM connector uses time-based incremental sync via the `Modified_Time` field for most endpoints:

* **First run:** Fetches records modified from `anchor_date` (default: 1 year ago) to present
* **Subsequent runs:** Only fetches records modified after the last sync

Incremental sync is supported for:

* Core CRM objects (leads, contacts, accounts, deals)
* Activities (tasks, meetings, calls)
* Sales & marketing (campaigns, products, quotes, vendors)
* Notes

The `users` and `modules` endpoints do not support incremental sync and always perform a full refresh.

## Rate Limiting

The Zoho CRM API enforces rate limits based on your Zoho edition. The connector automatically:

* Uses conservative rate limiting (5 requests/second with 3 concurrent requests)
* Retries with exponential backoff on 429 (rate limit) responses

## Common Use Cases

### Sync Core CRM Data

```yaml
source: ZOHO_CRM
target: MY_POSTGRES

defaults:
  mode: incremental
  object: crm.{stream_name}

streams:
  leads:
  contacts:
  accounts:
  deals:
  users:
    mode: full-refresh
```

### Sync Activity Data

```yaml
source: ZOHO_CRM
target: MY_POSTGRES

defaults:
  mode: incremental
  object: activities.{stream_name}

streams:
  tasks:
  meetings:
  calls:
  notes:
```

### Sync Sales Pipeline

```yaml
source: ZOHO_CRM
target: MY_POSTGRES

defaults:
  mode: incremental
  object: sales.{stream_name}

streams:
  deals:
  quotes:
  products:
  campaigns:
```

If you are facing issues connecting, please reach out to us at <support@slingdata.io>, on [discord](https://discord.gg/q5xtaSNDvp) or open a Github Issue [here](https://github.com/slingdata-io/sling-cli/issues).
