# sentbot agent guide

sentbot sells Copernicus Sentinel-2 and Sentinel-1 imagery and analysis per request. Prices are a few cents in USDC, paid with the x402 protocol on Base, Polygon, Arbitrum, Avalanche, Sei. This page is written for AI agents and developers. The same content is at https://sentbot.fly.dev/llms-full.txt.

## 1. Pay

Every paid endpoint returns HTTP 402 when no payment is attached. The response body and the `PAYMENT-REQUIRED` header hold the x402 payment requirements (amount in USDC atomic units, pay-to address, network, validity window). Each paid response lists one offer per network (`eip155:8453` Base, `eip155:137` Polygon, `eip155:42161` Arbitrum, `eip155:43114` Avalanche, `eip155:1329` Sei); pay on whichever one your wallet holds USDC on. An x402 client signs a USDC transfer (EIP-3009 on EVM chains, a token transfer on Solana) and retries with a `PAYMENT-SIGNATURE` header. The server verifies and settles it through a facilitator, then returns the product. Nothing is charged if the product fails.

TypeScript (viem + @x402/fetch):

```ts
import { privateKeyToAccount } from "viem/accounts";
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const client = new x402Client().register("eip155:*", new ExactEvmScheme(account)); // any EVM chain listed above
const fetchWithPay = wrapFetchWithPayment(fetch, client);

const res = await fetchWithPay("https://sentbot.fly.dev/v1/analyze?index=ndvi&bbox=13.35,52.48,13.45,52.55&date=2025-07-15");
const analysis = await res.json();
console.log(analysis.stats.mean, analysis.stats.classes);
```

Solana: add `@x402/svm` and `.register("solana:*", new ExactSvmScheme(signer))` with a Solana keypair signer. The receiving wallet already holds a USDC account.

Python: use the `x402` package (`pip install x402`) with `x402HttpxClient` or `requests` hooks, same URL.

Testing without paying: the service operator can give you an `x-api-key` header that skips the paywall.

## MCP

Add `https://sentbot.fly.dev/mcp` as a remote MCP server (streamable HTTP, no sign-in). Free tools: `search_scenes`, `get_quote`, `preview_image` (returns a PNG), `list_products`. Paid tools: `analyze_area`, `area_timeseries`, `detect_change`, `get_image`. A paid tool called without payment returns an error result whose structured content is the x402 PaymentRequired object (one offer per network). Pay with an x402 MCP client (`npm i @x402/mcp`, `createx402MCPClient`), which signs and retries with `_meta["x402/payment"]`. Settlement happens only after the tool succeeded.

## 2. Check before you buy (free)

- `GET https://sentbot.fly.dev/v1/quote?product=analyze&index=ndvi&bbox=...&date=...` returns the exact price and the URL to call.
- `GET https://sentbot.fly.dev/v1/catalog/search?bbox=...&from=2025-06-01&to=2025-07-31&maxCloud=20` lists scenes with dates and cloud cover. Pick a date, then pass it as `date=`.
- `GET https://sentbot.fly.dev/v1/preview?lat=...&lon=...&km=...&preset=true-color` returns a free 384x384 PNG of any place (rate limited). Look before you buy.
- `GET https://sentbot.fly.dev/v1/products` lists collections, presets, indices, their value ranges and class thresholds.
- `GET https://sentbot.fly.dev/v1/pricing` explains the price rules.

## 3. Common parameters

| Parameter | Meaning |
| --- | --- |
| bbox | west,south,east,north in decimal degrees (EPSG:4326). Max area 10,000 km². |
| lat, lon, km | Instead of bbox: a square of `km` side (default 5) around the point. |
| collection | `s2` Sentinel-2 L2A optical (default), `s1` Sentinel-1 GRD radar. Radar works through cloud and at night. |
| date | YYYY-MM-DD. The best scene in the 30 days up to this date is used. |
| from, to | Explicit window instead of date. |
| width, height | Pixels, 64 to 2048, default 512. Or `res` in metres per pixel (10 is native). |
| maxCloud | Sentinel-2 scene cloud cover limit in percent, default 30. Raise it if you get no data. |
| mosaicking | `leastCC` (least cloudy, s2 default), `mostRecent` (s1 default), `leastRecent`. |
| cloudMask | Sentinel-2: hide and exclude cloud pixels (default true). |
| orbit | Sentinel-1: `ascending` or `descending`. Use the same one for change detection. |

