# info.summary
Lawn-care data endpoints and Markdown page access for whatgrassisthis.com.

# info.description
Public, unauthenticated, read-only endpoints behind the What Grass Is This tools and widgets: soil temperature, weather, and rainfall by US ZIP code, US location lookup, regional lawn guidance, the lawn-plan engine vocabulary, and a Markdown rendering of any page for agents. No API key. Every operation is rate limited per client IP per minute (see each operation `x-rate-limit` extension and 429 response; limits range from 30 to 120 per minute, plus an aggregate budget of 300 requests per minute across all endpoints). Exceeding a limit returns HTTP 429 with Retry-After and X-RateLimit-* headers. Heavier sustained use should contact support@whatgrassisthis.com first. Endpoints are US-only. Every JSON failure carries the Error schema; the `code` field is present on the soil-temperature operations and on routing errors, and other endpoints return `error` alone. Only `/api/soil-temperature` sends CORS headers, so call the rest server-side. Grass identification from a photo is not exposed here; send users to https://whatgrassisthis.com/ or the iOS app.

# tags[].description
Weather and rainfall used by the lawn tools

# tags[].description
Regional lawn guidance and engine reference data

# paths./api/markdown.get.description
Returns the main content of a whatgrassisthis.com page as Markdown (headings, text, lists, tables, links). Equivalent to sending `Accept: text/markdown` to the page URL itself, which is the preferred form. Only real page paths are accepted; API routes, Next internals, auth-gated surfaces, embeds, and files with extensions return 400. A nonexistent page returns 404 with a Markdown body of recovery links. Rate limit: 30 requests per 60 seconds per client IP, shared across /api/markdown.

# paths./api/markdown.get.parameters[].description
Site-relative page path, optionally with a query string, e.g. `/guides/bermudagrass`.

# paths./api/markdown.get.responses.200.headers.Link.description
Points at the HTML representation: `<url>; rel="alternate"; type="text/html"`.

# paths./api/markdown.get.responses.404.description
No page at that path. Body lists recovery links.

# paths./api/markdown.get.responses.413.description
Page HTML exceeds the 5 MB conversion limit.

# paths./api/soil-temperature.get.summary
Soil temperature series for a US location

# paths./api/soil-temperature.get.description
Daily 6-inch soil temperature (°F) for a US location, from 30 days back to 16 days ahead by default, with a 5-day rolling average and the current trend. Backed by Open-Meteo. Provide exactly one of `zip`, `query`, or `lat`+`lon`. Sends CORS headers, so it can be called from a browser. Use it to time pre-emergent herbicide (target 55 °F sustained) and seeding windows. Rate limit: 60 requests per 60 seconds per client IP, shared across /api/soil-temperature.

# paths./api/soil-temperature.get.parameters[].description
Five-digit US ZIP code. Provide exactly one of `zip`, `query`, or `lat`+`lon`.

# paths./api/soil-temperature.get.parameters[].description
Free-text US place, e.g. `Dallas, TX`. Alternative to `zip`.

# paths./api/soil-temperature.get.parameters[].description
Latitude in decimal degrees (-90..90). Requires `lon`.

# paths./api/soil-temperature.get.parameters[].description
Longitude in decimal degrees (-180..180). Requires `lat`.

# paths./api/soil-temperature.get.parameters[].description
Start of the series (YYYY-MM-DD). Default: today minus 30 days.

# paths./api/soil-temperature.get.parameters[].description
End of the series (YYYY-MM-DD). Default: today plus 16 days. Span may not exceed 400 days.

# paths./api/soil-temperature.get.responses.400.description
Missing or invalid location, unknown ZIP, or date span over 400 days. `code` is one of missing_location, invalid_zip_format, zip_not_found, location_not_found, invalid_coordinates, date_range_too_long.

# paths./api/soil-temperature.get.responses.500.description
Weather upstream unavailable (`code`: weather_upstream_unavailable) or server error.

# paths./api/soil-temperature/historical-avg.get.summary
Multi-year daily soil temperature averages

# paths./api/soil-temperature/historical-avg.get.description
Day-of-year average, minimum, and maximum 6-inch soil temperature (°F) over the last 5 or 10 years for a US location. Useful for planning a season before live forecasts exist. Provide exactly one of `zip`, `query`, or `lat`+`lon`. Rate limit: 60 requests per 60 seconds per client IP, shared across /api/soil-temperature.

# paths./api/soil-temperature/historical-avg.get.parameters[].description
Five-digit US ZIP code. Provide exactly one of `zip`, `query`, or `lat`+`lon`.

# paths./api/soil-temperature/historical-avg.get.parameters[].description
Free-text US place, e.g. `Dallas, TX`. Alternative to `zip`.

