Join the waitlist
Get started

Provenance-tagged agricultural intelligence for any crop, anywhere.

Pestren answers agronomic questions for any crop at any coordinate on earth — and every value it returns carries its source, a timestamp, a calibrated confidence, and a three-tier verification tag.

What you get

Three surfaces share one field catalog and one provenance model, so an answer, a raw field, and an agent tool call all cite the same ground truth:

  • POST /v1/ask — natural-language question in, a cited answer + recommended action out.
  • POST /v1/fetch — deterministic raw fields or presets, each provenance-wrapped, with a partial_failures contract.
  • MCP serverpestren_ask and pestren_fetch native to any MCP-aware model.

Plus drop-in Skills (agronomy files an agent loads) and a public Benchmark playground.

Why it's different

Global authoritative sources

FAO, ESA Sentinel, NASA, SoilGrids, CABI, national ag departments — never a proprietary "AI-derived" number.

Per-field citations + 3 tiers

Every field ships its source_url and a literature / field-verified / lab-confirmed tag.

MCP-native distribution

Drop the tools into any agent loop; citations flow through like any other tool call.

Honest partial failures

Anything we can't fetch surfaces in partial_failures with a retryable flag — never a silent default.

Coverage

Global. Latitude [-60, 75], longitude [-180, 180]; out-of-bounds returns 400 coord_out_of_bounds. Any crop; verification depth grows region by region. 220+ fields across 7 layers; 12 presets — browse the full catalog at GET /v1/meta/fields.

What's next

Get started

Quickstart

Make your first /v1/ask call and read a cited answer in five minutes.

1 · Get a token

Grab an API token from your dashboard (see Authentication) and export it:

shell
export PESTREN_API_TOKEN="sk_live_…"

2 · Ask a question

curlPythonMCP
request.sh
curl -s https://api.pestren.com/v1/ask \
  -H "Authorization: Bearer $PESTREN_API_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"lat": 4.57, "lng": -75.66,
       "question": "Coffee leaf rust risk here this week — should I act?"}'
example.py
import os, requests
r = requests.post(
    "https://api.pestren.com/v1/ask",
    headers={"Authorization": f"Bearer {os.environ['PESTREN_API_TOKEN']}"},
    json={"lat": 4.57, "lng": -75.66,
          "question": "Coffee leaf rust risk here this week?"},
)
print(r.json()["answer"], r.json()["confidence"])
claude-code
# after installing the MCP server
/pestren_ask lat=4.57 lng=-75.66 \
  question="Coffee leaf rust risk here this week?"

3 · Read the response

You get a prose answer, an overall confidence bucket (high/medium/low), a citations[] array (one entry per source, each with a source_url, fetched_at, and verification tier), the fields_used[] that grounded the answer, and an optional recommended_action.

Every claim in the prose maps back to a citation a field officer can open. If a driver field couldn't be fetched, it appears in partial_failures — the answer is never silently padded.

Get started

Authentication

Three ways in — all bearer-token based. The public catalog needs no auth.

Dashboard API token

Copy a token from your account and send it as a bearer header on every call. Tokens are only accepted over https (with a loopback exception for local development).

header
Authorization: Bearer <PESTREN_API_TOKEN>

Device-flow login

For CLIs and local MCP, run a one-time browser login that stores a credential file:

shell
pestren-mcp login   # opens a browser, writes ~/.pestren/credentials

MCP OAuth

Remote MCP clients authenticate against the hosted endpoint https://api.pestren.com/mcp via OAuth — no token pasting.

Rotate & revoke

Rotate tokens from the dashboard; revoked tokens fail immediately with 401 unauthorized. Scope tokens per environment and never commit them.

GET /v1/meta/fields and GET /v1/meta/presets are public — no bearer required — so you can explore the catalog before you sign up.

Concepts

Field catalog & layers

Every value Pestren returns belongs to one of seven layers, plus a derived actions block. Here are representative fields per layer.

