# Air Quality, AQI, Pollen & UV Scraper (Global) (`scrapers_lat/air-quality-aqi-pollen-scraper`) Actor

Get live air quality for any city or coordinates: US AQI and European AQI with category labels, PM2.5, PM10, ozone, NO2, SO2, CO, dust, pollen and UV, plus forecast and optional 92-day history. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/scrapers\_lat/air-quality-aqi-pollen-scraper.md
- **Developed by:** [Scrapers Lat](https://apify.com/scrapers_lat) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.56 / 1,000 air quality results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

[![Air Quality, AQI, Pollen & UV Scraper (Global)](https://scrapers.lat/banners/air-quality-aqi-pollen-scraper.png)](https://console.apify.com/actors/Lug1vi37iryJiWQCZ/input)

## Air Quality, AQI, Pollen & UV Scraper (Global)

Here is one real result, with every field the actor returns (Krakow, Poland, with the history and AI advisory add-ons on):

```json
{
  "input": "Krakow, Poland",
  "resolvedName": "Krakow",
  "country": "Poland",
  "admin1": "Lesser Poland",
  "latitude": 50.1,
  "longitude": 19.9,
  "timezone": "Europe/Warsaw",
  "elevation": 214,
  "observedTime": "2026-08-21T11:00",
  "us_aqi": 51,
  "usAqiCategory": "Moderate",
  "european_aqi": 27,
  "euAqiCategory": "Fair",
  "dominantPollutant": "PM2.5",
  "pm2_5": 13,
  "pm10": 17.3,
  "ozone": 67,
  "nitrogen_dioxide": 15.6,
  "sulphur_dioxide": 5.5,
  "carbon_monoxide": 207,
  "ammonia": null,
  "dust": 6,
  "aerosol_optical_depth": 0.24,
  "uv_index": 3.6,
  "uv_index_clear_sky": 5,
  "alder_pollen": null,
  "birch_pollen": null,
  "grass_pollen": null,
  "mugwort_pollen": null,
  "olive_pollen": null,
  "ragweed_pollen": null,
  "pollenRisk": null,
  "forecastDays": 1,
  "forecast": [
    { "time": "2026-08-21T00:00", "us_aqi": 50, "pm2_5": 9.1 },
    { "time": "2026-08-21T01:00", "us_aqi": 50, "pm2_5": 7.4 },
    { "time": "2026-08-21T02:00", "us_aqi": 49, "pm2_5": 7.7 }
  ],
  "historyDays": 92,
  "historyStart": "2026-05-21",
  "historyEnd": "2026-08-20",
  "avgUsAqi": 58.6,
  "maxUsAqi": 139,
  "avgPm2_5": 13.8,
  "maxPm2_5": 26,
  "daysExceedingUsAqi100": 1,
  "worstDay": "2026-08-06",
  "worstDayUsAqi": 139,
  "aiRiskLevel": "moderate",
  "aiSensitiveGroupsAdvice": "Children, elderly, asthmatics, and pregnant individuals should limit prolonged outdoor exertion.",
  "aiOutdoorActivityAdvice": "Outdoor exercise is generally safe but should be limited for sensitive groups.",
  "aiMaskRecommended": false,
  "aiWindowVentilationAdvice": "Ventilation is acceptable, but consider limiting it during high pollution times.",
  "source": "Open-Meteo Air Quality",
  "observedAt": "2026-08-21T09:28:59.035Z",
  "error": null
}
```

The most complete air quality scraper available. It returns both the US AQI and the European AQI with human-readable category labels, the dominant pollutant, every major pollutant (PM2.5, PM10, ozone, NO2, SO2, CO, ammonia, dust, aerosol optical depth), UV index, optional European pollen counts, an hourly forecast, and an optional 92-day pollution history, for any city name or coordinate pair on Earth in a single call. Most AQI tools give you one number; this one gives you the full picture plus a forecast.

**📥 [Input](https://apify.com/scrapers_lat/air-quality-aqi-pollen-scraper/input-schema) · 📤 [Output](https://apify.com/scrapers_lat/air-quality-aqi-pollen-scraper/output-schema) · 💰 [Pricing](https://apify.com/scrapers_lat/air-quality-aqi-pollen-scraper/pricing) · ▶️ [Examples](https://apify.com/scrapers_lat/air-quality-aqi-pollen-scraper/examples)**

![Apify](https://img.shields.io/badge/Platform-Apify-1CE1CE?logo=apify\&logoColor=white)
![Coverage](https://img.shields.io/badge/Coverage-Global-blue)
![Output](https://img.shields.io/badge/Output-JSON%20%7C%20CSV%20%7C%20Excel-orange)
![Billing](https://img.shields.io/badge/Billing-Pay%20per%20result-brightgreen)

### Table of contents

- [What it does](#what-it-does)
- [Quickstart](#quickstart)
- [Input reference](#input-reference)
- [Output reference](#output-reference)
- [Example output record](#example-output-record)
- [Run via API and CLI](#run-via-api-and-cli)
- [Fetch results](#fetch-results)
- [Use cases](#use-cases)
- [Billing and limits](#billing-and-limits)
- [FAQ and troubleshooting](#faq-and-troubleshooting)

### What it does

Pass a list of locations. Each item can be a plain place name such as `Los Angeles, United States` or `Paris` (the actor geocodes it for you at no charge) or a `latitude,longitude` pair such as `34.05,-118.24`. For every location the actor fetches the current air quality and writes one normalized record with:

- **US AQI and European AQI**, each with a plain-English category label (`Good`, `Moderate`, `Unhealthy`, and so on).
- The **dominant pollutant** driving the highest AQI subindex.
- Every major pollutant concentration: **PM2.5, PM10, ozone, nitrogen dioxide, sulphur dioxide, carbon monoxide, ammonia, dust, aerosol optical depth**.
- **UV index** (and clear-sky UV index).
- An optional **hourly forecast** of US AQI and PM2.5 for up to 7 days.
- Optional **European pollen** counts (alder, birch, grass, mugwort, olive, ragweed) plus a pollen risk label.
- An optional **92-day pollution history** summary and an optional **AI health advisory**.

Missing source values are returned as `null`, never invented. Numbers are parsed and rounded so you can sort and filter without extra work.

### Quickstart

Open the actor, paste this into the input, and press Run. It returns the current air quality and a 2-day forecast for two cities.

```json
{
  "locations": ["Los Angeles, United States", "Beijing, China"],
  "forecastDays": 2
}
```

Every field except `locations` is optional. To add European pollen counts, set `includePollen` to `true`. To add the 92-day history and the AI advisory (paid plans), set `includeHistory` and `aiHealthAdvisory` to `true`.

### Input reference

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `locations` | string\[] | yes | (none) | Locations to fetch. Each item is a place name (`Paris`, `Los Angeles, United States`) or a `latitude,longitude` pair (`34.05,-118.24`). Names are geocoded automatically at no charge. |
| `forecastDays` | integer | no | `1` | Days of hourly US AQI and PM2.5 forecast to include per location (0 to 7). `0` returns only the current snapshot. |
| `includePollen` | boolean | no | `false` | Add pollen counts (alder, birch, grass, mugwort, olive, ragweed) and a pollen risk label. Pollen is available for Europe only; elsewhere these fields are `null`. |
| `includeHistory` | boolean | no | `false` | Add-on. Add a 92-day air-quality history summary per location. Billed per location only when a real history series is returned. Paid Apify plans only. |
| `aiHealthAdvisory` | boolean | no | `false` | Add-on. Add an AI-written health advisory per location. Billed per location only when a usable advisory is produced. Paid Apify plans only. |
| `maxResults` | integer | no | `10` | Maximum locations to return in one run. Free Apify plans are capped at 10. |

### Output reference

One dataset item per location. Types are `string`, `number`, `integer`, `boolean`, `array`, or `null` when a source value is absent.

| Field | Type | Description |
|---|---|---|
| `input` | string | The location string you passed in. |
| `resolvedName` | string | Resolved place name from geocoding. |
| `country` | string | Country of the resolved location. |
| `admin1` | string | State or region of the resolved location. |
| `latitude` | number | Latitude used for the query. |
| `longitude` | number | Longitude used for the query. |
| `timezone` | string | IANA timezone of the location. |
| `elevation` | number | Elevation in meters. |
| `observedTime` | string | Local time of the current observation. |
| `us_aqi` | number | US Air Quality Index. |
| `usAqiCategory` | string | US AQI category: `Good`, `Moderate`, `Unhealthy for Sensitive Groups`, `Unhealthy`, `Very Unhealthy`, `Hazardous`. |
| `european_aqi` | number | European Air Quality Index. |
| `euAqiCategory` | string | European AQI category: `Good`, `Fair`, `Moderate`, `Poor`, `Very Poor`, `Extremely Poor`. |
| `dominantPollutant` | string | Pollutant driving the highest AQI subindex. |
| `pm2_5` | number | Fine particulate matter PM2.5 in ug/m3. |
| `pm10` | number | Coarse particulate matter PM10 in ug/m3. |
| `ozone` | number | Ozone (O3) in ug/m3. |
| `nitrogen_dioxide` | number | Nitrogen dioxide (NO2) in ug/m3. |
| `sulphur_dioxide` | number | Sulphur dioxide (SO2) in ug/m3. |
| `carbon_monoxide` | number | Carbon monoxide (CO) in ug/m3. |
| `ammonia` | number | Ammonia (NH3) in ug/m3 (Europe only). |
| `dust` | number | Dust concentration in ug/m3. |
| `aerosol_optical_depth` | number | Aerosol optical depth at 550 nm. |
| `uv_index` | number | UV index. |
| `uv_index_clear_sky` | number | UV index assuming clear sky. |
| `alder_pollen` | number | Alder pollen in grains/m3 (pollen add-on, Europe). |
| `birch_pollen` | number | Birch pollen in grains/m3 (pollen add-on, Europe). |
| `grass_pollen` | number | Grass pollen in grains/m3 (pollen add-on, Europe). |
| `mugwort_pollen` | number | Mugwort pollen in grains/m3 (pollen add-on, Europe). |
| `olive_pollen` | number | Olive pollen in grains/m3 (pollen add-on, Europe). |
| `ragweed_pollen` | number | Ragweed pollen in grains/m3 (pollen add-on, Europe). |
| `pollenRisk` | string | Pollen risk label: `None`, `Low`, `Moderate`, `High`, `Very High`. |
| `forecastDays` | integer | Number of forecast days requested. |
| `forecast` | array | Hourly forecast points (`time`, `us_aqi`, `pm2_5`) for the requested window. |
| `historyDays` | integer | Days covered by the history summary (history add-on). |
| `historyStart` | string | First day in the history window (history add-on). |
| `historyEnd` | string | Last day in the history window (history add-on). |
| `avgUsAqi` | number | Average daily US AQI over the history window (history add-on). |
| `maxUsAqi` | number | Max US AQI over the history window (history add-on). |
| `avgPm2_5` | number | Average daily PM2.5 over the history window (history add-on). |
| `maxPm2_5` | number | Max daily-average PM2.5 over the history window (history add-on). |
| `daysExceedingUsAqi100` | integer | Count of history days with a max US AQI above 100 (history add-on). |
| `worstDay` | string | Worst day in the history window (history add-on). |
| `worstDayUsAqi` | number | Max US AQI on the worst day (history add-on). |
| `aiRiskLevel` | string | AI-assessed risk level (AI advisory add-on). |
| `aiSensitiveGroupsAdvice` | string | AI advice for sensitive groups (AI advisory add-on). |
| `aiOutdoorActivityAdvice` | string | AI outdoor activity advice (AI advisory add-on). |
| `aiMaskRecommended` | boolean | Whether the AI recommends a mask (AI advisory add-on). |
| `aiWindowVentilationAdvice` | string | AI window ventilation advice (AI advisory add-on). |
| `source` | string | Data source. |
| `observedAt` | string | ISO 8601 timestamp of when the record was collected. |
| `error` | string | `null` on success. On a location that cannot be resolved or fetched, a single item with a populated `error` field is written and not charged. |

### Example output record

Real record from a live run (input `{"locations": ["Paris, France"], "includePollen": true}`):

```json
{
  "input": "Paris, France",
  "resolvedName": "Paris",
  "country": "France",
  "latitude": 48.85,
  "longitude": 2.35,
  "timezone": "Europe/Paris",
  "us_aqi": 23,
  "usAqiCategory": "Good",
  "european_aqi": 18,
  "euAqiCategory": "Good",
  "dominantPollutant": "PM2.5",
  "pm2_5": 4.6,
  "grass_pollen": 0.5,
  "birch_pollen": 0,
  "ragweed_pollen": 2.1,
  "pollenRisk": "Low",
  "uv_index": 3.1,
  "source": "Open-Meteo Air Quality",
  "error": null
}
```

### Run via API and CLI

Start a run and read the dataset. Replace `<TOKEN>` with your Apify API token.

Run synchronously and get dataset items in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~air-quality-aqi-pollen-scraper/run-sync-get-dataset-items?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"locations":["Los Angeles, United States","Beijing, China"],"forecastDays":2}'
```

Start a run asynchronously:

```bash
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~air-quality-aqi-pollen-scraper/runs?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"locations":["Paris, France"],"includePollen":true}'
```

Apify CLI:

```bash
apify call scrapers_lat/air-quality-aqi-pollen-scraper \
  --input '{"locations":["34.05,-118.24"],"forecastDays":3}'
```

### Fetch results

Every run writes to a dataset. Fetch items as JSON, CSV, or Excel by changing `format`:

```bash
## JSON
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"

## CSV
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"
```

`<DATASET_ID>` is returned as `defaultDatasetId` in the run object.

### Use cases

- **Air-quality monitoring:** track US AQI and European AQI across many cities in one run and alert when a category crosses a threshold.
- **Health and wellness apps:** show users a clear air-quality category, the dominant pollutant, UV index, and pollen risk for their location.
- **Real estate and relocation:** compare long-term pollution history (92-day average and worst day) between neighborhoods or cities before a move.
- **Insurance risk:** feed pollutant and AQI history into environmental and health risk models.
- **Outdoor-event planning:** check the AQI and PM2.5 forecast for the days of a race, festival, or match.
- **Agriculture:** monitor ozone, dust, and pollen that affect crops and field workers.
- **Environmental compliance:** collect pollutant concentrations for reporting and trend analysis.
- **Smart-home automation:** drive air purifiers, HVAC, and window automations from live AQI and forecast data.

### Billing and limits

This actor uses pay-per-event billing. You are charged only for real results, never for failures.

- **`apify-actor-start`** is charged once when a run starts.
- **`result`** is the primary event, charged once per location for the full air-quality snapshot and forecast.
- **`pollution_history`** is an opt-in add-on (`includeHistory`), off by default and available to paying users only. It performs a genuine extra fetch (a 92-day history query) and is charged only when a real history series is returned.
- **`ai_health_advisory`** is an opt-in add-on (`aiHealthAdvisory`), off by default and available to paying users only. It is charged only when the model returns a usable advisory.

See the [pricing tab](https://apify.com/scrapers_lat/air-quality-aqi-pollen-scraper/pricing) for the current per-event prices.

- **No charge on failure.** A location that cannot be resolved or fetched is written as a single item with a populated `error` field and is not charged. Add-ons are charged only when they genuinely produce data.
- **Spend cap respected.** Set `maxTotalChargeUsd` on the run; once reached, the actor stops emitting and charging further billable results.
- **Free Apify plans** are capped at 10 locations per run and cannot use the paid add-ons. Upgrade for higher `maxResults` and the add-ons.

### FAQ and troubleshooting

**Can I pass a city name instead of coordinates?**
Yes. Pass a name like `Tokyo` or `Los Angeles, United States` and the actor geocodes it for you at no charge. You can also pass a `latitude,longitude` pair directly.

**Why are the pollen fields null?**
Pollen data is produced by the European CAMS model and is available for Europe only. Outside Europe the pollen fields are `null`. Pollen is also only fetched when `includePollen` is `true`.

**What is the difference between US AQI and European AQI?**
They are two different indices with different scales and category breakpoints. The US AQI runs roughly 0 to 500; the European AQI runs roughly 0 to 100+. This actor returns both plus their category labels so you can use whichever your audience expects.

**How is the dominant pollutant chosen?**
It is the pollutant with the highest AQI subindex for that location at the observed time (PM2.5, PM10, ozone, NO2, SO2, or CO).

**A location returned an error. Was I charged?**
No. Locations that cannot be resolved or fetched are written with an `error` field and are not charged.

**How current is the data?**
The `observedTime` field is the local time of the current observation. Air quality is updated hourly at the source.

**Is this an official government tool?**
No. This actor is independent and reads publicly available air-quality and geocoding data. Use it in accordance with the source terms of service.

### Related scrapers

- [Open-Meteo Weather Scraper](https://apify.com/scrapers_lat/open-meteo-weather-scraper): temperature, precipitation, and wind forecast by location.
- [FRED Economic Data Scraper](https://apify.com/scrapers_lat/fred-economic-data-scraper): US macroeconomic time series.
- [openFDA Food Recall & Enforcement Scraper](https://apify.com/scrapers_lat/openfda-food-recalls-scraper): US food recalls and enforcement.

### More scrapers at scrapers.lat

Built and maintained by [scrapers.lat](https://scrapers.lat), where we publish scrapers for US and Latin American public platforms: company registries, government data, finance, e-commerce and more. Browse the catalog or request a custom scraper at [scrapers.lat](https://scrapers.lat).

***

> Independent tool, not affiliated with any government air-quality agency. Accesses only publicly available air-quality and geocoding data. Use in accordance with the source terms of service.

# Actor input Schema

## `locations` (type: `array`):

One or more locations to fetch air quality for. Each item can be a place name like "Los Angeles, United States" or "Paris" (auto-geocoded), OR a "latitude,longitude" pair like "34.05,-118.24". One record is returned per location.

## `forecastDays` (type: `integer`):

How many days of hourly US AQI and PM2.5 forecast to include in each record (0 to 7). 0 returns only the current snapshot. Default 1.

## `includePollen` (type: `boolean`):

Add pollen counts (alder, birch, grass, mugwort, olive, ragweed) and a pollen risk label. Pollen data is available for Europe only (CAMS Europe model); elsewhere the values are null.

## `includeHistory` (type: `boolean`):

Add a 92-day air-quality history summary per location: average and max US AQI, average and max PM2.5, count of days exceeding US AQI 100, and the worst day. Opt-in add-on, billed per location only when a real history series is returned. Available to paid Apify plans.

## `aiHealthAdvisory` (type: `boolean`):

Add an AI-written health advisory per location (risk level, advice for sensitive groups, outdoor activity advice, whether a mask is recommended, ventilation advice) based on the current AQI, pollutants, UV and pollen. Opt-in add-on, billed per location only when a usable advisory is produced. Available to paid Apify plans.

## `maxResults` (type: `integer`):

Maximum number of locations to return in one run. Free Apify plans are capped at 10.

## Actor input object example

```json
{
  "locations": [
    "Los Angeles, United States",
    "Beijing, China"
  ],
  "forecastDays": 1,
  "includePollen": false,
  "includeHistory": false,
  "aiHealthAdvisory": false,
  "maxResults": 10
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locations": [
        "Los Angeles, United States",
        "Beijing, China"
    ],
    "forecastDays": 1,
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapers_lat/air-quality-aqi-pollen-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": [
        "Los Angeles, United States",
        "Beijing, China",
    ],
    "forecastDays": 1,
    "maxResults": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapers_lat/air-quality-aqi-pollen-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locations": [
    "Los Angeles, United States",
    "Beijing, China"
  ],
  "forecastDays": 1,
  "maxResults": 10
}' |
apify call scrapers_lat/air-quality-aqi-pollen-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapers_lat/air-quality-aqi-pollen-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Lug1vi37iryJiWQCZ/builds/lPf1NM7ga8ariggTM/openapi.json
