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

# CNHI FieldOps

> Connect to CNHI FieldOps (Case IH, New Holland) to pull field boundaries, machine files, and field operations through Leaf's provider credentials API.

<Note>
  This page covers CNHI FieldOps, CNH Industrial's current API platform. For the legacy CNHI (AFS Connect) integration, see [CNHI (AFS Connect)](/providers/cnhi).
</Note>

CNH Industrial (Case IH, New Holland, Steyr) exposes two API platforms. Leaf supports both as separate providers: **[CNHI (AFS Connect)](/providers/cnhi)** and **CNHI FieldOps** (this page). CNHI FieldOps is the current platform — use it for new integrations.

Leaf connects to CNHI FieldOps using OAuth 2.0. Once connected, Leaf syncs growers, farms, fields, machine files, and field operations.

## Prerequisites

1. A CNH developer account registered with a **company-domain email** (generic email domains like Gmail and Hotmail are not supported). [Register here](https://develop.cnh.com/).
2. A FieldOps application registered in the CNH Developer Portal, with your `clientId`, `clientSecret`, and `subscriptionKey`.
3. A grower's `refreshToken` obtained through the CNHI FieldOps OAuth 2.0 consent flow.

<Warning>
  Existing CNHI (AFS Connect) subscription keys do not work with FieldOps. You must obtain new credentials from the CNH Developer Portal for the FieldOps API.
</Warning>

## Setup steps

1. Complete the CNHI FieldOps OAuth 2.0 flow to obtain a `refreshToken` for the grower's account.
2. POST the credentials to Leaf:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
      -H 'Authorization: Bearer YOUR_TOKEN' \
      -H 'Content-Type: application/json' \
      -d '{
        "clientId": "your-client-id",
        "clientSecret": "your-client-secret",
        "subscriptionKey": "your-subscription-key",
        "refreshToken": "grower-refresh-token",
        "clientEnvironment": "PRODUCTION"
      }' \
      'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/cnhi-field-ops-credentials'
  ```

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

  TOKEN = 'YOUR_TOKEN'

  endpoint = 'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/cnhi-field-ops-credentials'
  headers = {'Authorization': f'Bearer {TOKEN}'}

  data = {
      "clientId": "your-client-id",
      "clientSecret": "your-client-secret",
      "subscriptionKey": "your-subscription-key",
      "refreshToken": "grower-refresh-token",
      "clientEnvironment": "PRODUCTION"
  }

  response = requests.post(endpoint, headers=headers, json=data)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios')
  const TOKEN = 'YOUR_TOKEN'

  const endpoint = 'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/cnhi-field-ops-credentials'
  const headers = { 'Authorization': `Bearer ${TOKEN}` }

  const data = {
      "clientId": "your-client-id",
      "clientSecret": "your-client-secret",
      "subscriptionKey": "your-subscription-key",
      "refreshToken": "grower-refresh-token",
      "clientEnvironment": "PRODUCTION"
  }

  axios.post(endpoint, data, { headers })
      .then(res => console.log(res.data))
      .catch(console.error)
  ```
</CodeGroup>

3. Leaf validates the token and begins syncing. Check credential status with `GET /users/{leafUserId}/cnhi-field-ops-credentials`.

## Credentials schema

**Create request body:**

| Field               | Type   | Required | Description                                                    |
| ------------------- | ------ | -------- | -------------------------------------------------------------- |
| `clientId`          | string | Yes      | Your application's client ID from the CNH Developer Portal     |
| `clientSecret`      | string | Yes      | Your application's client secret                               |
| `subscriptionKey`   | string | Yes      | Your FieldOps subscription key (not reusable from legacy CNHI) |
| `refreshToken`      | string | Yes      | The grower's OAuth refresh token                               |
| `clientEnvironment` | string | No       | `STAGE` or `PRODUCTION`. Defaults to `STAGE`                   |

**Response:**

```json theme={null}
{
  "id": "uuid",
  "status": "str",
  "createdTime": "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'",
  "clientId": "str",
  "clientSecret": "str",
  "refreshToken": "str",
  "clientEnvironment": "PRODUCTION",
  "subscriptionKey": "str"
}
```

## Endpoints

Base URL: `https://api.withleaf.io/services/usermanagement/api`

