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

# Sentera

> Connect to Sentera to pull field boundary data through Leaf's provider credentials API using username and password authentication.

Leaf connects to Sentera using username/password authentication rather than OAuth. Once connected, Leaf syncs field boundary data for the Leaf user. Sentera is primarily used for field boundary management.

## Prerequisites

1. A Sentera account with the target organization.
2. The grower's `username` and `password` for their Sentera account.
3. The `organizationName` within Sentera that the grower belongs to.

## Setup steps

POST the credentials to Leaf:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
      -H 'Authorization: Bearer YOUR_TOKEN' \
      -H 'Content-Type: application/json' \
      -d '{
        "username": "grower-username",
        "password": "grower-password",
        "organizationName": "grower-org-name"
      }' \
      'https://api.withleaf.io/services/usermanagement/api/users/{leafUserId}/sentera-credentials'
  ```

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

  TOKEN = 'YOUR_TOKEN'

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

  data = {
      "username": "grower-username",
      "password": "grower-password",
      "organizationName": "grower-org-name"
  }

  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}/sentera-credentials'
  const headers = { 'Authorization': `Bearer ${TOKEN}` }

  const data = {
      "username": "grower-username",
      "password": "grower-password",
      "organizationName": "grower-org-name"
  }

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

## Credentials schema

**Create request body:**

| Field              | Type   | Required | Description                   |
| ------------------ | ------ | -------- | ----------------------------- |
| `username`         | string | Yes      | The grower's Sentera username |
| `password`         | string | Yes      | The grower's Sentera password |
| `organizationName` | string | Yes      | The Sentera organization name |

**Response:**

```json theme={null}
{
  "id": "uuid",
  "status": "str",
  "createdTime": "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'",
  "username": "str",
  "authToken": "str",
  "organizationId": "str",
  "organizationName": "str"
}
```

Leaf generates an `authToken` and resolves the `organizationId` from the provided `organizationName` after successful authentication.

## 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}/sentera-credentials" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

If this worked, Leaf returns the Sentera credential object with the resolved `organizationId`.

## Endpoints

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

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

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

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

* **Invalid credentials**: If the grower changed their Sentera password, the credentials stored in Leaf become invalid. Delete and recreate with the new password.
* **Organization not found**: Verify the `organizationName` matches exactly what's configured in Sentera, including case sensitivity.

## What to do next

* [Fields Overview](/fields/overview) for how Sentera field boundaries appear in Leaf.
* [Managing Fields](/fields/managing-fields) for working with the synced boundaries.
* [Provider Credentials API Reference](/api-reference/providers) for the credential path matrix.