LayerRepresentative fields
cropcrop, crop_confidence, growth_stage, season, sowing_window
soilsoil_texture, soil_ph, soil_organic_carbon, soil_drainage
waterrainfall_7d, rainfall_30d, et0, soil_moisture, irrigation_need
weathertemp_min, temp_max, humidity, gdd, forecast_7d
pest & diseasepest_risk, disease_risk, primary_threat, risk_drivers
yieldndvi_current, ndvi_trend, biomass_estimate, yield_estimate, yield_risk
boundaries/terrainfield_polygon, field_area_ha, elevation, slope_degrees
actions (derived)recommended_action, recommended_products

Every value ships inside a Field_[T] wrapper carrying its provenance — see Provenance & confidence.

Concepts

Provenance & confidence

Two things that must never be conflated: the per-field verification tier and the per-answer confidence.

The provenance envelope

Every field is returned wrapped, not as a bare value:

Field_[T]
{
  "value": 74,
  "unit": "risk_index_0_100",
  "source": "FAO FAW-Monitor",
  "source_url": "https://…",
  "confidence": "field-verified",   // verification tier
  "fetched_at": "2026-07-01T06:12Z",
  "dataset_vintage": "2026-W26",
  "ttl_seconds": 86400,
  "notes": "warm nights + rainfall on whorl-stage maize"
}

The 3-tier verification ladder

TierMeansWhen it applies
literaturePublished model or dataset only.New region/crop with no on-ground sample yet.
field-verifiedConfirmed on the ground this season/region.Where Pestren's verification network has coverage.
lab-confirmedValidated by a lab diagnosis.Disease/pest ID escalated to a partner lab.

Answer calibration

An /v1/ask answer gets one overall high / medium / low, derived from three signals:

  • Field coverage — how many of the fields the question needed were actually fetched.
  • Tier mix — whether driver fields are field-verified/lab-confirmed or only literature.
  • Cross-source agreement — whether independent sources corroborate.

A downgrade fires when a key field returns only literature tier, or a partial_failure hits a driver field. Confidence is a promise about the evidence, not the prose.

Concepts

Presets

Named field bundles for common jobs. Pass preset instead of enumerating fields[].

PresetBest for
pest_riskThis week's pest pressure + drivers.
disease_riskDisease pressure + primary threat.
irrigation_planSoil moisture, ET0, rainfall, irrigation need.
soil_healthTexture, pH, organic carbon, drainage.
yield_forecastNDVI trend, biomass, yield estimate + risk.
crop_verifyCrop, growth stage, sowing window.
precision_scoutingRisk polygons + NDVI for fleet tasking.
insurance_underwriteCrop, sowing, flood/drainage, yield risk.
lending_collateralCrop, acreage, NDVI trend, yield-risk band.
climate_riskAggregated climate-hazard exposure.

There's a per-call field cap. If a preset exceeds it, fields are truncated in catalog order and the omission is reported in notes. Browse presets at GET /v1/meta/presets.

Concepts

Skills

Drop-in agronomy files an agent loads to reason about a crop or a practice — reusable across models and stacks.

What a skill is

A self-contained file describing an entity's agronomy: stages, thresholds, the sources behind them, and a verification tier. The agent reads the skill for reasoning; it calls /v1/fetch for live values.

skills/
skills/
  crop.coffee.skill.md        # agronomy, stages, thresholds, sources, tier
  crop.maize.skill.md
  practice.irrigation.md      # reusable across crops
  practice.disease-scouting.md

Schema

Each skill declares an entity, its stages, decision thresholds, the sources that back them, and a default verification tier. Load it in Claude/GPT skills or a custom stack.

Skills + /v1/fetch compose: the skill is the reasoning layer, fetch is the live-values layer. Together they give an agent grounded judgment instead of guesses.

Concepts

Benchmarking

Run any farm question at any coordinate and see Pestren scored against other models. A first-class, public feature.

What it does

Each model is scored on four axes and rolled into a single number:

AxisChecked by
groundedAre claims tied to fetched field values (not priors)?
citedDoes each claim carry an openable source_url?
freshAre values within their ttl for this week/coordinate?
actionableDoes the answer end in a concrete next step?

Programmatic access

Run the same rubric in CI over your own prompts:

