> ## 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.

# John Deere

> Connect to John Deere Operations Center to pull field boundaries, machine files, and field operations through Leaf's provider credentials API.

Leaf connects to John Deere Operations Center using OAuth 2.0. Once connected, Leaf syncs fields, machine files, and field operations for the Leaf user.

## Prerequisites

1. A John Deere developer account. [Register here](https://account.deere.com/actmgmt/onboarding/registration).
2. An application registered in the [My Applications](https://developer.deere.com/#/applications) portal with the appropriate scopes and redirect URIs configured. Make sure **Webhook Read** and **Webhook Write** permissions are enabled under **Operations Center - Webhook** — this allows Leaf to receive real-time data notifications instead of relying solely on polling.
3. Your application's `clientKey` and `clientSecret` from John Deere.
4. A grower's `refreshToken` obtained through the John Deere OAuth 2.0 consent flow.

<Note>
  John Deere accounts can span multiple organizations. By default, Leaf syncs data from all organizations the account has access to. Use the `organizationDataSync` configuration to limit this to specific organizations.
</Note>

## Setup steps

1. Complete the John Deere 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 '{
        "clientKey": "your-client-key",
        "clientSecret": "your-client-secret",
        "refreshToken": "grower-refresh-token",
        "clientEnvironment": "PRODUCTION"
      }' \
      'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/john-deere-credentials'
  ```

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

  TOKEN = 'YOUR_TOKEN'

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

  data = {
      "clientKey": "your-client-key",
      "clientSecret": "your-client-secret",
      "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}/john-deere-credentials'
  const headers = { 'Authorization': `Bearer ${TOKEN}` }

  const data = {
      "clientKey": "your-client-key",
      "clientSecret": "your-client-secret",
      "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}/john-deere-credentials`.

## Credentials schema

**Create request body:**

| Field               | Type   | Required | Description                                   |
| ------------------- | ------ | -------- | --------------------------------------------- |
| `clientKey`         | string | Yes      | Your application's client key from John Deere |
| `clientSecret`      | string | Yes      | Your application's client secret              |
| `refreshToken`      | string | Yes      | The grower's OAuth refresh token              |
| `clientEnvironment` | string | Yes      | `STAGE` or `PRODUCTION`                       |

**Response:**

```json theme={null}
{
  "id": "uuid",
  "status": "str",
  "createdTime": "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'",
  "tokenMetadata": {"scopes": ["str"]},
  "clientKey": "str",
  "clientSecret": "str",
  "accessToken": "str",
  "refreshToken": "str",
  "clientEnvironment": "PRODUCTION"
}
```

The `status` field reflects the current health of the credential. If Leaf detects during background processing that the credential is no longer valid, the status changes accordingly.

## Endpoints

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

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

## 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}/john-deere-credentials/events'
  ```

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

  TOKEN = 'YOUR_TOKEN'
  endpoint = 'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/john-deere-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}/john-deere-credentials/events'
  const headers = { 'Authorization': `Bearer ${TOKEN}` }

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

Each event includes a `body`, `headers`, `statusCode`, and `createdDate`.

<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 in John Deere Operations Center, or the refresh token expired. Have the grower re-authorize through the OAuth flow.
* **Missing organizations**: If expected data isn't appearing, check whether `organizationDataSync` is set to `SELECTED_ONLY` and verify the correct organizations are selected.
* **STAGE vs. PRODUCTION mismatch**: Make sure `clientEnvironment` matches the environment your John Deere app is registered in.

## What to do next

* [Connect John Deere Tutorial](/guides/tutorials/connect-john-deere) — Step-by-step walkthrough.
* [Provider Authentication Overview](/providers/overview) — How provider credentials work across all providers.
* [API Reference: Providers](/api-reference/providers) — Full endpoint reference for provider credentials.
