{
    "info": {
        "name": "ForecastWatch API — Webinar Demo",
        "description": "Hands-on demo collection for the ForecastWatch API webinar.\n\n## Setup\n\n1. **Import this file** (Postman → Import → drag this JSON).\n2. Open the collection. On the **Variables** tab, set `apiKey` to your real key (format: `fw_...`). Generate one at https://app3.forecastwatch.com → Tools → API Portal.\n3. Run the requests top-to-bottom. Earlier requests auto-populate variables that later requests consume, so you don't have to copy IDs by hand:\n   - **List Months** saves the newest month ID into `latestMonth`.\n   - **List Daily Dates** saves the newest available date into `latestDailyDate`.\n   - **Monthly Stations** saves the first `station_id` from the response into `demoStationId`.\n\n## What's included\n\n- **API Docs** — the self-documenting catalog (curl examples for every endpoint).\n- **Me** — authentication sanity check; shows your account, active provider, menu.\n- **List Months** — discovery of month IDs; auto-saves the most recent into `latestMonth`.\n- **Monthly Insights** — your provider's score + anonymous benchmark for one month.\n- **Monthly Stations** — per-station scores for one month (input to the chronic-offender demo); auto-saves first station into `demoStationId`.\n- **List Daily Dates** — available dates for daily insights; auto-saves newest into `latestDailyDate`.\n- **Daily Insights** — per-station quadrant classification for one day.\n- **Station Trend** — 30–90 day skill-ratio trend for a single station (drilldown).\n- **Export Monthly CSV** — CSV download for the Excel demo.\n\nAuth is set at the collection level (Bearer `{{apiKey}}`) so every request inherits it.",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    },
    "auth": {
        "type": "bearer",
        "bearer": [
            {
                "key": "token",
                "value": "{{apiKey}}",
                "type": "string"
            }
        ]
    },
    "variable": [
        {
            "key": "baseUrl",
            "value": "https://api.forecastwatch.com",
            "type": "string",
            "description": "API base URL. Override for staging."
        },
        {
            "key": "apiKey",
            "value": "",
            "type": "string",
            "description": "Your ForecastWatch API key. Format: fw_xxxxxxxxxxxx. Generate at https://app3.forecastwatch.com → Tools → API Portal."
        },
        {
            "key": "latestMonth",
            "value": "",
            "type": "string",
            "description": "Auto-populated by the List Months request. Don't set manually."
        },
        {
            "key": "demoStationId",
            "value": "",
            "type": "string",
            "description": "Auto-populated by the Monthly Stations request (first station_id in the response). Don't set manually — run Monthly Stations first."
        },
        {
            "key": "latestDailyDate",
            "value": "",
            "type": "string",
            "description": "Auto-populated by the List Daily Dates request. Don't set manually."
        }
    ],
    "item": [
        {
            "name": "API Docs",
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/api-docs/",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "api-docs", ""]
                },
                "description": "The full self-documenting endpoint catalog. Each entry includes parameters, an example response, and a ready-to-paste curl example. Treat this as your reference for every other endpoint not in this collection."
            }
        },
        {
            "name": "Me",
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/auth/me/",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "auth", "me", ""]
                },
                "description": "Authentication smoke test. Returns your user, account, active_provider, menu, preferences, and email subscriptions. If this works, your key is valid and you're ready to call anything else.\n\nThe `active_provider` returned here is the one the insights endpoints answer for, so you never pass a provider as a query param."
            }
        },
        {
            "name": "List Months",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "// Auto-save the most recent month ID into a collection variable",
                            "// so downstream requests can use {{latestMonth}} without manual copy-paste.",
                            "pm.test('Status is 200', function () {",
                            "    pm.response.to.have.status(200);",
                            "});",
                            "",
                            "const months = pm.response.json();",
                            "if (Array.isArray(months) && months.length > 0) {",
                            "    const latest = months[0].id;",
                            "    pm.collectionVariables.set('latestMonth', latest);",
                            "    console.log('Saved latestMonth =', latest);",
                            "} else {",
                            "    console.warn('No months returned — latestMonth not updated.');",
                            "}"
                        ]
                    }
                }
            ],
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/reference/months/",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "reference", "months", ""]
                },
                "description": "Returns the list of months that have aggregated scoring data. Each entry is `{id, year, month, label}`. The `id` is what you pass to insights endpoints — NOT a year-month string.\n\n**Test script:** auto-saves `months[0].id` into the `latestMonth` collection variable, so downstream requests can use `{{latestMonth}}` directly."
            }
        },
        {
            "name": "Monthly Insights",
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/insights/monthly/?month={{latestMonth}}&metric=high24&days_out=1",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "insights", "monthly", ""],
                    "query": [
                        {
                            "key": "month",
                            "value": "{{latestMonth}}",
                            "description": "Month ID from /v1/reference/months/. Auto-populated by the List Months request."
                        },
                        {
                            "key": "metric",
                            "value": "high24",
                            "description": "Metric code. Default: high24 (24-hour high temperature)."
                        },
                        {
                            "key": "days_out",
                            "value": "1",
                            "description": "Forecast horizon in days. Default: 1."
                        }
                    ]
                },
                "description": "Your provider's score for a single month, plus anonymous benchmark stats (percentile, tier, best/mean) against the peer set in the same market.\n\nNo competitor names are ever revealed — that's a design constraint.\n\n**Run `List Months` first** so `{{latestMonth}}` is populated."
            }
        },
        {
            "name": "Monthly Stations",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "// Auto-save the first station_id into the demoStationId",
                            "// collection variable so the Station Trend request below",
                            "// can use {{demoStationId}} without manual copy-paste.",
                            "pm.test('Status is 200', function () {",
                            "    pm.response.to.have.status(200);",
                            "});",
                            "",
                            "const body = pm.response.json();",
                            "const stations = body && body.stations ? body.stations : [];",
                            "if (Array.isArray(stations) && stations.length > 0) {",
                            "    const firstId = stations[0].station_id;",
                            "    pm.collectionVariables.set('demoStationId', String(firstId));",
                            "    console.log('Saved demoStationId =', firstId);",
                            "} else {",
                            "    console.warn('No stations returned — demoStationId not updated.');",
                            "}"
                        ]
                    }
                }
            ],
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/insights/monthly/stations/?month={{latestMonth}}&metric=high24&days_out=1",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "insights", "monthly", "stations", ""],
                    "query": [
                        {
                            "key": "month",
                            "value": "{{latestMonth}}"
                        },
                        {
                            "key": "metric",
                            "value": "high24"
                        },
                        {
                            "key": "days_out",
                            "value": "1"
                        }
                    ]
                },
                "description": "Per-station metric scores for one month. Response is `{stations: [{station_id, score, market_avg, ...}], metric: {...}, secondary_stats: [...]}`. Station names aren't included here — pair with `/v1/reference/station-metadata/` if you need them.\n\nThis is the input for the chronic-offender analysis in the Excel demo: loop this over N recent months, append, group by station, count appearances in the worst-N. The endpoint deliberately returns ALL stations (not pre-filtered) so you can define 'worst' however you want.\n\n**Test script:** auto-saves `stations[0].station_id` into the `demoStationId` collection variable, so the Station Trend request below can use `{{demoStationId}}` directly."
            }
        },
        {
            "name": "List Daily Dates",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('Status is 200', function () {",
                            "    pm.response.to.have.status(200);",
                            "});",
                            "",
                            "const body = pm.response.json();",
                            "const dates = body && body.dates ? body.dates : [];",
                            "if (Array.isArray(dates) && dates.length > 0) {",
                            "    pm.collectionVariables.set('latestDailyDate', dates[0]);",
                            "    console.log('Saved latestDailyDate =', dates[0]);",
                            "} else {",
                            "    console.warn('No daily dates returned — latestDailyDate not updated.');",
                            "}"
                        ]
                    }
                }
            ],
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/insights/daily/dates/?metric=high24",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "insights", "daily", "dates", ""],
                    "query": [
                        {
                            "key": "metric",
                            "value": "high24",
                            "description": "Metric code. Omit to see dates with data for any metric."
                        }
                    ]
                },
                "description": "Available dates for daily insights — a rolling ~50-day window of dates that have scoring data for the given metric.\n\nResponse: `{dates: [...], count: N}` with newest first.\n\n**Test script:** auto-saves `dates[0]` into the `latestDailyDate` collection variable, so Daily Insights can use `{{latestDailyDate}}` directly."
            }
        },
        {
            "name": "Daily Insights",
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/insights/daily/?date={{latestDailyDate}}&days_out=1&metric=high24",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "insights", "daily", ""],
                    "query": [
                        {
                            "key": "date",
                            "value": "{{latestDailyDate}}",
                            "description": "Date (YYYY-MM-DD). Auto-populated by the List Daily Dates request."
                        },
                        {
                            "key": "days_out",
                            "value": "1",
                            "description": "Forecast horizon in days. Default: 1."
                        },
                        {
                            "key": "metric",
                            "value": "high24"
                        },
                        {
                            "key": "quadrant",
                            "value": "bold_wrong",
                            "description": "Optional. Filter to one or more quadrants (comma-separated). Enable this row to see only bold_wrong stations.",
                            "disabled": true
                        }
                    ]
                },
                "description": "Per-station quadrant classification for one day. Each station gets `divergence_z`, `accuracy_z`, and a `quadrant` label: bold_right, bold_wrong, dragged_down, conventional_correct, unremarkable.\n\nStations are sorted by `|divergence_z|` descending — biggest divergences first.\n\nThe `quadrant` query param (disabled by default) does server-side filtering — enable it to get only e.g. bold_wrong stations. The `summary` block in the response always reflects the unfiltered totals so you can see the full landscape.\n\nThe Excel Part 3 demo uses this filter to find chronically miscalibrated stations.\n\n**Run `List Daily Dates` first** so `{{latestDailyDate}}` is populated."
            }
        },
        {
            "name": "Station Trend",
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/insights/station-trend/?station_id={{demoStationId}}&metric=high24&days=30",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "insights", "station-trend", ""],
                    "query": [
                        {
                            "key": "station_id",
                            "value": "{{demoStationId}}",
                            "description": "Station ID. Auto-populated by the Monthly Stations request (first station_id in the response)."
                        },
                        {
                            "key": "metric",
                            "value": "high24"
                        },
                        {
                            "key": "days",
                            "value": "30",
                            "description": "Number of days in the trend. Range: 7–90. Default: 30."
                        }
                    ]
                },
                "description": "Daily error trend for a single station over the last N days. Returns `{station_id, metric, days_out, trend: [...]}` where each item in `trend` is `{date, skill_ratio, your_signed_diff, direction_score}`.\n\nUse this as the drilldown after Monthly Stations identifies a chronically-bad station. Plot `skill_ratio` over time to see whether the station is degrading, recovering, or stably bad.\n\n**Run `Monthly Stations` first** so `{{demoStationId}}` is populated."
            }
        },
        {
            "name": "Export Monthly CSV",
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "{{baseUrl}}/v1/export/?source=monthly&month={{latestMonth}}&format=csv&metric=high24",
                    "host": ["{{baseUrl}}"],
                    "path": ["v1", "export", ""],
                    "query": [
                        {
                            "key": "source",
                            "value": "monthly",
                            "description": "Export type: monthly | daily | trends | watchlist."
                        },
                        {
                            "key": "month",
                            "value": "{{latestMonth}}"
                        },
                        {
                            "key": "format",
                            "value": "csv",
                            "description": "csv or xlsx."
                        },
                        {
                            "key": "metric",
                            "value": "high24"
                        }
                    ]
                },
                "description": "Downloads accuracy data as CSV (or xlsx). The endpoint returns a real file with `Content-Disposition: attachment` — Postman will display the body inline, but in Excel Power Query this URL hydrates a refreshable table.\n\nThis is the URL you paste into the Excel demo: `Data → Get Data → From Web → Advanced`, then add an `Authorization: Bearer fw_...` header."
            }
        }
    ]
}