request.sh
curl -s https://api.pestren.com/v1/eval \
  -H "Authorization: Bearer $PESTREN_API_TOKEN" \
  -d '{"lat": 47.3, "lng": 8.5,
       "question": "Late-blight risk for potato this week?",
       "models": ["pestren","gpt-5","gemini","claude"]}'

Returns a per-model, per-axis scored comparison. Open the hosted playground →

API reference
Coming Soon
API reference

POST /v1/fetch

The developer escape hatch — deterministic, provenance-wrapped fields with no LLM in the loop.

Request

lat / lngnumberrequired

Coordinate within global bounds.

fields[]string[]one of

Explicit catalog field ids.

presetstringone of

A named bundle (see Presets).

Worked example — irrigation_plan, maize in Kenya

200 · response.json
{
  "fields": {
    "soil_moisture": { "value": 0.18, "unit": "m3/m3",
        "source": "NASA SMAP", "confidence": "field-verified" },
    "et0":           { "value": 5.1,  "unit": "mm/day", "source": "NASA POWER" },
    "rainfall_7d":   { "value": 6,    "unit": "mm",     "source": "ERA5" },
    "irrigation_need":{ "value": "moderate", "confidence": "literature" },
    "growth_stage":  { "value": "whorl", "confidence": "field-verified" }
  },
  "partial_failures": []
}

The honesty pattern

When a source can't be reached, the field is not silently defaulted — it lands in partial_failures with a retryable flag:

partial_failures
"partial_failures": [
  { "field": "ndvi_current", "error": "cloudy_sentinel_pass",
    "retryable": true }
]

Batch / polygon: fetch for a resolved field_polygon to aggregate over the parcel, or a bare point for a single sample. In unverified regions a field's tier may drop to literature — always reported, never hidden.

API reference

GET /v1/meta/fields

The public catalog — no auth. Every field, described.

Returns each field's id, layer, unit, description, default source, typical confidence tier, and ttl_seconds. Companion endpoint GET /v1/meta/presets lists the bundles.

200 · response.json
{
  "fields": [
    { "id": "disease_risk", "layer": "pest_disease",
      "unit": "risk_index_0_100", "source": "CABI PlantwisePlus",
      "confidence": "literature", "ttl_seconds": 86400,
      "description": "Weekly disease pressure for the resolved crop." }
  ]
}
API reference

Field catalog

The browsable table of every field by layer — generated from /v1/meta/fields so docs never drift from the API.

FieldLayerUnitTypical tier
cropcroplabelfield-verified
growth_stagecroplabelfield-verified
soil_phsoilpHliterature
soil_drainagesoilclassliterature
rainfall_7dwatermmfield-verified
et0watermm/dayfield-verified
humidityweather%field-verified
disease_riskpest & disease0–100literature
ndvi_currentyieldindexfield-verified
yield_riskyieldbandliterature
field_polygonboundariesgeojsonfield-verified
recommended_actionactionstextderived

This is an excerpt. The live table renders all 220+ fields from the public catalog endpoint.

API reference

Errors

HTTP errors, the non-error partial_failures contract, and the crop_unsupported soft-fallback.

StatusCodeMeaning
400coord_out_of_boundslat/lng outside global bounds.
401unauthorizedMissing/invalid/revoked token.
403quota_exceededPlan quota reached.
404unknown_field / unknown_presetNot in the catalog.
422validation_errorBad body; see detail[].
429rate_limitedToo many requests; back off.
500internalSomething broke on our side.

partial_failures (not an error)

A 200 can still carry per-field failures — each with an error and a retryable flag. Treat it as data, not an exception.

crop_unsupported soft-fallback

For an unsupported crop, Pestren answers generically, drops tier to literature, and flags it in notes rather than failing the call.

MCP

Installation

Wire Pestren into any MCP-aware agent. Server name com.pestren/agri.

Hosted (OAuth) — Claude Code

shell
claude mcp add --transport http pestren https://api.pestren.com/mcp
# then run /mcp in Claude Code and complete the browser login

Local stdio fallback

A slim adapter (no GDAL) for Claude Desktop, Cursor, or custom clients:

shell
uvx pestren-mcp            # run the server
pestren-mcp login          # or set PESTREN_BEARER_TOKEN

Config blocks

