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

# Get Satellite Imagery for Your Fields

> Use Leaf's crop monitoring API to get satellite imagery for your fields. Create fields, retrieve NDVI, NDRE, and RGB images from Sentinel-2 and Planet.

Leaf's crop monitoring API delivers satellite imagery from Sentinel-2 and Planet, processed and clipped to your field boundaries. You get NDVI, NDRE, RGB compositions, and raw multiband GeoTIFFs. This tutorial walks through creating a satellite field and retrieving images.

## Before you start

* A Leaf account with a valid API token.
* A field boundary (as a GeoJSON MultiPolygon). You can use coordinates from any source.

<Note>
  Leaf users and configurations are not required for satellite imagery. You only need authentication and a field geometry.
</Note>

## Step 1: Get your Leaf token

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.withleaf.io/api/authenticate" \
    -H "Content-Type: application/json" \
    -d '{
      "username": "your-email@example.com",
      "password": "your-password"
    }'
  ```

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

  response = requests.post(
      "https://api.withleaf.io/api/authenticate",
      json={"username": "your-email@example.com", "password": "your-password"}
  )
  token = response.json()["id_token"]
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://api.withleaf.io/api/authenticate", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      username: "your-email@example.com",
      password: "your-password",
    }),
  });
  const { id_token } = await res.json();
  ```
</CodeGroup>

## Step 2: Create a satellite field

POST a field boundary to the crop monitoring endpoint. The geometry must be a MultiPolygon.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.withleaf.io/services/satellite/api/fields" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "externalId": "my-field-001",
      "providers": [
        {
          "name": "sentinel",
          "startDate": "2025-01-01"
        }
      ],
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [[[
          [-93.48821, 41.77137],
          [-93.48821, 41.77088],
          [-93.48738, 41.77088],
          [-93.48738, 41.77137],
          [-93.48821, 41.77137]
        ]]]
      }
    }'
  ```

  ```python Python theme={null}
  headers = {"Authorization": f"Bearer {token}"}

  field = requests.post(
      "https://api.withleaf.io/services/satellite/api/fields",
      headers=headers,
      json={
          "externalId": "my-field-001",
          "providers": [{"name": "sentinel", "startDate": "2025-01-01"}],
          "geometry": {
              "type": "MultiPolygon",
              "coordinates": [[[
                  [-93.48821, 41.77137],
                  [-93.48821, 41.77088],
                  [-93.48738, 41.77088],
                  [-93.48738, 41.77137],
                  [-93.48821, 41.77137]
              ]]]
          }
      }
  ).json()
  satellite_field_id = field["id"]
  print(f"Satellite field created: {satellite_field_id}")
  ```

  ```javascript JavaScript theme={null}
  const field = await fetch(
    "https://api.withleaf.io/services/satellite/api/fields",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${id_token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        externalId: "my-field-001",
        providers: [{ name: "sentinel", startDate: "2025-01-01" }],
        geometry: {
          type: "MultiPolygon",
          coordinates: [[[
            [-93.48821, 41.77137],
            [-93.48821, 41.77088],
            [-93.48738, 41.77088],
            [-93.48738, 41.77137],
            [-93.48821, 41.77137],
          ]]],
        },
      }),
    }
  ).then((r) => r.json());
  console.log("Satellite field created:", field.id);
  ```
</CodeGroup>

Key details:

* The `name` field in providers must be exactly `"sentinel"` or `"planet"`. Planet requires activation from Leaf support.
* The `startDate` tells Leaf how far back to fetch historical images.
* You can request multiple providers and asset types for the same field.

After creation, Leaf begins fetching and processing images from the start date forward.

## Step 3: Retrieve images

Query the images available for your satellite field:

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.withleaf.io/services/satellite/api/fields/SATELLITE_FIELD_ID/processes" \
    -H "Authorization: Bearer YOUR_TOKEN"
  ```

  ```python Python theme={null}
  images = requests.get(
      f"https://api.withleaf.io/services/satellite/api/fields/{satellite_field_id}/processes",
      headers=headers
  ).json()

  for img in images:
      print(f"Date: {img['date']}")
      print(f"  NDVI PNG: {img.get('ndvi', {}).get('png')}")
      print(f"  NDVI TIF: {img.get('ndvi', {}).get('tif')}")
      print(f"  RGB PNG:  {img.get('rgb', {}).get('png')}")
  ```

  ```javascript JavaScript theme={null}
  const images = await fetch(
    `https://api.withleaf.io/services/satellite/api/fields/${field.id}/processes`,
    { headers: { Authorization: `Bearer ${id_token}` } }
  ).then((r) => r.json());

  images.forEach((img) => {
    console.log(`Date: ${img.date}`);
    console.log(`  NDVI: ${img.ndvi?.png}`);
    console.log(`  RGB: ${img.rgb?.png}`);
  });
  ```
</CodeGroup>

Each image process includes:

* **Multiband GeoTIFF** (the original satellite data)
* **RGB** composition (GeoTIFF and PNG)
* **NDVI** (GeoTIFF and PNG)
* **NDRE** (GeoTIFF and PNG)

The download URLs require authentication. Pass your Leaf token in the `Authorization` header when downloading.

You can filter results by date range and cloud coverage:

```text theme={null}
?startDate=2025-06-01&endDate=2025-09-01&maxCloudCoverage=50
```

<Note>
  If cloud coverage is 50% or less, the image is included but cloud shadows may still be visible. There's no way to filter out the shadow itself.
</Note>

## Step 4: Set up alerts

Instead of polling for new images, set up an alert to get notified when new satellite imagery is processed:

```bash theme={null}
curl -X POST "https://api.withleaf.io/services/alerts/api/alerts" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "newSatelliteImage",
    "url": "https://your-app.com/webhook/satellite"
  }'
```

Leaf sends a POST to your webhook URL with the satellite field ID, process ID, and timestamp whenever a new image finishes processing.

## What you built

You created a satellite field with Leaf's crop monitoring API and retrieved NDVI, NDRE, and RGB imagery. Leaf continuously monitors the field and processes new images as they become available from Sentinel-2 (roughly every 5 days) or Planet (daily with activation).

For the full endpoint reference, see the [satellite API reference](/api-reference/satellite). To use satellite data in ArcGIS, see the [ArcGIS integration tutorial](/guides/tutorials/arcgis-integration).
