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

# Precision Planting Panorama

> Connect to Precision Planting Panorama to pull field boundaries, machine files, and field operations through Leaf's provider credentials API.

Leaf connects to Precision Planting Panorama using OAuth 2.0 via AWS Cognito. Once connected, Leaf syncs growers, farms, fields, machine files, and field operations.

<Tip>
  The recommended way to create Panorama credentials is through the one-click integration endpoint: `POST /users/{leafUserId}/one-click-integration/Panorama`. This handles the Cognito token exchange and sharing handshake automatically.
</Tip>

## Prerequisites

1. A Precision Planting Panorama developer/partner account.
2. Your application's `clientId` from the Panorama developer portal.
3. The partner's `username` and `password` from your Panorama account.
4. A `refreshToken` obtained through the Cognito authentication flow, or use the one-click integration endpoint which handles this for you.
5. The grower's organizationCode, pre-authorized to share data with your Panorama partner application (manual credential creation only).

## Setup steps

**Option A: One-click integration (recommended)**

Use the one-click integration endpoint, which handles the Cognito token exchange automatically:

```
POST /users/{leafUserId}/one-click-integration/Panorama
```

One-click start request:

```json theme={null}
{
  "clientId": "your-client-id",
  "username": "partner-username",
  "password": "partner-password",
  "clientEnvironment": "PRODUCTION",
  "sharingUrlId": "your-custom-sharing-url-id"
}
```

* `organizationCode` is not requried for the one-click flow.
* Set the `sharingUrlId` in both the one-click request body and your Panorama app key configuration.
* Set the Sharing Confirmation URL to `https://widget.withleaf.io` in the Panorama Partner Portal so Leaf can receive the callback and complete credential attachment.
* The `sharingUrlId` is the UUID contained in the Share Initiation URL and can be obtained through the Panorama Partner Portal under the Account Details tab.

<img src="https://mintcdn.com/leaf-3ed5893a/OOLsMKK8a9O_nbyQ/providers/images/panorama_app_information.png?fit=max&auto=format&n=OOLsMKK8a9O_nbyQ&q=85&s=0b16635e096b8cc92d5ce1aa466b4d91" alt="Panorama application information" width="620" height="522" data-path="providers/images/panorama_app_information.png" />

**Option B: Manual credential creation**

If you manage the Cognito flow yourself, 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",
        "username": "partner-username",
        "password": "partner-password",
        "organizationCode": "grower-org-code",
        "refreshToken": "cognito-refresh-token",
        "clientEnvironment": "PRODUCTION"
      }' \
      'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/panorama-credentials'
  ```

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

  TOKEN = 'YOUR_TOKEN'

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

  data = {
      "clientId": "your-client-id",
      "username": "partner-username",
      "password": "partner-password",
      "organizationCode": "grower-org-code",
      "refreshToken": "cognito-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}/panorama-credentials'
  const headers = { 'Authorization': `Bearer ${TOKEN}` }

  const data = {
      "clientId": "your-client-id",
      "username": "partner-username",
      "password": "partner-password",
      "organizationCode": "grower-org-code",
      "refreshToken": "cognito-refresh-token",
      "clientEnvironment": "PRODUCTION"
  }

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

## Confirm the credentials are attached

Check the stored credentials for the Leaf user:

```bash theme={null}
curl "https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/panorama-credentials" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

If this worked, Leaf returns the Panorama credential object for the Leaf user.

## Credentials schema

**Create request body:**

| Field               | Type   | Required | Description                                |
| ------------------- | ------ | -------- | ------------------------------------------ |
| `clientId`          | string | Yes      | Your application's client ID from Panorama |
| `username`          | string | Yes      | The partner's Panorama username            |
| `password`          | string | Yes      | The partner's Panorama password            |
| `organizationCode`  | string | Yes      | The grower's organization code in Panorama |
| `refreshToken`      | string | Yes      | Cognito 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'",
  "clientId": "str",
  "username": "str",
  "organizationCode": "str",
  "clientEnvironment": "PRODUCTION",
  "accessToken": "str",
  "refreshToken": "str"
}
```

## Endpoints

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

| Action                | Method | Path                                              |
| --------------------- | ------ | ------------------------------------------------- |
| Get credentials       | GET    | `/users/{leafUserId}/panorama-credentials`        |
| Create credentials    | POST   | `/users/{leafUserId}/panorama-credentials`        |
| Delete credentials    | DELETE | `/users/{leafUserId}/panorama-credentials`        |
| Get credential events | GET    | `/users/{leafUserId}/panorama-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}/panorama-credentials/events'
  ```

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

  TOKEN = 'YOUR_TOKEN'
  endpoint = 'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/panorama-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}/panorama-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:

* **Cognito token expiry**: Panorama uses AWS Cognito for auth. If the credential becomes invalid, the grower may need to re-authenticate. Using the one-click integration endpoint avoids much of this complexity.
* **Wrong organization code**: For manual credential creation, verify the `organizationCode` is already authorized to share data with your Panorama partner application.
* **STAGE vs. PRODUCTION mismatch**: Make sure `clientEnvironment` matches your Panorama setup.

## What to do next

* [Field Operations Quickstart](/guides/tutorials/field-operations-quickstart) for checking synced field and operation data.
* [Provider Organizations](/providers/organizations) if you need to review sync scope after connection.
* [Provider Credentials API Reference](/api-reference/providers) for the credential path matrix.
