# AgKit.io Services

A unified GeoJSON gateway for public soil, agriculture, hydrology,
weather, infrastructure, and political data. 36 endpoints across five
categories; every endpoint returns a standards-compliant GeoJSON
FeatureCollection. AgSci's PostGIS warehouse plus best-of-breed US
Government ESRI services, behind one host.

## URL schema

All data endpoints accept either:

- `?extent=xmin,ymin,xmax,ymax` (a bounding envelope), or
- `?wkt=<WKT geometry>` (a POINT, POLYGON, or MULTIPOLYGON).

Coordinates are EPSG:4326 (lon, lat). A few weather and forecast routes
take per-station parameters instead — see the OpenAPI spec.

## Categories

- **Soils** — SSURGO map units + yields, USDA Common Land Units,
  detected crop boundaries, Cropland Data Layer with an XGBoost
  rotation predictor, geometry helpers.
- **Hydrology** — NWI wetlands, FEMA flood hazards + FIRM panels
  (vector / raster / MVT), USGS Watershed Boundary Dataset HUC-12
  subwatersheds.
- **Weather** — NWS gridpoint + forecast (no API key required).
- **Infrastructure** — Transmission lines, substations, wind farms,
  individual wind turbines.
- **Political** — County / state / county-subdivision (Census), HUD
  opportunity zones, PLSS townships + ranges + sections.

## MCP connector

An agent can use this gateway as a tool surface instead of composing URLs.
It speaks the Model Context Protocol over streamable HTTP at:

    https://services.agkit.io/mcp/<bypass-token-key>/

The token is the path segment because connector UIs have no field for a
request header, and the trailing slash is required. Four tools, so that
seventy datasets are not forty pages of your context: `list_datasets` for
what this token can reach, `describe_dataset` for the parameter contract
and the semantic caveats, then `fetch` for the geometry-addressed
datasets and `adm_query` for the tabular RMA crop-insurance ones.

The two kinds meet at county FIPS. `fetch('get-county', wkt='POINT(lon
lat)')` gives you STATEFP and COUNTYFP for a location; joined into a
5-digit FIPS, that is what every `adm_query` dataset is keyed by — so a
field boundary leads to its yields, prices, and premiums.

Discovery is free. Only `fetch` and `adm_query` cost anything, and each
costs exactly what the REST call behind it costs — same entitlement, same
rate, same usage record. Ask for a token at the contact below.

## Reference (machine-readable)

- [OpenAPI 3 spec](/openapi.json) — authoritative surface description.
- [Swagger UI](/docs) — interactive, per-endpoint example calls.
- [/pricing](/pricing) — human-readable rate card (per-call tiers +
  full per-endpoint pricing, live from the x402 catalog).
- [/.well-known/x402](/.well-known/x402) — marketplace + payment
  discovery.
- [Showcase JSONs](/static/showcase/) — pre-baked example responses for
  the demo AOI in Champaign Co., IL.

## Worked examples

Soils within an envelope:

    GET /ssurgo?extent=-88.456,40.145,-88.450,40.151

Returns a GeoJSON FeatureCollection of soil mapunits with NCCPI ratings,
water-holding capacity by depth, drainage class, and other agronomic
properties.

HUC-12 subwatershed for a point:

    GET /watersheds/huc12?wkt=POINT(-88.453 40.148)

NWS forecast for a point:

    GET /weather/forecast/at?wkt=POINT(-88.453 40.148)

## Access

Call an endpoint. If it is open, you get data. If it is gated, you get
`402 Payment Required` carrying a `PAYMENT-REQUIRED` header that quotes an
exact price, recipient, chain, and asset. Pay it and repeat the request with
the signed authorization; the gateway verifies, serves, and settles on-chain,
returning the settlement tx hash in `X-PAYMENT-RESPONSE`.

There is no signup, no API key, and no human in the loop.

No endpoint is gated right now: every endpoint is open, and a
call returns data with no credential and no payment. Calls are metered
but not billed. When a product group is given an income wallet, its
endpoints begin answering unpaid callers with the 402 challenge below,
and they appear in this list and in `/.well-known/x402`. Code written
against the flow below keeps working when that happens.

### Paying with x402 (Python)

    pip install "x402>=2.13.1" eth-account httpx

The client wrapper handles the whole round trip: it catches the 402, signs a
gasless EIP-3009 USDC authorization for the quoted amount, and replays the
request. You never construct the payment header yourself.

    import asyncio
    import httpx
    from eth_account import Account
    from x402 import SchemeRegistration, x402ClientConfig
    from x402.http.clients import wrapHttpxWithPaymentFromConfig
    from x402.mechanisms.evm.exact import ExactEvmScheme
    from x402.mechanisms.evm.signers import EthAccountSigner

    BASE = "https://services.agkit.io"

    async def main():
        # Read the chain + asset straight from discovery rather than
        # hardcoding them; they change without notice.
        async with httpx.AsyncClient() as probe:
            disco = (await probe.get(f"{BASE}/.well-known/x402")).json()
        network = disco["access"]["x402"]["network"]

        account = Account.from_key("0x<YOUR_FUNDED_PRIVATE_KEY>")
        config = x402ClientConfig(schemes=[
            SchemeRegistration(
                network=network,
                client=ExactEvmScheme(signer=EthAccountSigner(account)),
            )
        ])

        async with wrapHttpxWithPaymentFromConfig(config, timeout=60.0) as client:
            r = await client.get(
                f"{BASE}/ssurgo",
                params={"extent": "-88.456,40.145,-88.450,40.151"},
            )
            r.raise_for_status()
            print(r.json()["features"][0]["properties"])

    asyncio.run(main())

Your wallet must hold USDC on `eip155:84532` (asset `0x036CbD53842c5426634e7929541eC2318f3dCF7e`) plus nothing
else — settlement is gasless, so you do not need the chain's native token.
Prices are per call, typically $0.002–$0.01; see the
[rate card](https://x402.agkit.io/api/v1/catalog/public/?tenant=agsci).

An unpaid probe costs nothing and tells you the price:

    curl -sD- "https://services.agkit.io/ssurgo?extent=-88.456,40.145,-88.450,40.151"
    # HTTP/1.1 402 Payment Required
    # payment-required: <base64 challenge>
    # {"accepts": [{"scheme": "exact", "amount": "5000", "payTo": "0x...",
    #               "network": "eip155:84532", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"}], ...}

`amount` is in the asset's base units — `"5000"` is 0.005 USDC at 6 decimals.

### Prepaid access (bypass token)

If you would rather settle out of band, we issue long-lived bearer tokens
that entitle a consumer to a set of endpoints:

    curl -H "Authorization: Bearer <token>" "https://services.agkit.io/ssurgo?extent=..."

A bypass token always wins over the payment gate: a gated endpoint serves a
permitted token holder directly and never charges them. Email
<info@soildiagnostics.com> to get one.

## Anonymous probes

These routes stay open with no auth, for liveness and capability checks:

    GET /                -> HTML landing
    GET /about           -> JSON heartbeat
    GET /openapi.json    -> OpenAPI 3 spec
    GET /docs            -> Swagger UI
    GET /llms.txt        -> this file
    GET /.well-known/x402 -> marketplace discovery

## Contact

<info@soildiagnostics.com>