# paths./api/soil-temperature/historical-avg.get.parameters[].description
Latitude in decimal degrees (-90..90). Requires `lon`.

# paths./api/soil-temperature/historical-avg.get.parameters[].description
Longitude in decimal degrees (-180..180). Requires `lat`.

# paths./api/soil-temperature/historical-avg.get.responses.400.description
Invalid `years` (`code`: invalid_years) or missing/invalid location.

# paths./api/soil-temperature/historical-avg.get.responses.500.description
Historical upstream unavailable or server error.

# paths./api/soil-temperature/national.get.summary
Current soil temperature grid for the contiguous US

# paths./api/soil-temperature/national.get.description
A grid of current 6-inch soil temperature points (°F) across the US, refreshed by a scheduled job roughly hourly. No parameters. Powers the national soil temperature map. Rate limit: 60 requests per 60 seconds per client IP, shared across /api/soil-temperature.

# paths./api/soil-temperature/national.get.responses.503.description
The grid has not been generated yet; retry later.

# paths./api/weather.get.summary
Current conditions and 7-day forecast for a ZIP code

# paths./api/weather.get.description
Current temperature, humidity, and precipitation plus a 24-hour and 7-day forecast for a US ZIP code, in °F and inches. Responses are cached per 3-digit ZIP prefix, so nearby ZIP codes share a regional answer. Rate limit: 60 requests per 60 seconds per client IP, shared across /api/weather.

# paths./api/weather.get.responses.400.description
ZIP is not five digits or is not a known US ZIP.

# paths./api/rainfall.get.summary
Rainfall over the last 7 days for a ZIP code

# paths./api/rainfall.get.description
Total rainfall in inches and the number of rainy days over the past week for a US ZIP code. Never fails on upstream trouble; `source` says whether the numbers are live, cached, or a zero fallback. Use it to decide whether a lawn needs watering this week. Rate limit: 60 requests per 60 seconds per client IP, shared across /api/rainfall.

# paths./api/location/zip.get.description
Local (no upstream) lookup of a five-digit US ZIP code to its city, state, coordinates, and time zone. Rate limit: 120 requests per 60 seconds per client IP, shared across /api/location.

# paths./api/location/reverse.get.description
Local reverse geocode from latitude/longitude to the nearest US ZIP code with its city and state. US only. Rate limit: 120 requests per 60 seconds per client IP, shared across /api/location.

# paths./api/location/search.get.description
Resolves a ZIP code, `City, ST`, `City ST`, or a bare city name to a ZIP code with city and state. When a bare city name is matched, `hint` says which place was chosen. Rate limit: 120 requests per 60 seconds per client IP, shared across /api/location.

# paths./api/location/search.get.parameters[].description
ZIP code or place text, at least 2 characters.

# paths./api/regional-info.get.summary
Lawn region and common grasses for a ZIP code

# paths./api/regional-info.get.description
Maps a US ZIP code to its lawn region (for example "Cool Season North"), a climate label, and the grass species commonly grown there. Static lookup, no upstream call. Note the parameter is `zipCode`, not `zip`. Rate limit: 120 requests per 60 seconds per client IP, shared across /api/regional-info.

# paths./api/lawn-engine/reference.get.summary
Vocabulary and formulas of the lawn-plan engine

# paths./api/lawn-engine/reference.get.description
The grass types, aliases, sunlight bands, lawn-size buckets, and the fertilizer and watering formulas the site's deterministic care-plan engine uses, with the version string. Read this first when translating a user's words into the site's terms. Rate limit: 60 requests per 60 seconds per client IP, shared across /api/lawn-engine.

# components.schemas.Error.description
Error envelope for every JSON failure. `error` is always present. `code`, `message`, `hint`, `docs`, and `status` are present on routing errors (unknown paths) and soil-temperature operations; older endpoints send `error` alone.

# components.schemas.Error.properties.error.description
Machine-readable code when `code` is present, otherwise a short message.

# components.schemas.Error.properties.details.description
Optional structured detail, e.g. validation issues.

# components.schemas.SoilTemperatureSeries.properties.current.properties.avg5d.description
5-day rolling average; null until enough days exist.

# components.schemas.ResolvedLocation.description
City, state, coordinates, and time zone for a ZIP code.

# components.schemas.PlaceMatch.properties.hint.description
Present when a bare city name was matched to a specific place.

# components.responses.RateLimited.description
Per-IP rate limit exceeded for this endpoint family. Wait Retry-After seconds. Body is the Error schema with code `rate_limited` (JSON), or a Markdown notice on `/api/markdown`.

# components.responses.RateLimited.headers.X-RateLimit-Reset.description
Unix time (seconds) when the window resets.

# components.responses.RateLimited.headers.X-RateLimit-Policy.description
`<limit>;w=<window seconds>`.