## 4. Products and prices

Prices below are for 512x512 pixels on Sentinel-2. Sentinel-1 costs 1.5x because radar processing is heavier. Larger images cost more per 512x512 block; `/v1/quote` gives the exact figure.

### GET /v1/imagery (0.01 USD)
Returns the image bytes. `preset` picks the rendering:
- Sentinel-2: `true-color`, `false-color` (vegetation red), `swir`, `agriculture`, `ndvi`, `ndwi`, `ndmi`, `nbr`, `evi`, `savi`, `ndsi`, `scl` (scene classes)
- Sentinel-1: `vv`, `vh`, `rgb` (VV, VH, ratio), `water`
`format=png` (default, transparent where no data), `jpeg`, or `tiff` (GeoTIFF; index presets give FLOAT32 values, -9999 = no data).
Response headers: `x-sentbot-bbox`, `x-sentbot-time-range`, `x-sentbot-size`, `x-sentbot-price-usd`.

Example: `https://sentbot.fly.dev/v1/imagery?lat=48.8566&lon=2.3522&km=8&preset=true-color&date=2025-07-15&width=1024`

### GET /v1/analyze?index={index} (0.03 USD)
Indices: `ndvi` vegetation, `ndwi` water, `ndmi` moisture, `nbr` burn, `evi`, `savi`, `ndsi` snow (Sentinel-2); `vv`, `vh` backscatter in dB, `water` mask fraction (Sentinel-1).
JSON with `stats` (mean, min, max, stDev, percentiles p5 to p95, histogram, `classes` fractions such as bare/sparse/moderate/dense for NDVI), `validFraction` (share of usable pixels; below 0.5 means cloud or no coverage, try another date), a `legend`, and `image.dataUrl` (PNG base64). `format=png` or `tiff` returns only the image.

Example: `https://sentbot.fly.dev/v1/analyze?index=ndwi&bbox=-122.55,37.7,-122.35,37.85&date=2025-08-01`

### GET /v1/timeseries?index={index} (0.01 USD per interval, min 0.02, max 0.25)
`from` required, `to` defaults to today, `interval` such as `P10D` (default) or `P30D`. Max 60 intervals, 3 years. Each entry has mean, p10, p50, p90, validFraction and class fractions. Intervals without a usable scene have null means.

Example: `https://sentbot.fly.dev/v1/timeseries?index=ndvi&bbox=5.1,52.0,5.2,52.08&from=2025-03-01&to=2025-10-01&interval=P10D`

### GET /v1/change?index={index} (0.05 USD)
`dateA` and `dateB` required; `window` days (default 15) before each date are searched for a clean scene. Returns before and after stats, `difference.stats`, `lossFraction`, `gainFraction`, `stableFraction` (threshold = 10 percent of the index range) and a red (loss) / green (gain) PNG. For radar use `index=vv` or `water` with the same `orbit` for both dates: good for flood mapping.

Example: `https://sentbot.fly.dev/v1/change?index=nbr&bbox=-8.7,39.4,-8.5,39.55&dateA=2025-06-01&dateB=2025-08-20`

## 5. Reading the numbers

- NDVI: below 0.1 water/bare, 0.2 to 0.4 sparse, 0.4 to 0.6 crops, above 0.6 dense vegetation.
- NDWI: above 0 wet, above 0.3 open water.
- NBR: a drop of more than 0.27 between dates means moderate to high burn severity.
- NDSI above 0.4: snow or ice.
- Sentinel-1 VV below -18 dB: smooth surface, usually water. Urban is above -6 dB.
- Always check `validFraction` first. Under 0.5, pick another date via the catalog or raise `maxCloud`.

## 6. Errors

- 400: parameter problem, message says what to fix. Not charged.
- 402: payment required (see section 1).
- 429 or 502: Copernicus Data Space limits or failure. Retry after a few seconds. Not charged.

## 7. Attribution

Contains modified Copernicus Sentinel data, processed by Sentinel Hub on the Copernicus Data Space Ecosystem. Sentinel data is free and open; you pay for processing and delivery.
