Start with coordinates

air-quality returns current AQI and pollutant readings for a coordinate pair. A travel agent can add air quality to a destination brief. An outdoor planning app can request hourly forecasts to compare conditions across its scheduled window.

Each call costs 0.005 USDC, paid through x402 on Base mainnet.

Send numeric latitude and longitude values to https://x402.agentutility.ai/air-quality. Latitude accepts values from -90 to 90; longitude accepts -180 to 180. Strings such as "37.7749" fail validation, so keep coordinates as JSON numbers.

Here's a current-readings request for San Francisco:

curl -X POST https://x402.agentutility.ai/air-quality \
  -H 'Content-Type: application/json' \
  -d '{
    "latitude": 37.7749,
    "longitude": -122.4194
  }'

This shows the request shape. Your x402 client handles the payment challenge and paid retry; plain curl without payment handling won't complete the paid call.

The response groups readings under current. Its location object includes returned coordinates and a timezone, while units gives the measurement labels for the fields.

Keep the returned location. It can differ from the exact coordinates you submitted.

Request the hours you need

Want to compare the afternoon with the evening? Set hourly to true and choose forecast_hours.

{
  "latitude": 37.7749,
  "longitude": -122.4194,
  "hourly": true,
  "forecast_hours": 12
}

The forecast window defaults to 24 hours. The endpoint rounds a supplied numeric value down to a whole hour, then limits it to 1–72. A value of 12.8 becomes 12; 100 becomes 72.

Use an integer explicitly. It makes the request easier to audit.

And keep the two controls separate: forecast_hours sets the window, while hourly: true requests the rows. Supplying the window alone doesn't add an hourly array. With hourly output requested, current readings remain in the response.

Each hourly row has a time value and the same numeric AQI and pollutant fields used for current readings. The response includes up to the requested number of rows, subject to available data. Check the array's actual length before indexing it.

Read the category beside the measurements

current.us_aqi_category is derived from current.us_aqi. The endpoint uses these thresholds:

| US AQI | Returned category | |---|---| | 50 or below | good | | Above 50 through 100 | moderate | | Above 100 through 150 | unhealthy_for_sensitive_groups | | Above 150 through 200 | unhealthy | | Above 200 through 300 | very_unhealthy | | Above 300 | hazardous |

The response also includes european_aqi. Keep its label attached when presenting it. The returned category belongs to the US AQI value.

Pollutant fields include pm2_5 and pm10, plus carbon_monoxide, nitrogen_dioxide, sulphur_dioxide, and ozone. Preserve those exact names in parsers, including the spelling of sulphur_dioxide.

Read units from the payload. AQI values are indices; pollutant concentrations have measurement units. Copying a concentration into a user-facing sentence without its unit loses information.

This illustrative response excerpt shows how a reading pairs with its unit. These aren't live readings:

{
  "current": {
    "us_aqi": 42,
    "us_aqi_category": "good",
    "pm2_5": 7.2
  },
  "units": {
    "us_aqi": "USAQI",
    "pm2_5": "μg/m³"
  }
}

That gives your agent enough to write “US AQI: 42, good” and “PM2.5: 7.2 μg/m³” without guessing what either number means.

Preserve missing values and timestamps

Missing numeric current readings return as null. A missing US AQI also produces a null category. Treat that as unavailable data; converting it to zero would invent a reading.

Hourly rows don't include us_aqi_category. If your interface needs a category for every hour, apply the US AQI thresholds to each row's us_aqi and preserve nulls.

For a destination brief, attach current.time to the current reading and retain location.timezone when displaying it. For a forecast comparison, use each row's own timestamp. Before choosing a row for a planned departure, check that its time matches the user's intended local hour.