claude_desktop_config.json / cursor
{ "mcpServers": {
    "pestren": { "command": "uvx", "args": ["pestren-mcp"] }
} }

If uvx isn't on your client's PATH, use its absolute path (e.g. ~/.local/bin/uvx) in command.

Environment variables

VarPurpose
PESTREN_BASE_URLOverride the API base (default https://api.pestren.com).
PESTREN_BEARER_TOKENToken instead of device login.
PESTREN_TIMEOUT_SPer-call timeout; raise on cold start.
MCP

Tools, resources & prompts

Two tools, three resources, four prompts — results are the verbatim /v1 JSON.

Tools

  • pestren_ask(lat, lng, question[, crop]) — mirrors /v1/ask.
  • pestren_fetch(lat, lng, fields|preset) — mirrors /v1/fetch.

Resources

  • pestren://catalog/fields
  • pestren://catalog/presets
  • pestren://catalog/coverage

Prompts

pestren_grower_report · pestren_pest_check · pestren_irrigation_plan · pestren_pick_fields — each exposed as a slash command in Claude Code.

MCP

Troubleshooting

Smoke-test with MCP Inspector, then fix the usual suspects.

You should see two tools, three resources, and prompts visible — and a passing pestren_ask and pestren_fetch call returning provenance-wrapped JSON.
Confirm PESTREN_BASE_URL has no trailing slash and the token is exported in the same shell that launches the client. For hosted OAuth, re-run /mcp to refresh the grant.
First call after idle can exceed the default timeout — raise PESTREN_TIMEOUT_S (e.g. to 30).
Use cases

Grower advisory

A grower or agronomist asks pest / irrigation / yield questions in language and gets a cited answer, an action, and optional products.

Query

"Coffee at 4.57, -75.66 — leaf rust risk this week, and should I irrigate?"

Response & audit trail

A grounded answer + recommended_action, every claim citing CABI / Sentinel / NASA with tiers a field officer can re-open.

Why it works

The planner pulls the disease and water layers for the exact coordinate — not generic advice.

What it does NOT do: it's not a spray prescription of record, not a geocoder (you resolve address → lat/lng), and not a live pest-trap feed — add those alongside if you need them.

Use cases

Insurance underwriting

Verify crop, sowing window, flood/drainage exposure, and yield-risk with per-field citations an adjuster or regulator can re-fetch.

Query

"Verify crop, sowing window, and flood exposure for this parcel to settle a claim."

Why it works

Use the insurance_underwrite preset; every figure is sourced and audit-trailed with a fetched_at.

What it does NOT do: Pestren is not a CAT model — it returns the inputs; the carrier scores.

Use cases

Agri-lending & collateral

Crop, acreage, NDVI trend, and a yield-risk band as sourced collateral evidence — reproducible at loan time.

Why it works

The lending_collateral preset returns an independent, citable read on the standing crop and its trajectory.

What it does NOT do: it's evidence, not a credit decision — your model does the underwriting.

Use cases

Robotics & sensor builders

/v1/fetch as training data and risk polygons to task fleets and calibrate models. Your detections flow back as ground truth.

Why it works

Sourced field priors reduce false positives; the precision_scouting preset returns polygons to fly.

What it does NOT do: not a replacement for on-board perception — it's the sourced prior.

Use cases

Government & policy

Aggregate crop maps and climate-risk zones for scheme targeting and policy modeling — every figure sourced.

Why it works

Fetch across a district's parcels with the climate_risk preset; provenance makes the aggregate defensible.

What it does NOT do: not real-time event feeds — pair with live gauge/trap APIs for hazard nowcasting.

Use cases

Building agents

Drop the MCP tools + Skills into an agent loop; let the planner pick fields; keep citations flowing through tool calls.

Sample transcript

agent.log
user → Is my rice at 21.94, 87.75 at risk this week?
agent → pestren_ask(lat=21.94, lng=87.75,
             question="pest/disease risk this week for rice?")
tool → { answer, confidence:"high", citations:[…], recommended_action }
agent → Elevated stem-borer pressure — scout now. (FAO, Sentinel ↗)

Load a crop.rice.skill.md alongside the tools so the agent reasons with the right thresholds, then fetches live values.

Copied