# Net Zero Watering (`sciguy/evapotranspiration`) Actor

Apply only the water the plant used. Weather, rain, and plant type in — litres or gallons out.

- **URL**: https://apify.com/sciguy/evapotranspiration.md
- **Developed by:** [Josh Berry](https://apify.com/sciguy) (community)
- **Categories:** Automation, AI
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 irrigation calculations

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Net Zero Watering do?

**Net Zero Watering** tells you the exact volume to apply so you replace what the plant used — not a guess, not a timer, and not a soak “just in case.” Send the weather, recent rain, plant type, and canopy size. You get **litres or US gallons** from the **FAO-56 Penman–Monteith** method: farm-grade irrigation science, minus the spreadsheet.

Try it from the **Input** tab or POST JSON to `/calculate`. Pick a plant such as `tomato` (see [common plants](#plant-types-and-kc)). If you skip plant type, the crop coefficient defaults to **0.8**. On Apify you get a stable API URL, scheduling, monitoring, and pay-per-calculation billing — you pay when you ask, not while the Actor sits idle.

### Why use Net Zero Watering?

Overwatering wastes money and drowns roots. Underwatering stresses fruit, turf, and greenhouse crops. **Net Zero Watering** turns the sensors you already have into a **single number: water to apply** — enough to cover crop demand after rain is credited, and not a drop more.

- **Water the plant, not the calendar.** Demand is scaled with a built-in coefficient for 100+ plants (tomato, lawn, grapes, citrus, corn, …). Rain since the last watering and rain still coming is subtracted so you do not irrigate on top of a storm.
- **One POST instead of a spreadsheet.** Controllers, farm software, and scripts send weather and get a volume back. No-code users fill the Input tab and run.
- **Metric or imperial, same field names.** `units: "metric"` is litres, m², mm, °C, hPa. `units: "imperial"` is US gallons, ft², inches, °F, inHg.
- **Honest about missing data.** Wind defaults to 2 m/s, radiation can be estimated from temperature, and every assumption is listed in the response so you can trust the number — or override the coefficient yourself.
- **Built for live irrigation, not a crawl.** Standby keeps the API ready. Each successful `/calculate` is a short request, not a long Actor start.

### How to use Net Zero Watering

1. Open this Actor on Apify.
2. On the **Input** tab, set `units`, wettable area (`canopy_area` or `pot_diameter` — if both are filled, canopy area wins), temperature, humidity, pressure or elevation (sea level is assumed if you skip both), latitude, rainfall, and `plant_type`.
3. Click **Start** — or POST the same JSON to `/calculate` on the Standby URL.
4. Read **`water_to_apply`**. That is litres (metric) or US gallons (imperial). When it is zero, you are already at net zero for this interval.

API example:

```bash
curl -X POST "https://sciguy--evapotranspiration.apify.actor/calculate" \
  -H "Authorization: Bearer <APIFY_TOKEN>" \
  -H "content-type: application/json" \
  -d '{
    "units": "metric",
    "canopy_area": 1.5,
    "tmin": 18,
    "tmax": 30,
    "relative_humidity": 55,
    "pressure": 1013,
    "latitude": 40.0,
    "precip_since_last": 0,
    "precip_forecast_until_next": 2,
    "date": "2026-07-15",
    "plant_type": "tomato"
  }'
```

A classic run writes the same result to the default dataset. Schedule it from a watering controller, a greenhouse dashboard, or a daily check for every zone you manage.

### Input

All quantity field names are **unit-agnostic**. Required `units` is `metric` or `imperial`. You must also send:

- Wettable area: `canopy_area` **or** `pot_diameter`
- Temperature: `temperature` **or** both `tmin` and `tmax`
- `relative_humidity` (0–100)
- `pressure` **or** `elevation` (pressure preferred)
- `latitude`
- `precip_since_last` and `precip_forecast_until_next` (0 is allowed)

Optional: `pressure_type` (`absolute` default, or `sea_level`), `date`, `days_since_last`, `days_until_next`, `wind_speed` (defaults to **2 m/s after conversion**), `wind_height` (metres), `solar_radiation` or `sunshine_hours`, `coastal`, `dewpoint`, `plant_type`, `plant_age_years`, `growth_stage` (`ini` / `mid` / `end`), `kc`.

See the **Input** tab for the Console form.

### Output

You can download the dataset in JSON, HTML, CSV, or Excel. A typical item:

```json
{
  "units": "metric",
  "water_to_apply": 8.41,
  "irrigation_depth": 5.61,
  "eto_per_day": 4.75,
  "etc": 7.61,
  "kc_used": 1.15,
  "kc_source": "lookup",
  "plant_key": "tomato",
  "kc_stage": "mid",
  "precip_credit": 2.0,
  "interval_days": 2,
  "canopy_area": 1.5,
  "assumptions": ["unit system metric", "northern hemisphere growing season … → Kc mid"],
  "fao56": {
    "pressure": 101.3,
    "psychrometric_constant": 0.0674,
    "saturation_vapour_pressure": 2.98,
    "actual_vapour_pressure": 1.64,
    "delta": 0.189,
    "net_radiation": 12.4,
    "wind_2m": 2.0
  }
}
```

`water_to_apply` is litres when `units` is `metric` and US gallons when `imperial`. Depth fields (`irrigation_depth`, `eto_per_day`, `etc`, `precip_credit`) are millimetres or inches. `fao56` is always SI.

### Data table

| Field | Meaning |
| --- | --- |
| `water_to_apply` | Volume to apply (L or US gal) |
| `irrigation_depth` | Depth equivalent of that volume |
| `eto_per_day` | Grass reference demand (FAO-56) |
| `etc` | Crop demand over the watering interval (`kc × ETo × days`) |
| `kc_used` / `kc_source` | Coefficient actually applied (`lookup`, `input`, or `default`) |
| `plant_key` / `kc_stage` | Looked-up plant key and ini/mid/end stage |
| `precip_credit` | Rain already in plus rain forecast |
| `interval_days` | `days_since_last + days_until_next` |
| `fao56` | Penman–Monteith intermediates |

### Pricing / Cost estimation

How much does it cost to water smarter? **$5.00 USD per 1,000 successful calculations** — **$0.005** each time `/calculate` (or a Console run) returns a volume. You are **not billed while the API sits idle**. A backyard controller checking once a day is about half a cent a day. A greenhouse asking once per zone still beats one overwatered crop or a wasted tank of water.

There is no crawl and no long run: each request is a short CPU answer. Set a schedule and only pay when you actually ask how much to apply.

### Tips or Advanced options

- Send **tmin and tmax**, not only mean temperature. FAO-56 vapour pressure is more accurate with the daily range.
- If your weather provider reports **sea-level pressure**, set `pressure_type` to `sea_level` and include `elevation`.
- Airport wind is often **10 m**; set `wind_height` to 10 so it is converted to 2 m.
- `dewpoint`, when you have it, is preferred over relative humidity for actual vapour pressure.
- Pass `growth_stage` (`ini`, `mid`, `end`) if you already know phenology; otherwise the Actor infers it from `date` and `latitude` (northern growing season 1 March–31 October, southern 1 September–30 April).
- `plant_age_years` selects an age bucket 0–10. Those buckets currently copy the same coefficient; age-specific values can replace them later.

### Plant types and Kc

`plant_type` is a **human-readable key**. Variations are separate keys (`onions-dry`, `grapes-wine`, `banana-1st-year`). Common examples:

| Key | Crop | Kc ini | Kc mid | Kc end |
| --- | --- | ---: | ---: | ---: |
| `tomato` | Tomato | 0.60 | 1.15 | 0.80 |
| `lettuce` | Lettuce | 0.70 | 1.00 | 0.95 |
| `potato` | Potato | 0.50 | 1.15 | 0.75 |
| `maize-field-grain-field-corn` | Field corn (also `corn`) | 0.30 | 1.20 | 0.47 |
| `beans-green` | Green beans | 0.50 | 1.05 | 0.90 |
| `watermelon` | Watermelon | 0.40 | 1.00 | 0.75 |
| `strawberries` | Strawberries | 0.40 | 0.85 | 0.75 |
| `turf-grass-cool-season` | Cool-season turf (also `lawn`) | 0.90 | 0.95 | 0.95 |
| `grapes-wine` | Wine grapes | 0.30 | 0.70 | 0.45 |
| `apples-cherries-pears-no-ground-cover-killing-frost` | Apple/cherry/pear, bare ground, frost | 0.45 | 0.95 | 0.70 |

The Actor ships with **100+ keys** (every onion, citrus canopy, and hay-cutting variation). Aliases such as `corn`, `onion`, and `strawberry` map onto those keys. If `plant_type` is omitted or unknown, the coefficient is **0.8**. The full catalog is in **[PLANTS.md](PLANTS.md)**.

### FAQ, disclaimers, and support

**Net Zero Watering** estimates how much water a stand needs so you can irrigate to replace demand, not to flood it. It is not agronomic advice: soil type, drainage, salinity, and irrigation uniformity still matter. Built-in coefficients assume typical well-watered crop stands; they are not a substitute for a local agronomist.

Using the Actor to drive valves or pumps is your responsibility. Respect local water-use rules.

Questions and feature requests: use the Actor **Issues** tab. Custom plant tables, extra weather sources, or a private deployment are available as a custom solution.

# Actor input Schema

## `units` (type: `string`):

Unit system for every quantity in this request and in the response. metric uses litres and m² (depths in mm). imperial uses US gallons and ft² (depths in inches).

## `canopy_area` (type: `number`):

Wettable canopy area. m² if units=metric, ft² if units=imperial. If you also fill pot\_diameter, canopy\_area is used.

## `pot_diameter` (type: `number`):

Pot or canopy diameter used to compute a circular area. m if units=metric, ft if units=imperial. Ignored when canopy\_area is set. Leave empty if you already filled canopy area.

## `temperature` (type: `number`):

Mean air temperature. °C if units=metric, °F if units=imperial. Provide this, or both tmin and tmax.

## `tmin` (type: `number`):

Daily minimum temperature. °C if units=metric, °F if units=imperial.

## `tmax` (type: `number`):

Daily maximum temperature. °C if units=metric, °F if units=imperial.

## `relative_humidity` (type: `number`):

Mean relative humidity (%).

## `pressure` (type: `number`):

Barometric pressure. hPa if units=metric, inHg if units=imperial. Preferred over elevation. If both pressure and elevation are empty, elevation is treated as sea level (0).

## `pressure_type` (type: `string`):

absolute is station pressure at the plant. sea\_level is the reduced sea-level value many weather APIs send; that option also requires elevation.

## `elevation` (type: `number`):

Site elevation above sea level. m if units=metric, ft if units=imperial. Used to estimate pressure, or to reduce sea-level pressure to station pressure.

## `latitude` (type: `number`):

Site latitude in decimal degrees (north positive). Needed to estimate solar radiation when solar\_radiation is omitted.

## `precip_since_last` (type: `number`):

Rain already received since the last watering. mm if units=metric, inches if units=imperial. 0 is allowed.

## `precip_forecast_until_next` (type: `number`):

Rain expected before the next watering. mm if units=metric, inches if units=imperial. 0 is allowed.

## `date` (type: `string`):

Date for solar geometry (YYYY-MM-DD). Defaults to today UTC.

## `days_since_last` (type: `number`):

Days of evapotranspiration already accumulated since the last watering.

## `days_until_next` (type: `number`):

Days until the next planned watering.

## `wind_speed` (type: `number`):

Wind speed. m/s if units=metric, mph if units=imperial. Defaults to the FAO-56 standard of 2 m/s after conversion.

## `wind_height` (type: `number`):

Height of the wind sensor above the surface, always in metres. Airport and OpenWeather winds are often 10 m.

## `solar_radiation` (type: `number`):

Incoming shortwave solar radiation. MJ m⁻² day⁻¹ if units=metric, Langley/day if units=imperial. Estimated from temperature when omitted.

## `sunshine_hours` (type: `number`):

Bright sunshine duration in hours. Used to estimate solar radiation when solar\_radiation is omitted.

## `coastal` (type: `boolean`):

Set true if air masses are influenced by a nearby large water body. Only used when solar radiation is estimated from temperature.

## `dewpoint` (type: `number`):

Dewpoint temperature (°C metric, °F imperial). Preferred over relative humidity for actual vapour pressure.

## `plant_type` (type: `string`):

Plant key from the bundled Kc table, e.g. tomato, onions-dry, turf-grass-cool-season. See PLANTS.md for the full list. Unknown or omitted keys use Kc 0.8.

## `plant_age_years` (type: `number`):

Selects an age bucket 0–10 in the Kc table. Buckets currently copy the same Kc; age-specific values can replace them later.

## `growth_stage` (type: `string`):

Override growth stage (ini / mid / end). If omitted, inferred from date and latitude.

## `kc` (type: `number`):

Override crop coefficient. When set, plant\_type lookup is skipped.

## Actor input object example

```json
{
  "units": "metric",
  "canopy_area": 1.5,
  "tmin": 18,
  "tmax": 30,
  "relative_humidity": 55,
  "pressure": 1013,
  "pressure_type": "absolute",
  "latitude": 40,
  "precip_since_last": 0,
  "precip_forecast_until_next": 0,
  "days_since_last": 1,
  "days_until_next": 1,
  "wind_height": 2,
  "coastal": false,
  "plant_type": "tomato"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "units": "metric",
    "canopy_area": 1.5,
    "tmin": 18,
    "tmax": 30,
    "relative_humidity": 55,
    "pressure": 1013,
    "latitude": 40,
    "plant_type": "tomato"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sciguy/evapotranspiration").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "units": "metric",
    "canopy_area": 1.5,
    "tmin": 18,
    "tmax": 30,
    "relative_humidity": 55,
    "pressure": 1013,
    "latitude": 40,
    "plant_type": "tomato",
}

# Run the Actor and wait for it to finish
run = client.actor("sciguy/evapotranspiration").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "units": "metric",
  "canopy_area": 1.5,
  "tmin": 18,
  "tmax": 30,
  "relative_humidity": 55,
  "pressure": 1013,
  "latitude": 40,
  "plant_type": "tomato"
}' |
apify call sciguy/evapotranspiration --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sciguy/evapotranspiration"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/JObaVZ7H13KkNkfvW/builds/RJpL8dMjWogYq81WR/openapi.json