| Action                | Method | Path                                                    |
| --------------------- | ------ | ------------------------------------------------------- |
| Get credentials       | GET    | `/users/{leafUserId}/cnhi-field-ops-credentials`        |
| Create credentials    | POST   | `/users/{leafUserId}/cnhi-field-ops-credentials`        |
| Delete credentials    | DELETE | `/users/{leafUserId}/cnhi-field-ops-credentials`        |
| Get credential events | GET    | `/users/{leafUserId}/cnhi-field-ops-credentials/events` |

## Data sync behavior

CNHI FieldOps supports webhook-based change notifications. When new files, operations, or field changes occur in a grower's FieldOps account, CNH pushes events to Leaf. This reduces sync latency compared to the legacy CNHI provider, which relies on periodic polling.

Leaf manages webhook subscriptions automatically for each connected account. No additional configuration is needed.

## Troubleshooting

Use the events endpoint to inspect credential health:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET \
      -H 'Authorization: Bearer YOUR_TOKEN' \
      'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/cnhi-field-ops-credentials/events'
  ```

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

  TOKEN = 'YOUR_TOKEN'
  endpoint = 'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/cnhi-field-ops-credentials/events'
  headers = {'Authorization': f'Bearer {TOKEN}'}

  response = requests.get(endpoint, headers=headers)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios')
  const TOKEN = 'YOUR_TOKEN'

  const endpoint = 'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/cnhi-field-ops-credentials/events'
  const headers = { 'Authorization': `Bearer ${TOKEN}` }

  axios.get(endpoint, { headers })
      .then(res => console.log(res.data))
      .catch(console.error)
  ```
</CodeGroup>

<Warning>
  Event logs are retained for 30 days. Once the credential is deleted or disassociated from the Leaf user, the logs are no longer available.
</Warning>

Common issues:

* **Status changes to invalid**: The grower may have revoked access or the refresh token expired. Have the grower re-authorize through the FieldOps OAuth flow.
* **STAGE vs. PRODUCTION mismatch**: Make sure `clientEnvironment` matches the environment your CNHI FieldOps app is registered in.
* **Missing or invalid subscription key**: FieldOps requires a new `subscriptionKey` separate from any legacy CNHI keys. Verify you're passing the correct key.
* **Account mismatch**: The grower's FieldOps account may not exist in the environment you specified. Staging and production identities are separate.
* **Grower cannot authorize**: The grower must have the **Farm Manager** title in their FieldOps account and must have logged into the [FieldOps portal](https://develop.cnh.com/get-started/fieldops-portal) at least once before they can complete the OAuth consent flow.

## How FieldOps data appears in Leaf's APIs

CNHI FieldOps data flows through the same Leaf endpoints as every other provider — fields, files, and operations. The `provider` field on each object identifies the source:

* Fields from FieldOps: `"provider": "CNHIFieldOps"`
* Machine files from FieldOps: `"provider": "CNHIFieldOps"`
* Field operations from FieldOps: `"provider": "CNHIFieldOps"`

Legacy CNHI (AFS Connect) data continues to show `"provider": "CNHI"`.

You can filter by provider when querying:

```bash theme={null}
curl "https://api.withleaf.io/services/fields/api/fields?provider=CNHIFieldOps" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

The data structure, output format (GeoJSON/GeoParquet), and field operation merging behavior are identical regardless of provider. The only difference is the `provider` value on the returned objects.

<Warning>
  If a Leaf user has both `cnhi-credentials` and `cnhi-field-ops-credentials` attached, the same physical field may appear twice — once with `"provider": "CNHI"` and once with `"provider": "CNHIFieldOps"`. Remove the legacy credential after confirming the FieldOps connection to avoid duplicates.
</Warning>

## What to do next

* [Connect CNHI FieldOps Tutorial](/guides/tutorials/connect-cnhi-fieldops) — Step-by-step walkthrough.
* [Migrate from CNHI to CNHI FieldOps](/guides/tutorials/migrate-cnhi-to-fieldops) — For customers moving from the legacy provider.
* [Provider Authentication Overview](/providers/overview) — How provider credentials work across all providers.
* [API Reference: Providers](/api-reference/providers) — Full endpoint reference for provider credentials.
