{
  "info": {
    "_postman_id": "b6e7c1a4-9f31-4d2a-9c52-geog-ai-spec",
    "name": "geog.ai Spatial Intelligence API",
    "description": "geog.ai turns coordinates into spatial decisions. Every API call resolves location into\nenriched context — terrain, jurisdiction, neighbors, atmospheric conditions — and optionally\nruns physics-based propagation models to answer \"what happens next?\"\n\n**Base URL:** `https://api.geog.ai/v1`\n\n**Response modes:**\n- **Synchronous** — context queries and RF/graph lookups return immediately (typically <200 ms)\n- **Async jobs** — propagation simulations (`/simulate/*`) return a job ID; results delivered\n  via webhook or polled via `GET /jobs/{job_id}`\n- **Streaming** — real-time plume tracking via SSE (`/simulate/plume/stream`, Site Calibration plans only)\n\nEvery response is wrapped in a standard envelope that includes a confidence score (0.0–1.0),\nmodel version, calibration age, and data provenance.\n\n---\n\n**Setup:**\n1. Import the matching environment file `geog-ai.postman_environment.json`.\n2. Set `api_key` to your `geog_test_sk_…` or `geog_live_sk_…` token.\n3. The `base_url` defaults to `https://api.geog.ai/v1`.\n\nRegenerate this collection from `openapi.yaml` with `python3 docs/postman/generate_postman.py`.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_exporter_id": "geog-ai-openapi-generator"
  },
  "item": [
    {
      "name": "Context API",
      "description": "Resolve spatial state for registered devices and arbitrary coordinates.",
      "item": [
        {
          "name": "Resolve SpatialState for a registered device",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/context?device_id=sensor_h2s_023",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "context"
              ],
              "query": [
                {
                  "key": "device_id",
                  "value": "sensor_h2s_023",
                  "description": "Registered device identifier.",
                  "disabled": false
                },
                {
                  "key": "include",
                  "value": "terrain,jurisdiction,wind",
                  "description": "Comma-separated context fields to include. Default: all. Options: terrain, jurisdiction, wind, nearby, assets, calibration.",
                  "disabled": true
                },
                {
                  "key": "max_age_s",
                  "value": "300",
                  "description": "Maximum acceptable state age in seconds. Older states trigger fresh enrichment.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns the full `SpatialState` for a registered device — terrain, jurisdiction, wind vector,\nnearby entities, atmospheric stability class, and asset proximity. Enrichment runs at ingest\ntime; this call returns the pre-computed state.\n\n**Pricing:** $0.001 / call\n\n`GET /context`\n\n_operationId:_ `getContext`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 SpatialState resolved successfully.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/context?device_id=sensor_h2s_023",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "context"
                  ],
                  "query": [
                    {
                      "key": "device_id",
                      "value": "sensor_h2s_023",
                      "description": "Registered device identifier.",
                      "disabled": false
                    },
                    {
                      "key": "include",
                      "value": "terrain,jurisdiction,wind",
                      "description": "Comma-separated context fields to include. Default: all. Options: terrain, jurisdiction, wind, nearby, assets, calibration.",
                      "disabled": true
                    },
                    {
                      "key": "max_age_s",
                      "value": "300",
                      "description": "Maximum acceptable state age in seconds. Older states trigger fresh enrichment.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns the full `SpatialState` for a registered device — terrain, jurisdiction, wind vector,\nnearby entities, atmospheric stability class, and asset proximity. Enrichment runs at ingest\ntime; this call returns the pre-computed state.\n\n**Pricing:** $0.001 / call\n\n`GET /context`\n\n_operationId:_ `getContext`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "SpatialState resolved successfully.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"entity_id\": \"sensor_h2s_023\",\n    \"location\": {\n      \"lat\": 31.9686,\n      \"lon\": -99.9018,\n      \"alt_m\": 547.2,\n      \"h3_index\": \"8944c0ba857ffff\",\n      \"indoor\": null\n    },\n    \"time\": \"2026-04-21T03:14:22Z\",\n    \"context\": {\n      \"wind_vector\": {\n        \"speed_ms\": 8.2,\n        \"bearing_deg\": 312\n      },\n      \"terrain\": {\n        \"elevation_m\": 547.2,\n        \"slope_deg\": 3.1,\n        \"aspect_deg\": 180\n      },\n      \"atmospheric_stability\": \"D\",\n      \"nearby_entities\": [\n        {\n          \"id\": \"sensor_h2s_021\",\n          \"distance_m\": 184.2,\n          \"bearing_deg\": 271,\n          \"reading_ppm\": 0.4\n        },\n        {\n          \"id\": \"sensor_h2s_024\",\n          \"distance_m\": 412.7,\n          \"bearing_deg\": 88,\n          \"reading_ppm\": 0.1\n        }\n      ],\n      \"jurisdiction\": {\n        \"authority\": \"TCEQ\",\n        \"permit_id\": \"PSDTX1234\",\n        \"limit_ppm\": 10\n      },\n      \"asset_proximity\": [\n        {\n          \"asset_id\": \"wellhead_07\",\n          \"distance_m\": 96.1,\n          \"type\": \"wellhead\"\n        }\n      ]\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.93,\n    \"model_version\": \"plume-v4.1.2\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"terrain:USGS-3DEP-1m\",\n      \"met:NOAA-HRRR-2026-04-21T03Z\",\n      \"jurisdiction:TCEQ-2025-Q4\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 87\n  }\n}"
            }
          ]
        },
        {
          "name": "Batch context resolution (up to 500 devices)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/context/batch?device_ids=[\"sensor_h2s_023\",\"sensor_h2s_024\",\"drone_01\"]",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "context",
                "batch"
              ],
              "query": [
                {
                  "key": "device_ids",
                  "value": "[\"sensor_h2s_023\",\"sensor_h2s_024\",\"drone_01\"]",
                  "description": "JSON-encoded array of device IDs. Max 500 per request.",
                  "disabled": false
                },
                {
                  "key": "include",
                  "value": "",
                  "description": "Comma-separated context fields to include (see /context).",
                  "disabled": true
                }
              ]
            },
            "description": "Resolves SpatialState for up to 500 devices in a single request. Partial failures\nare represented with `null` result entries and an error sub-object.\n\n**Pricing:** $0.001 / device\n\n`GET /context/batch`\n\n_operationId:_ `getContextBatch`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Batch context resolved.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/context/batch?device_ids=[\"sensor_h2s_023\",\"sensor_h2s_024\",\"drone_01\"]",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "context",
                    "batch"
                  ],
                  "query": [
                    {
                      "key": "device_ids",
                      "value": "[\"sensor_h2s_023\",\"sensor_h2s_024\",\"drone_01\"]",
                      "description": "JSON-encoded array of device IDs. Max 500 per request.",
                      "disabled": false
                    },
                    {
                      "key": "include",
                      "value": "",
                      "description": "Comma-separated context fields to include (see /context).",
                      "disabled": true
                    }
                  ]
                },
                "description": "Resolves SpatialState for up to 500 devices in a single request. Partial failures\nare represented with `null` result entries and an error sub-object.\n\n**Pricing:** $0.001 / device\n\n`GET /context/batch`\n\n_operationId:_ `getContextBatch`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Batch context resolved.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"count\": 3,\n    \"succeeded\": 3,\n    \"failed\": 0,\n    \"items\": [\n      {\n        \"entity_id\": \"sensor_h2s_023\",\n        \"location\": {\n          \"lat\": 31.9686,\n          \"lon\": -99.9018,\n          \"alt_m\": 547.2,\n          \"h3_index\": \"8944c0ba857ffff\",\n          \"indoor\": null\n        },\n        \"time\": \"2026-04-21T03:14:22Z\",\n        \"context\": {\n          \"wind_vector\": {\n            \"speed_ms\": 8.2,\n            \"bearing_deg\": 312\n          },\n          \"atmospheric_stability\": \"D\"\n        }\n      },\n      {\n        \"entity_id\": \"sensor_h2s_024\",\n        \"location\": {\n          \"lat\": 31.969,\n          \"lon\": -99.9012,\n          \"alt_m\": 548.0,\n          \"h3_index\": \"8944c0ba853ffff\",\n          \"indoor\": null\n        },\n        \"time\": \"2026-04-21T03:14:22Z\",\n        \"context\": {\n          \"wind_vector\": {\n            \"speed_ms\": 8.2,\n            \"bearing_deg\": 312\n          },\n          \"atmospheric_stability\": \"D\"\n        }\n      },\n      {\n        \"entity_id\": \"drone_01\",\n        \"location\": {\n          \"lat\": 31.9701,\n          \"lon\": -99.9024,\n          \"alt_m\": 612.5,\n          \"h3_index\": \"8944c0ba84bffff\",\n          \"indoor\": null\n        },\n        \"time\": \"2026-04-21T03:14:22Z\",\n        \"context\": {\n          \"wind_vector\": {\n            \"speed_ms\": 8.2,\n            \"bearing_deg\": 312\n          }\n        }\n      }\n    ]\n  },\n  \"meta\": {\n    \"confidence\": 0.92,\n    \"model_version\": \"plume-v4.1.2\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"terrain:USGS-3DEP-1m\",\n      \"met:NOAA-HRRR-2026-04-21T03Z\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 142\n  }\n}"
            }
          ]
        },
        {
          "name": "Proximity search",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/nearby?lat=31.96&lon=-99.9&radius_m=500",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "nearby"
              ],
              "query": [
                {
                  "key": "lat",
                  "value": "31.96",
                  "description": "WGS84 latitude of center point.",
                  "disabled": false
                },
                {
                  "key": "lon",
                  "value": "-99.9",
                  "description": "WGS84 longitude of center point.",
                  "disabled": false
                },
                {
                  "key": "radius_m",
                  "value": "500",
                  "description": "Search radius in meters. Max 50,000 m.",
                  "disabled": false
                },
                {
                  "key": "type",
                  "value": "gas_sensor",
                  "description": "Filter by entity type. Built-in values: gas_sensor, water_sensor, rf_node, asset, personnel, drone. Any registered custom type is also accepted.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Maximum results to return. Default 50, max 500.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns all registered entities within a given radius of a coordinate, optionally\nfiltered by type. Results are ordered by distance.\n\n**Pricing:** $0.001 / call\n\n`GET /nearby`\n\n_operationId:_ `getNearby`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Nearby entities returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/nearby?lat=31.96&lon=-99.9&radius_m=500",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "nearby"
                  ],
                  "query": [
                    {
                      "key": "lat",
                      "value": "31.96",
                      "description": "WGS84 latitude of center point.",
                      "disabled": false
                    },
                    {
                      "key": "lon",
                      "value": "-99.9",
                      "description": "WGS84 longitude of center point.",
                      "disabled": false
                    },
                    {
                      "key": "radius_m",
                      "value": "500",
                      "description": "Search radius in meters. Max 50,000 m.",
                      "disabled": false
                    },
                    {
                      "key": "type",
                      "value": "gas_sensor",
                      "description": "Filter by entity type. Built-in values: gas_sensor, water_sensor, rf_node, asset, personnel, drone. Any registered custom type is also accepted.",
                      "disabled": true
                    },
                    {
                      "key": "limit",
                      "value": "50",
                      "description": "Maximum results to return. Default 50, max 500.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns all registered entities within a given radius of a coordinate, optionally\nfiltered by type. Results are ordered by distance.\n\n**Pricing:** $0.001 / call\n\n`GET /nearby`\n\n_operationId:_ `getNearby`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Nearby entities returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"center\": {\n      \"lat\": 31.96,\n      \"lon\": -99.9\n    },\n    \"radius_m\": 500,\n    \"count\": 4,\n    \"entities\": [\n      {\n        \"id\": \"sensor_h2s_023\",\n        \"type\": \"gas_sensor\",\n        \"distance_m\": 142.0,\n        \"bearing_deg\": 87\n      },\n      {\n        \"id\": \"sensor_h2s_021\",\n        \"type\": \"gas_sensor\",\n        \"distance_m\": 268.4,\n        \"bearing_deg\": 271\n      },\n      {\n        \"id\": \"sensor_h2s_024\",\n        \"type\": \"gas_sensor\",\n        \"distance_m\": 401.8,\n        \"bearing_deg\": 88\n      },\n      {\n        \"id\": \"drone_01\",\n        \"type\": \"drone\",\n        \"distance_m\": 489.2,\n        \"bearing_deg\": 12\n      }\n    ]\n  },\n  \"meta\": {\n    \"confidence\": 0.95,\n    \"model_version\": \"plume-v4.1.2\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 41\n  }\n}"
            }
          ]
        },
        {
          "name": "Polygon containment query",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/within?geometry=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "within"
              ],
              "query": [
                {
                  "key": "geometry",
                  "value": "",
                  "description": "URL-encoded GeoJSON Polygon or MultiPolygon.",
                  "disabled": false
                },
                {
                  "key": "type",
                  "value": "",
                  "description": "Entity type filter. Same built-in values as /nearby (gas_sensor, water_sensor, rf_node, asset, personnel, drone), plus any registered custom type.",
                  "disabled": true
                },
                {
                  "key": "include_context",
                  "value": "False",
                  "description": "If true, includes full SpatialState for each result (billed at $0.001/entity).",
                  "disabled": true
                }
              ]
            },
            "description": "Returns all registered entities whose location falls within a given GeoJSON polygon.\nUsed for zone-based queries — \"which sensors are inside this permit boundary?\"\n\n**Pricing:** $0.001 / call (+$0.001/entity if include_context=true)\n\n`GET /within`\n\n_operationId:_ `getWithin`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Entities within polygon returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/within?geometry=",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "within"
                  ],
                  "query": [
                    {
                      "key": "geometry",
                      "value": "",
                      "description": "URL-encoded GeoJSON Polygon or MultiPolygon.",
                      "disabled": false
                    },
                    {
                      "key": "type",
                      "value": "",
                      "description": "Entity type filter. Same built-in values as /nearby (gas_sensor, water_sensor, rf_node, asset, personnel, drone), plus any registered custom type.",
                      "disabled": true
                    },
                    {
                      "key": "include_context",
                      "value": "False",
                      "description": "If true, includes full SpatialState for each result (billed at $0.001/entity).",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns all registered entities whose location falls within a given GeoJSON polygon.\nUsed for zone-based queries — \"which sensors are inside this permit boundary?\"\n\n**Pricing:** $0.001 / call (+$0.001/entity if include_context=true)\n\n`GET /within`\n\n_operationId:_ `getWithin`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Entities within polygon returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"count\": 3,\n    \"entities\": [\n      {\n        \"id\": \"sensor_h2s_023\",\n        \"type\": \"gas_sensor\",\n        \"location\": {\n          \"lat\": 31.9686,\n          \"lon\": -99.9018,\n          \"alt_m\": 547.2,\n          \"h3_index\": \"8944c0ba857ffff\",\n          \"indoor\": null\n        }\n      },\n      {\n        \"id\": \"sensor_h2s_024\",\n        \"type\": \"gas_sensor\",\n        \"location\": {\n          \"lat\": 31.969,\n          \"lon\": -99.9012,\n          \"alt_m\": 548.0,\n          \"h3_index\": \"8944c0ba853ffff\",\n          \"indoor\": null\n        }\n      },\n      {\n        \"id\": \"wellhead_07\",\n        \"type\": \"asset\",\n        \"location\": {\n          \"lat\": 31.9682,\n          \"lon\": -99.902,\n          \"alt_m\": 547.0,\n          \"h3_index\": \"8944c0ba85bffff\",\n          \"indoor\": null\n        }\n      }\n    ]\n  },\n  \"meta\": {\n    \"confidence\": 0.97,\n    \"model_version\": \"plume-v4.1.2\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 38\n  }\n}"
            }
          ]
        },
        {
          "name": "Jurisdiction resolution for any coordinate",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/jurisdiction",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "jurisdiction"
              ],
              "query": [
                {
                  "key": "lat",
                  "value": "31.9686",
                  "description": "WGS84 latitude. Required unless device_id is provided.",
                  "disabled": true
                },
                {
                  "key": "lon",
                  "value": "-99.9018",
                  "description": "WGS84 longitude. Required unless device_id is provided.",
                  "disabled": true
                },
                {
                  "key": "device_id",
                  "value": "",
                  "description": "Alternative to lat/lon — uses the device's registered coordinates.",
                  "disabled": true
                },
                {
                  "key": "domains",
                  "value": "air,water",
                  "description": "Comma-separated domain filter. Options: air, water, noise, land, fire. Default: all.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns all applicable regulatory jurisdictions and permit obligations for a given\ncoordinate — air quality authority, watershed governance, noise ordinance, and\ncross-boundary relationships.\n\n**Pricing:** $0.0005 / call (free when device_id is passed to /context)\n\n`GET /jurisdiction`\n\n_operationId:_ `getJurisdiction`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Jurisdiction data returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/jurisdiction",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "jurisdiction"
                  ],
                  "query": [
                    {
                      "key": "lat",
                      "value": "31.9686",
                      "description": "WGS84 latitude. Required unless device_id is provided.",
                      "disabled": true
                    },
                    {
                      "key": "lon",
                      "value": "-99.9018",
                      "description": "WGS84 longitude. Required unless device_id is provided.",
                      "disabled": true
                    },
                    {
                      "key": "device_id",
                      "value": "",
                      "description": "Alternative to lat/lon — uses the device's registered coordinates.",
                      "disabled": true
                    },
                    {
                      "key": "domains",
                      "value": "air,water",
                      "description": "Comma-separated domain filter. Options: air, water, noise, land, fire. Default: all.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns all applicable regulatory jurisdictions and permit obligations for a given\ncoordinate — air quality authority, watershed governance, noise ordinance, and\ncross-boundary relationships.\n\n**Pricing:** $0.0005 / call (free when device_id is passed to /context)\n\n`GET /jurisdiction`\n\n_operationId:_ `getJurisdiction`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Jurisdiction data returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"location\": {\n      \"lat\": 31.9686,\n      \"lon\": -99.9018\n    },\n    \"jurisdiction\": {\n      \"air_quality\": {\n        \"authority\": \"TCEQ\",\n        \"permit_id\": \"PSDTX1234\",\n        \"limit_ppm\": 10\n      },\n      \"water\": {\n        \"authority\": \"TCEQ\",\n        \"watershed_id\": \"basin_colorado_mid\"\n      }\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.99,\n    \"model_version\": \"jurisdiction-v2.3.0\",\n    \"calibration_age_days\": 12,\n    \"site_calibrated\": false,\n    \"provenance\": [\n      \"jurisdiction:TCEQ-2025-Q4\",\n      \"watershed:USGS-WBD-2025\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 33\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Simulate API",
      "description": "Physics-based propagation simulations (async jobs).",
      "item": [
        {
          "name": "Atmospheric dispersion simulation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/simulate/plume",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "simulate",
                "plume"
              ]
            },
            "description": "Runs an atmospheric dispersion model for a point or area source. Tier 1 uses Gaussian\nplume (fast screening, <8 s). Tier 2 uses AERMOD-style regulatory-grade modeling\n(15–60 s). Tier 3 uses Lagrangian particle tracking for non-steady-state scenarios\n(minutes). Returns concentration isopleths, predicted readings at registered sensor\nlocations, and affected zone classifications.\n\n**Pricing:** $0.05–$0.25 / run depending on tier.\n\n`POST /simulate/plume`\n\n_operationId:_ `simulatePlume`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source\": {\n    \"lat\": 31.9642,\n    \"lon\": -99.9035,\n    \"alt_m\": 545,\n    \"emission_rate_gs\": 2.4,\n    \"stack_height_m\": 12\n  },\n  \"wind\": {\n    \"speed_ms\": 8.2,\n    \"bearing_deg\": 312\n  },\n  \"stability_class\": \"D\",\n  \"duration_min\": 60,\n  \"tier\": 2,\n  \"species\": \"H2S\",\n  \"output_receptors\": [\n    \"sensor_h2s_021\",\n    \"sensor_h2s_023\",\n    \"sensor_h2s_024\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Simulation job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/simulate/plume",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "simulate",
                    "plume"
                  ]
                },
                "description": "Runs an atmospheric dispersion model for a point or area source. Tier 1 uses Gaussian\nplume (fast screening, <8 s). Tier 2 uses AERMOD-style regulatory-grade modeling\n(15–60 s). Tier 3 uses Lagrangian particle tracking for non-steady-state scenarios\n(minutes). Returns concentration isopleths, predicted readings at registered sensor\nlocations, and affected zone classifications.\n\n**Pricing:** $0.05–$0.25 / run depending on tier.\n\n`POST /simulate/plume`\n\n_operationId:_ `simulatePlume`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"source\": {\n    \"lat\": 31.9642,\n    \"lon\": -99.9035,\n    \"alt_m\": 545,\n    \"emission_rate_gs\": 2.4,\n    \"stack_height_m\": 12\n  },\n  \"wind\": {\n    \"speed_ms\": 8.2,\n    \"bearing_deg\": 312\n  },\n  \"stability_class\": \"D\",\n  \"duration_min\": 60,\n  \"tier\": 2,\n  \"species\": \"H2S\",\n  \"output_receptors\": [\n    \"sensor_h2s_021\",\n    \"sensor_h2s_023\",\n    \"sensor_h2s_024\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Simulation job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a3f9k8qmzn7p\",\n    \"type\": \"simulate/plume\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 8,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a3f9k8qmzn7p\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Live plume tracking via Server-Sent Events",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "text/event-stream"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/simulate/plume/stream",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "simulate",
                "plume",
                "stream"
              ]
            },
            "description": "Opens a Server-Sent Events (SSE) stream that delivers a running plume\nsimulation in real time. The client POSTs a `PlumeStreamRequest` with\n`Accept: text/event-stream`; the server responds `200 OK` with\n`Content-Type: text/event-stream` and emits a sequence of named events\nuntil the simulation completes or the client disconnects.\n\n**Event types** (the SSE `event:` field):\n\n- `tick` — heartbeat with simulation clock and wind vector, emitted\n  every `tick_interval_s` seconds\n- `concentration` — updated isopleth polygons and per-receptor\n  concentrations, emitted on every tick after the field stabilises\n- `alert` — emitted when an `alert_thresholds` value is crossed at\n  any receptor or isopleth\n- `end` — terminal event with run summary; clients should stop\n  reconnecting after receiving this\n\nEvery event carries a stable `id:` field. Clients that drop the\nconnection should reconnect with `Last-Event-ID` to resume from the\nlast event seen. The official SDKs (`streamPlume` in TypeScript,\n`stream_plume` in Python) implement this reconnect-with-backoff\nbehaviour automatically.\n\n**Availability:** Site Calibration plans only.\n\n**Pricing:** $0.25 / run, billed once on `end`.\n\n`POST /simulate/plume/stream`\n\n_operationId:_ `streamPlume`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source\": {\n    \"lat\": 31.9642,\n    \"lon\": -99.9035,\n    \"alt_m\": 545,\n    \"emission_rate_gs\": 2.4,\n    \"stack_height_m\": 12\n  },\n  \"wind\": {\n    \"speed_ms\": 8.2,\n    \"bearing_deg\": 312\n  },\n  \"stability_class\": \"D\",\n  \"duration_min\": 60,\n  \"species\": \"H2S\",\n  \"output_receptors\": [\n    \"sensor_h2s_021\",\n    \"sensor_h2s_023\",\n    \"sensor_h2s_024\"\n  ],\n  \"tick_interval_s\": 5,\n  \"alert_thresholds\": {\n    \"warn\": 1.0,\n    \"action\": 5.0,\n    \"evacuate\": 10.0\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "200 SSE stream opened. The response body is a `text/event-stream",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "text/event-stream"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/simulate/plume/stream",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "simulate",
                    "plume",
                    "stream"
                  ]
                },
                "description": "Opens a Server-Sent Events (SSE) stream that delivers a running plume\nsimulation in real time. The client POSTs a `PlumeStreamRequest` with\n`Accept: text/event-stream`; the server responds `200 OK` with\n`Content-Type: text/event-stream` and emits a sequence of named events\nuntil the simulation completes or the client disconnects.\n\n**Event types** (the SSE `event:` field):\n\n- `tick` — heartbeat with simulation clock and wind vector, emitted\n  every `tick_interval_s` seconds\n- `concentration` — updated isopleth polygons and per-receptor\n  concentrations, emitted on every tick after the field stabilises\n- `alert` — emitted when an `alert_thresholds` value is crossed at\n  any receptor or isopleth\n- `end` — terminal event with run summary; clients should stop\n  reconnecting after receiving this\n\nEvery event carries a stable `id:` field. Clients that drop the\nconnection should reconnect with `Last-Event-ID` to resume from the\nlast event seen. The official SDKs (`streamPlume` in TypeScript,\n`stream_plume` in Python) implement this reconnect-with-backoff\nbehaviour automatically.\n\n**Availability:** Site Calibration plans only.\n\n**Pricing:** $0.25 / run, billed once on `end`.\n\n`POST /simulate/plume/stream`\n\n_operationId:_ `streamPlume`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"source\": {\n    \"lat\": 31.9642,\n    \"lon\": -99.9035,\n    \"alt_m\": 545,\n    \"emission_rate_gs\": 2.4,\n    \"stack_height_m\": 12\n  },\n  \"wind\": {\n    \"speed_ms\": 8.2,\n    \"bearing_deg\": 312\n  },\n  \"stability_class\": \"D\",\n  \"duration_min\": 60,\n  \"species\": \"H2S\",\n  \"output_receptors\": [\n    \"sensor_h2s_021\",\n    \"sensor_h2s_023\",\n    \"sensor_h2s_024\"\n  ],\n  \"tick_interval_s\": 5,\n  \"alert_thresholds\": {\n    \"warn\": 1.0,\n    \"action\": 5.0,\n    \"evacuate\": 10.0\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "SSE stream opened. The response body is a `text/event-stream`",
              "code": 200,
              "_postman_previewlanguage": "text",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/event-stream"
                },
                {
                  "key": "Cache-Control",
                  "value": "no-cache"
                },
                {
                  "key": "Connection",
                  "value": "keep-alive"
                }
              ],
              "body": "event: tick\nid: 1\ndata: {\"sim_time_s\":5,\"wall_time\":\"2026-04-21T03:14:27Z\",\"progress\":0.0014,\"wind_vector\":{\"speed_ms\":8.2,\"bearing_deg\":312}}\n\nevent: concentration\nid: 2\ndata: {\"sim_time_s\":10,\"isopleths\":[{\"concentration_ppm\":10,\"polygon\":{\"type\":\"Polygon\",\"coordinates\":[]}}],\"receptors\":[{\"device_id\":\"sensor_h2s_023\",\"concentration_ppm\":4.7}],\"max_concentration_ppm\":12.4}\n\nevent: alert\nid: 9\ndata: {\"sim_time_s\":45,\"threshold\":\"action\",\"threshold_ppm\":5.0,\"observed_ppm\":6.2,\"device_id\":\"sensor_h2s_023\",\"location\":{\"lat\":31.9686,\"lon\":-99.9018}}\n\nevent: end\nid: 720\ndata: {\"sim_time_s\":3600,\"reason\":\"completed\",\"summary\":{\"ticks_emitted\":720,\"alerts_emitted\":3,\"max_concentration_ppm\":58.1,\"job_id\":\"job_01hx2a3f9k8qmzn7p\"}}\n"
            }
          ]
        },
        {
          "name": "Flood and hydrological simulation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/simulate/flood",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "simulate",
                "flood"
              ]
            },
            "description": "Runs DEM-based watershed delineation, SCS Curve Number rainfall-runoff modeling,\nkinematic wave channel routing, and 2D inundation mapping. Returns flood extent\npolygons at multiple return intervals, time-to-crest forecasts, and sensors predicted\nto be inundated.\n\nEither `watershed_id` or `area` is required.\n\n**Pricing:** $0.10 / run\n\n`POST /simulate/flood`\n\n_operationId:_ `simulateFlood`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"watershed_id\": \"basin_colorado_mid\",\n  \"precip_mm\": 85,\n  \"duration_hr\": 3,\n  \"return_periods\": [\n    10,\n    100\n  ],\n  \"antecedent_moisture\": \"wet\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Simulation job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/simulate/flood",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "simulate",
                    "flood"
                  ]
                },
                "description": "Runs DEM-based watershed delineation, SCS Curve Number rainfall-runoff modeling,\nkinematic wave channel routing, and 2D inundation mapping. Returns flood extent\npolygons at multiple return intervals, time-to-crest forecasts, and sensors predicted\nto be inundated.\n\nEither `watershed_id` or `area` is required.\n\n**Pricing:** $0.10 / run\n\n`POST /simulate/flood`\n\n_operationId:_ `simulateFlood`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"watershed_id\": \"basin_colorado_mid\",\n  \"precip_mm\": 85,\n  \"duration_hr\": 3,\n  \"return_periods\": [\n    10,\n    100\n  ],\n  \"antecedent_moisture\": \"wet\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Simulation job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7kflood01\",\n    \"type\": \"simulate/flood\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 22,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7kflood01\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Single-node RF coverage simulation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/simulate/rf_coverage",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "simulate",
                "rf_coverage"
              ]
            },
            "description": "Runs the ITM/Longley-Rice terrain propagation model for a single RF node. Returns a\ncoverage probability polygon at the specified RSSI threshold, plus a raster heatmap\nand link budget summary. Either `node_id` or `lat/lon/alt_m` is required.\n\n**Pricing:** $0.08 / run\n\n`POST /simulate/rf_coverage`\n\n_operationId:_ `simulateRFCoverage`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"node_id\": \"rf_node_A7\",\n  \"frequency_mhz\": 915,\n  \"tx_power_dbm\": 20,\n  \"rssi_threshold_dbm\": -95,\n  \"antenna_height_m\": 6,\n  \"model\": \"itm\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Simulation job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/simulate/rf_coverage",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "simulate",
                    "rf_coverage"
                  ]
                },
                "description": "Runs the ITM/Longley-Rice terrain propagation model for a single RF node. Returns a\ncoverage probability polygon at the specified RSSI threshold, plus a raster heatmap\nand link budget summary. Either `node_id` or `lat/lon/alt_m` is required.\n\n**Pricing:** $0.08 / run\n\n`POST /simulate/rf_coverage`\n\n_operationId:_ `simulateRFCoverage`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"node_id\": \"rf_node_A7\",\n  \"frequency_mhz\": 915,\n  \"tx_power_dbm\": 20,\n  \"rssi_threshold_dbm\": -95,\n  \"antenna_height_m\": 6,\n  \"model\": \"itm\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Simulation job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7krf0001\",\n    \"type\": \"simulate/rf_coverage\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 11,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7krf0001\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Noise propagation simulation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/simulate/noise",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "simulate",
                "noise"
              ]
            },
            "description": "Runs ISO 9613-2 octave-band outdoor sound propagation from a point or line source.\nAccounts for geometric spreading, atmospheric absorption, ground effect, barrier\ninsertion loss, and vegetation attenuation. Returns noise contour polygons (isodB\nlines) and exceedance flags at registered receptor locations.\n\nEither `source_id` or a source geometry must be provided.\n\n**Pricing:** $0.08 / run\n\n`POST /simulate/noise`\n\n_operationId:_ `simulateNoise`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_id\": \"compressor_C4\",\n  \"octave_bands_db\": [\n    82,\n    86,\n    91,\n    95,\n    93,\n    88,\n    84,\n    79\n  ],\n  \"contour_levels_dba\": [\n    45,\n    55,\n    65\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Simulation job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/simulate/noise",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "simulate",
                    "noise"
                  ]
                },
                "description": "Runs ISO 9613-2 octave-band outdoor sound propagation from a point or line source.\nAccounts for geometric spreading, atmospheric absorption, ground effect, barrier\ninsertion loss, and vegetation attenuation. Returns noise contour polygons (isodB\nlines) and exceedance flags at registered receptor locations.\n\nEither `source_id` or a source geometry must be provided.\n\n**Pricing:** $0.08 / run\n\n`POST /simulate/noise`\n\n_operationId:_ `simulateNoise`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"source_id\": \"compressor_C4\",\n  \"octave_bands_db\": [\n    82,\n    86,\n    91,\n    95,\n    93,\n    88,\n    84,\n    79\n  ],\n  \"contour_levels_dba\": [\n    45,\n    55,\n    65\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Simulation job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7knoise01\",\n    \"type\": \"simulate/noise\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 14,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7knoise01\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Thermal / heat diffusion simulation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/simulate/thermal",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "simulate",
                "thermal"
              ]
            },
            "description": "Models heat propagation from industrial sources, fire events, or equipment failures.\nReturns time-to-temperature-threshold at monitored locations and hot zone polygons.\n\n**Pricing:** $0.08 / run\n\n`POST /simulate/thermal`\n\n_operationId:_ `simulateThermal`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source\": {\n    \"lat\": 31.9642,\n    \"lon\": -99.9035,\n    \"power_kw\": 850,\n    \"temperature_c\": 240\n  },\n  \"duration_min\": 120,\n  \"threshold_c\": [\n    40,\n    60,\n    80\n  ],\n  \"output_receptors\": [\n    \"sensor_temp_07\",\n    \"sensor_temp_12\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Simulation job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/simulate/thermal",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "simulate",
                    "thermal"
                  ]
                },
                "description": "Models heat propagation from industrial sources, fire events, or equipment failures.\nReturns time-to-temperature-threshold at monitored locations and hot zone polygons.\n\n**Pricing:** $0.08 / run\n\n`POST /simulate/thermal`\n\n_operationId:_ `simulateThermal`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"source\": {\n    \"lat\": 31.9642,\n    \"lon\": -99.9035,\n    \"power_kw\": 850,\n    \"temperature_c\": 240\n  },\n  \"duration_min\": 120,\n  \"threshold_c\": [\n    40,\n    60,\n    80\n  ],\n  \"output_receptors\": [\n    \"sensor_temp_07\",\n    \"sensor_temp_12\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Simulation job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7kthermal\",\n    \"type\": \"simulate/thermal\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 12,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7kthermal\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Fire spread simulation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/simulate/fire",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "simulate",
                "fire"
              ]
            },
            "description": "Models wildfire spread using terrain, fuel model, and weather conditions. Returns fire\nperimeter polygons at specified time intervals, rate-of-spread vectors, and smoke plume\ntrajectory (linked to `/simulate/plume` for full smoke transport).\n\n**Pricing:** $0.15 / run\n\n`POST /simulate/fire`\n\n_operationId:_ `simulateFire`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"ignition_point\": {\n    \"type\": \"Point\",\n    \"coordinates\": [\n      -119.42,\n      34.21\n    ]\n  },\n  \"fuel_model\": \"GR2\",\n  \"weather\": {\n    \"wind_speed_ms\": 8.3,\n    \"wind_bearing_deg\": 225,\n    \"rh_pct\": 12,\n    \"temp_c\": 38\n  },\n  \"duration_hr\": 24,\n  \"output_intervals_hr\": [\n    1,\n    4,\n    12,\n    24\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Simulation job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/simulate/fire",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "simulate",
                    "fire"
                  ]
                },
                "description": "Models wildfire spread using terrain, fuel model, and weather conditions. Returns fire\nperimeter polygons at specified time intervals, rate-of-spread vectors, and smoke plume\ntrajectory (linked to `/simulate/plume` for full smoke transport).\n\n**Pricing:** $0.15 / run\n\n`POST /simulate/fire`\n\n_operationId:_ `simulateFire`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"ignition_point\": {\n    \"type\": \"Point\",\n    \"coordinates\": [\n      -119.42,\n      34.21\n    ]\n  },\n  \"fuel_model\": \"GR2\",\n  \"weather\": {\n    \"wind_speed_ms\": 8.3,\n    \"wind_bearing_deg\": 225,\n    \"rh_pct\": 12,\n    \"temp_c\": 38\n  },\n  \"duration_hr\": 24,\n  \"output_intervals_hr\": [\n    1,\n    4,\n    12,\n    24\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Simulation job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7kfire001\",\n    \"type\": \"simulate/fire\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 42,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7kfire001\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "RF API",
      "description": "Radio-frequency coverage, link budget, and mesh analysis.",
      "item": [
        {
          "name": "Coverage polygon for a registered node",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/rf/coverage?node=rf_node_A7",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "rf",
                "coverage"
              ],
              "query": [
                {
                  "key": "node",
                  "value": "rf_node_A7",
                  "description": "Registered RF node ID.",
                  "disabled": false
                },
                {
                  "key": "threshold_dbm",
                  "value": "-92",
                  "description": "RSSI threshold in dBm. Default -90 dBm.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns the coverage probability polygon for a registered RF node at a given RSSI\nthreshold. Cached per node until terrain or node configuration changes.\n\n**Pricing:** $0.08 / call\n\n`GET /rf/coverage`\n\n_operationId:_ `getRFCoverage`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Coverage polygon returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/rf/coverage?node=rf_node_A7",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "rf",
                    "coverage"
                  ],
                  "query": [
                    {
                      "key": "node",
                      "value": "rf_node_A7",
                      "description": "Registered RF node ID.",
                      "disabled": false
                    },
                    {
                      "key": "threshold_dbm",
                      "value": "-92",
                      "description": "RSSI threshold in dBm. Default -90 dBm.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns the coverage probability polygon for a registered RF node at a given RSSI\nthreshold. Cached per node until terrain or node configuration changes.\n\n**Pricing:** $0.08 / call\n\n`GET /rf/coverage`\n\n_operationId:_ `getRFCoverage`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Coverage polygon returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"node_id\": \"rf_node_A7\",\n    \"threshold_dbm\": -92,\n    \"coverage_polygon\": {\n      \"type\": \"Polygon\",\n      \"coordinates\": [\n        [\n          [\n            -99.911,\n            31.962\n          ],\n          [\n            -99.901,\n            31.962\n          ],\n          [\n            -99.901,\n            31.972\n          ],\n          [\n            -99.911,\n            31.972\n          ],\n          [\n            -99.911,\n            31.962\n          ]\n        ]\n      ]\n    },\n    \"coverage_area_km2\": 4.12,\n    \"max_range_m\": 1820,\n    \"cached\": true,\n    \"cache_age_min\": 17\n  },\n  \"meta\": {\n    \"confidence\": 0.91,\n    \"model_version\": \"rf-itm-v3.2.0\",\n    \"calibration_age_days\": 22,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"terrain:USGS-3DEP-1m\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 64\n  }\n}"
            }
          ]
        },
        {
          "name": "Point-to-point RF link budget",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/rf/link?from=rf_node_A7&to=rf_node_B3",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "rf",
                "link"
              ],
              "query": [
                {
                  "key": "from",
                  "value": "rf_node_A7",
                  "description": "Source node ID.",
                  "disabled": false
                },
                {
                  "key": "to",
                  "value": "rf_node_B3",
                  "description": "Target node ID.",
                  "disabled": false
                },
                {
                  "key": "reliability_pct",
                  "value": "99.0",
                  "description": "Required link reliability percentage. Default 99.0.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns the link budget between two registered nodes — predicted RSSI, fade margin,\nFresnel zone clearance, and obstruction analysis. Returns a pass/fail recommendation\ngiven the specified reliability threshold.\n\n**Pricing:** $0.03 / call\n\n`GET /rf/link`\n\n_operationId:_ `getRFLink`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Link budget calculated.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/rf/link?from=rf_node_A7&to=rf_node_B3",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "rf",
                    "link"
                  ],
                  "query": [
                    {
                      "key": "from",
                      "value": "rf_node_A7",
                      "description": "Source node ID.",
                      "disabled": false
                    },
                    {
                      "key": "to",
                      "value": "rf_node_B3",
                      "description": "Target node ID.",
                      "disabled": false
                    },
                    {
                      "key": "reliability_pct",
                      "value": "99.0",
                      "description": "Required link reliability percentage. Default 99.0.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns the link budget between two registered nodes — predicted RSSI, fade margin,\nFresnel zone clearance, and obstruction analysis. Returns a pass/fail recommendation\ngiven the specified reliability threshold.\n\n**Pricing:** $0.03 / call\n\n`GET /rf/link`\n\n_operationId:_ `getRFLink`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Link budget calculated.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"from\": \"rf_node_A7\",\n    \"to\": \"rf_node_B3\",\n    \"distance_m\": 1842.0,\n    \"predicted_rssi_dbm\": -78.4,\n    \"fade_margin_db\": 11.6,\n    \"fresnel_clearance_pct\": 84.0,\n    \"obstructions\": [],\n    \"link_viable\": true,\n    \"reliability_at_threshold\": 99.4\n  },\n  \"meta\": {\n    \"confidence\": 0.94,\n    \"model_version\": \"rf-itm-v3.2.0\",\n    \"calibration_age_days\": 22,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"terrain:USGS-3DEP-1m\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 56\n  }\n}"
            }
          ]
        },
        {
          "name": "Coverage gap heatmap within an area",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/rf/gaps?area=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "rf",
                "gaps"
              ],
              "query": [
                {
                  "key": "area",
                  "value": "",
                  "description": "URL-encoded GeoJSON Polygon defining the area to analyze.",
                  "disabled": false
                },
                {
                  "key": "threshold_dbm",
                  "value": "-90",
                  "description": "RSSI below which a cell is considered a gap. Default -90 dBm.",
                  "disabled": true
                },
                {
                  "key": "node_ids",
                  "value": "",
                  "description": "Comma-separated node IDs to analyze against. Default all registered nodes in area.",
                  "disabled": true
                }
              ]
            },
            "description": "Identifies coverage gaps within a defined area given existing node topology. Returns a\nGeoJSON heatmap of gap severity and a list of H3 cells with insufficient coverage.\n\n**Pricing:** $0.05 / call\n\n`GET /rf/gaps`\n\n_operationId:_ `getRFGaps`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Coverage gap analysis returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/rf/gaps?area=",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "rf",
                    "gaps"
                  ],
                  "query": [
                    {
                      "key": "area",
                      "value": "",
                      "description": "URL-encoded GeoJSON Polygon defining the area to analyze.",
                      "disabled": false
                    },
                    {
                      "key": "threshold_dbm",
                      "value": "-90",
                      "description": "RSSI below which a cell is considered a gap. Default -90 dBm.",
                      "disabled": true
                    },
                    {
                      "key": "node_ids",
                      "value": "",
                      "description": "Comma-separated node IDs to analyze against. Default all registered nodes in area.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Identifies coverage gaps within a defined area given existing node topology. Returns a\nGeoJSON heatmap of gap severity and a list of H3 cells with insufficient coverage.\n\n**Pricing:** $0.05 / call\n\n`GET /rf/gaps`\n\n_operationId:_ `getRFGaps`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Coverage gap analysis returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"coverage_pct\": 67.4,\n    \"gap_pct\": 32.6,\n    \"gap_heatmap\": {\n      \"type\": \"FeatureCollection\",\n      \"features\": []\n    },\n    \"gap_cells_h3\": [\n      \"8944c0ba8a3ffff\",\n      \"8944c0ba8a7ffff\",\n      \"8944c0ba8abffff\"\n    ],\n    \"worst_gap_location\": {\n      \"lat\": 31.9712,\n      \"lon\": -99.8945,\n      \"best_rssi_dbm\": -101.4\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.88,\n    \"model_version\": \"rf-itm-v3.2.0\",\n    \"calibration_age_days\": 22,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"terrain:USGS-3DEP-1m\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 192\n  }\n}"
            }
          ]
        },
        {
          "name": "Full mesh connectivity matrix",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/rf/mesh/viability",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "rf",
                "mesh",
                "viability"
              ]
            },
            "description": "Computes the full link budget matrix for a mesh network — every node-to-node pair,\nwith failure probability based on calibrated path loss models. Returns a connectivity\nmatrix, mesh reliability score, single-points-of-failure, and failure scenario analysis.\n\nAsync job; typical completion 15–40 seconds for networks up to 200 nodes.\n\n**Pricing:** $0.15 / run\n\n`POST /rf/mesh/viability`\n\n_operationId:_ `rfMeshViability`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"node_ids\": [\n    \"rf_node_A7\",\n    \"rf_node_B3\",\n    \"rf_node_C2\",\n    \"rf_node_D9\"\n  ],\n  \"min_path_reliability_pct\": 99.5,\n  \"failure_scenarios\": [\n    {\n      \"node_id\": \"rf_node_A7\",\n      \"failure_probability\": 0.05\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Mesh viability job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/rf/mesh/viability",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "rf",
                    "mesh",
                    "viability"
                  ]
                },
                "description": "Computes the full link budget matrix for a mesh network — every node-to-node pair,\nwith failure probability based on calibrated path loss models. Returns a connectivity\nmatrix, mesh reliability score, single-points-of-failure, and failure scenario analysis.\n\nAsync job; typical completion 15–40 seconds for networks up to 200 nodes.\n\n**Pricing:** $0.15 / run\n\n`POST /rf/mesh/viability`\n\n_operationId:_ `rfMeshViability`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"node_ids\": [\n    \"rf_node_A7\",\n    \"rf_node_B3\",\n    \"rf_node_C2\",\n    \"rf_node_D9\"\n  ],\n  \"min_path_reliability_pct\": 99.5,\n  \"failure_scenarios\": [\n    {\n      \"node_id\": \"rf_node_A7\",\n      \"failure_probability\": 0.05\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Mesh viability job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7kmesh001\",\n    \"type\": \"rf/mesh/viability\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 28,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7kmesh001\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Node placement optimizer for RF coverage",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/rf/optimize/placement",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "rf",
                "optimize",
                "placement"
              ]
            },
            "description": "Given existing mesh topology, terrain, and coverage requirements, returns the top-N\ncandidate locations that maximize marginal coverage gain.\n\n**Pricing:** $1.00–$5.00 / run\n\n`POST /rf/optimize/placement`\n\n_operationId:_ `rfOptimizePlacement`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"area\": {\n    \"type\": \"Polygon\",\n    \"coordinates\": [\n      [\n        [\n          \"-99.92 - 31.95\",\n          [\n            -99.88,\n            31.95\n          ],\n          [\n            -99.88,\n            31.99\n          ],\n          [\n            -99.92,\n            31.99\n          ],\n          [\n            -99.92,\n            31.95\n          ]\n        ]\n      ]\n    ]\n  },\n  \"coverage_threshold\": 0.95,\n  \"existing_nodes\": [\n    \"rf_node_A7\",\n    \"rf_node_B3\"\n  ],\n  \"candidate_count\": 5,\n  \"frequency_mhz\": 915,\n  \"constraints\": {\n    \"min_distance_from_edge_m\": 50,\n    \"require_road_access\": true\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Placement optimization job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/rf/optimize/placement",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "rf",
                    "optimize",
                    "placement"
                  ]
                },
                "description": "Given existing mesh topology, terrain, and coverage requirements, returns the top-N\ncandidate locations that maximize marginal coverage gain.\n\n**Pricing:** $1.00–$5.00 / run\n\n`POST /rf/optimize/placement`\n\n_operationId:_ `rfOptimizePlacement`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"area\": {\n    \"type\": \"Polygon\",\n    \"coordinates\": [\n      [\n        [\n          \"-99.92 - 31.95\",\n          [\n            -99.88,\n            31.95\n          ],\n          [\n            -99.88,\n            31.99\n          ],\n          [\n            -99.92,\n            31.99\n          ],\n          [\n            -99.92,\n            31.95\n          ]\n        ]\n      ]\n    ]\n  },\n  \"coverage_threshold\": 0.95,\n  \"existing_nodes\": [\n    \"rf_node_A7\",\n    \"rf_node_B3\"\n  ],\n  \"candidate_count\": 5,\n  \"frequency_mhz\": 915,\n  \"constraints\": {\n    \"min_distance_from_edge_m\": 50,\n    \"require_road_access\": true\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Placement optimization job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7krfopt01\",\n    \"type\": \"rf/optimize/placement\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 180,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7krfopt01\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Optimize API",
      "description": "Node and sensor placement optimization; coverage and gap analysis.",
      "item": [
        {
          "name": "General node placement optimizer",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/optimize/node_placement",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "optimize",
                "node_placement"
              ]
            },
            "description": "Generalizes RF placement to any monitoring objective — air quality sensor spacing\n(accounting for plume physics), flood gauge placement (watershed coverage), or\nacoustic monitor placement (source coverage). Returns ranked candidate locations with\nobjective-specific marginal gain scores.\n\n**Pricing:** $1.00–$5.00 / run\n\n`POST /optimize/node_placement`\n\n_operationId:_ `optimizeNodePlacement`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"area\": {\n    \"type\": \"Polygon\",\n    \"coordinates\": [\n      [\n        [\n          \"-99.92 - 31.95\",\n          [\n            -99.88,\n            31.95\n          ],\n          [\n            -99.88,\n            31.99\n          ],\n          [\n            -99.92,\n            31.99\n          ],\n          [\n            -99.92,\n            31.95\n          ]\n        ]\n      ]\n    ]\n  },\n  \"coverage_threshold\": 0.9,\n  \"existing_nodes\": [\n    \"sensor_h2s_021\",\n    \"sensor_h2s_023\"\n  ],\n  \"objective\": \"plume_detection\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Node placement job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/optimize/node_placement",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "optimize",
                    "node_placement"
                  ]
                },
                "description": "Generalizes RF placement to any monitoring objective — air quality sensor spacing\n(accounting for plume physics), flood gauge placement (watershed coverage), or\nacoustic monitor placement (source coverage). Returns ranked candidate locations with\nobjective-specific marginal gain scores.\n\n**Pricing:** $1.00–$5.00 / run\n\n`POST /optimize/node_placement`\n\n_operationId:_ `optimizeNodePlacement`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"area\": {\n    \"type\": \"Polygon\",\n    \"coordinates\": [\n      [\n        [\n          \"-99.92 - 31.95\",\n          [\n            -99.88,\n            31.95\n          ],\n          [\n            -99.88,\n            31.99\n          ],\n          [\n            -99.92,\n            31.99\n          ],\n          [\n            -99.92,\n            31.95\n          ]\n        ]\n      ]\n    ]\n  },\n  \"coverage_threshold\": 0.9,\n  \"existing_nodes\": [\n    \"sensor_h2s_021\",\n    \"sensor_h2s_023\"\n  ],\n  \"objective\": \"plume_detection\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Node placement job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7knode001\",\n    \"type\": \"optimize/node_placement\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 120,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7knode001\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Vertical-aware sensor placement optimization",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/optimize/sensor_placement",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "optimize",
                "sensor_placement"
              ]
            },
            "description": "Recommends sensor placement for a given ZOOID vertical — accounts for the vertical's\nspecific measurement physics, regulatory requirements, and deployment constraints.\n\n**Pricing:** $2.00–$5.00 / run\n\n`POST /optimize/sensor_placement`\n\n_operationId:_ `optimizeSensorPlacement`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"vertical\": \"V01\",\n  \"area\": {\n    \"type\": \"Polygon\",\n    \"coordinates\": [\n      [\n        [\n          \"-99.92 - 31.95\",\n          [\n            -99.88,\n            31.95\n          ],\n          [\n            -99.88,\n            31.99\n          ],\n          [\n            -99.92,\n            31.99\n          ],\n          [\n            -99.92,\n            31.95\n          ]\n        ]\n      ]\n    ]\n  },\n  \"target_coverage_pct\": 0.95,\n  \"budget_nodes\": 8\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Sensor placement job accepted.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/optimize/sensor_placement",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "optimize",
                    "sensor_placement"
                  ]
                },
                "description": "Recommends sensor placement for a given ZOOID vertical — accounts for the vertical's\nspecific measurement physics, regulatory requirements, and deployment constraints.\n\n**Pricing:** $2.00–$5.00 / run\n\n`POST /optimize/sensor_placement`\n\n_operationId:_ `optimizeSensorPlacement`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"vertical\": \"V01\",\n  \"area\": {\n    \"type\": \"Polygon\",\n    \"coordinates\": [\n      [\n        [\n          \"-99.92 - 31.95\",\n          [\n            -99.88,\n            31.95\n          ],\n          [\n            -99.88,\n            31.99\n          ],\n          [\n            -99.92,\n            31.99\n          ],\n          [\n            -99.92,\n            31.95\n          ]\n        ]\n      ]\n    ]\n  },\n  \"target_coverage_pct\": 0.95,\n  \"budget_nodes\": 8\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Sensor placement job accepted.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a4q7ksensor01\",\n    \"type\": \"optimize/sensor_placement\",\n    \"status\": \"queued\",\n    \"eta_seconds\": 240,\n    \"poll_url\": \"https://api.geog.ai/v1/jobs/job_01hx2a4q7ksensor01\",\n    \"webhook_delivered\": false\n  },\n  \"meta\": {\n    \"request_id\": \"req_01hx29sknd4bqyt8r\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Coverage analysis for an area",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/coverage?area=&type=gas_sensor",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "coverage"
              ],
              "query": [
                {
                  "key": "area",
                  "value": "",
                  "description": "URL-encoded GeoJSON polygon defining the area of interest.",
                  "disabled": false
                },
                {
                  "key": "type",
                  "value": "gas_sensor",
                  "description": "Sensor type to assess coverage for.",
                  "disabled": false
                }
              ]
            },
            "description": "Returns the current monitoring coverage fraction for a given area and sensor type.\nCoverage is defined by the spatial footprint of registered sensors given their\ndetection physics.\n\n**Pricing:** $0.01 / call\n\n`GET /coverage`\n\n_operationId:_ `getCoverage`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Coverage analysis returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/coverage?area=&type=gas_sensor",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "coverage"
                  ],
                  "query": [
                    {
                      "key": "area",
                      "value": "",
                      "description": "URL-encoded GeoJSON polygon defining the area of interest.",
                      "disabled": false
                    },
                    {
                      "key": "type",
                      "value": "gas_sensor",
                      "description": "Sensor type to assess coverage for.",
                      "disabled": false
                    }
                  ]
                },
                "description": "Returns the current monitoring coverage fraction for a given area and sensor type.\nCoverage is defined by the spatial footprint of registered sensors given their\ndetection physics.\n\n**Pricing:** $0.01 / call\n\n`GET /coverage`\n\n_operationId:_ `getCoverage`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Coverage analysis returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"sensor_type\": \"gas_sensor\",\n    \"area_km2\": 12.4,\n    \"covered_km2\": 8.16,\n    \"coverage_pct\": 65.8,\n    \"active_sensors\": 14,\n    \"coverage_polygon\": {\n      \"type\": \"Polygon\",\n      \"coordinates\": [\n        [\n          [\n            -99.911,\n            31.962\n          ],\n          [\n            -99.901,\n            31.962\n          ],\n          [\n            -99.901,\n            31.972\n          ],\n          [\n            -99.911,\n            31.972\n          ],\n          [\n            -99.911,\n            31.962\n          ]\n        ]\n      ]\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.92,\n    \"model_version\": \"coverage-v1.4.0\",\n    \"calibration_age_days\": 18,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 72\n  }\n}"
            }
          ]
        },
        {
          "name": "Monitoring gap analysis for an area",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/gaps?area=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "gaps"
              ],
              "query": [
                {
                  "key": "area",
                  "value": "",
                  "description": "URL-encoded GeoJSON polygon defining the area of interest.",
                  "disabled": false
                },
                {
                  "key": "threshold_m",
                  "value": "400",
                  "description": "Maximum acceptable distance from any sensor in metres. Default 500 m.",
                  "disabled": true
                },
                {
                  "key": "type",
                  "value": "",
                  "description": "Sensor type filter.",
                  "disabled": true
                }
              ]
            },
            "description": "Identifies monitoring gaps within a defined area — H3 cells where no sensor provides\nadequate coverage given detection physics. Returns a GeoJSON gap heatmap and summary\nstatistics.\n\n**Pricing:** $0.01 / call\n\n`GET /gaps`\n\n_operationId:_ `getGaps`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Gap analysis returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/gaps?area=",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "gaps"
                  ],
                  "query": [
                    {
                      "key": "area",
                      "value": "",
                      "description": "URL-encoded GeoJSON polygon defining the area of interest.",
                      "disabled": false
                    },
                    {
                      "key": "threshold_m",
                      "value": "400",
                      "description": "Maximum acceptable distance from any sensor in metres. Default 500 m.",
                      "disabled": true
                    },
                    {
                      "key": "type",
                      "value": "",
                      "description": "Sensor type filter.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Identifies monitoring gaps within a defined area — H3 cells where no sensor provides\nadequate coverage given detection physics. Returns a GeoJSON gap heatmap and summary\nstatistics.\n\n**Pricing:** $0.01 / call\n\n`GET /gaps`\n\n_operationId:_ `getGaps`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Gap analysis returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"gap_pct\": 34.2,\n    \"gap_heatmap\": {\n      \"type\": \"FeatureCollection\",\n      \"features\": []\n    },\n    \"gap_cells_h3\": [\n      \"8944c0ba8a3ffff\",\n      \"8944c0ba8a7ffff\"\n    ],\n    \"largest_gap_area_km2\": 1.8,\n    \"largest_gap_centroid\": {\n      \"lat\": 31.9714,\n      \"lon\": -99.8946\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.9,\n    \"model_version\": \"coverage-v1.4.0\",\n    \"calibration_age_days\": 18,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 96\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Trajectory API",
      "description": "Spatiotemporal trajectory storage, retrieval, and prediction.",
      "item": [
        {
          "name": "Trajectory history for a moving entity",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/trajectory?entity_id=drone_01&from=2026-04-21T02:00:00Z&to=2026-04-21T03:00:00Z",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "trajectory"
              ],
              "query": [
                {
                  "key": "entity_id",
                  "value": "drone_01",
                  "description": "Registered entity ID (drone, vehicle, or personnel).",
                  "disabled": false
                },
                {
                  "key": "from",
                  "value": "2026-04-21T02:00:00Z",
                  "description": "Start of time window (ISO 8601).",
                  "disabled": false
                },
                {
                  "key": "to",
                  "value": "2026-04-21T03:00:00Z",
                  "description": "End of time window (ISO 8601). Max window 30 days.",
                  "disabled": false
                },
                {
                  "key": "resolution_s",
                  "value": "0",
                  "description": "Temporal resolution of returned positions in seconds. Default raw (all recorded positions).",
                  "disabled": true
                }
              ]
            },
            "description": "Returns the stored trajectory (sequence of positions with timestamps and uncertainty\nbounds) for a registered moving entity over a specified time window.\n\n**Pricing:** $0.002 / call\n\n`GET /trajectory`\n\n_operationId:_ `getTrajectory`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Trajectory returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/trajectory?entity_id=drone_01&from=2026-04-21T02:00:00Z&to=2026-04-21T03:00:00Z",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "trajectory"
                  ],
                  "query": [
                    {
                      "key": "entity_id",
                      "value": "drone_01",
                      "description": "Registered entity ID (drone, vehicle, or personnel).",
                      "disabled": false
                    },
                    {
                      "key": "from",
                      "value": "2026-04-21T02:00:00Z",
                      "description": "Start of time window (ISO 8601).",
                      "disabled": false
                    },
                    {
                      "key": "to",
                      "value": "2026-04-21T03:00:00Z",
                      "description": "End of time window (ISO 8601). Max window 30 days.",
                      "disabled": false
                    },
                    {
                      "key": "resolution_s",
                      "value": "0",
                      "description": "Temporal resolution of returned positions in seconds. Default raw (all recorded positions).",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns the stored trajectory (sequence of positions with timestamps and uncertainty\nbounds) for a registered moving entity over a specified time window.\n\n**Pricing:** $0.002 / call\n\n`GET /trajectory`\n\n_operationId:_ `getTrajectory`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Trajectory returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"entity_id\": \"drone_01\",\n    \"window\": {\n      \"from\": \"2026-04-21T02:00:00Z\",\n      \"to\": \"2026-04-21T03:00:00Z\"\n    },\n    \"point_count\": 3,\n    \"positions\": [\n      {\n        \"time\": \"2026-04-21T02:00:00Z\",\n        \"lat\": 31.9701,\n        \"lon\": -99.9024,\n        \"alt_m\": 612.5,\n        \"uncertainty_m\": 1.2\n      },\n      {\n        \"time\": \"2026-04-21T02:30:00Z\",\n        \"lat\": 31.9712,\n        \"lon\": -99.9018,\n        \"alt_m\": 615.0,\n        \"uncertainty_m\": 1.4\n      },\n      {\n        \"time\": \"2026-04-21T03:00:00Z\",\n        \"lat\": 31.9724,\n        \"lon\": -99.9011,\n        \"alt_m\": 618.2,\n        \"uncertainty_m\": 1.6\n      }\n    ],\n    \"geojson_linestring\": {\n      \"type\": \"LineString\",\n      \"coordinates\": [\n        [\n          -99.9024,\n          31.9701,\n          612.5\n        ],\n        [\n          -99.9018,\n          31.9712,\n          615.0\n        ],\n        [\n          -99.9011,\n          31.9724,\n          618.2\n        ]\n      ]\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.96,\n    \"model_version\": \"trajectory-v2.0.1\",\n    \"calibration_age_days\": 30,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"telemetry:drone-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 49\n  }\n}"
            }
          ]
        },
        {
          "name": "Trajectory prediction / dead reckoning",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/trajectory/predict",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "trajectory",
                "predict"
              ]
            },
            "description": "Predicts the future trajectory of a moving entity given current position, velocity,\nand historical movement patterns. Returns a predicted path with expanding uncertainty\nbounds. Used for drone flight path prediction, fleet routing optimization, and\npersonnel zone arrival forecasting.\n\n**Pricing:** $0.005 / call\n\n`POST /trajectory/predict`\n\n_operationId:_ `trajectoryPredict`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"entity_id\": \"drone_01\",\n  \"lookahead_min\": 30,\n  \"mission_plan\": {\n    \"type\": \"LineString\",\n    \"coordinates\": [\n      [\n        -99.9024,\n        31.9701\n      ],\n      [\n        -99.898,\n        31.9755\n      ],\n      [\n        -99.8932,\n        31.981\n      ]\n    ]\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "200 Trajectory prediction returned.",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/trajectory/predict",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "trajectory",
                    "predict"
                  ]
                },
                "description": "Predicts the future trajectory of a moving entity given current position, velocity,\nand historical movement patterns. Returns a predicted path with expanding uncertainty\nbounds. Used for drone flight path prediction, fleet routing optimization, and\npersonnel zone arrival forecasting.\n\n**Pricing:** $0.005 / call\n\n`POST /trajectory/predict`\n\n_operationId:_ `trajectoryPredict`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"entity_id\": \"drone_01\",\n  \"lookahead_min\": 30,\n  \"mission_plan\": {\n    \"type\": \"LineString\",\n    \"coordinates\": [\n      [\n        -99.9024,\n        31.9701\n      ],\n      [\n        -99.898,\n        31.9755\n      ],\n      [\n        -99.8932,\n        31.981\n      ]\n    ]\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Trajectory prediction returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"entity_id\": \"drone_01\",\n    \"predicted_positions\": [\n      {\n        \"time\": \"2026-04-21T03:10:00Z\",\n        \"lat\": 31.974,\n        \"lon\": -99.9,\n        \"alt_m\": 620.0,\n        \"uncertainty_m\": 4.2\n      },\n      {\n        \"time\": \"2026-04-21T03:20:00Z\",\n        \"lat\": 31.976,\n        \"lon\": -99.898,\n        \"alt_m\": 622.4,\n        \"uncertainty_m\": 8.7\n      },\n      {\n        \"time\": \"2026-04-21T03:30:00Z\",\n        \"lat\": 31.978,\n        \"lon\": -99.896,\n        \"alt_m\": 624.1,\n        \"uncertainty_m\": 14.1\n      }\n    ],\n    \"predicted_path\": {\n      \"type\": \"LineString\",\n      \"coordinates\": [\n        [\n          -99.9,\n          31.974,\n          620.0\n        ],\n        [\n          -99.898,\n          31.976,\n          622.4\n        ],\n        [\n          -99.896,\n          31.978,\n          624.1\n        ]\n      ]\n    },\n    \"uncertainty_corridor\": {\n      \"type\": \"Polygon\",\n      \"coordinates\": [\n        [\n          [\n            -99.9004,\n            31.9738\n          ],\n          [\n            -99.8956,\n            31.9778\n          ],\n          [\n            -99.8964,\n            31.9784\n          ],\n          [\n            -99.9008,\n            31.9742\n          ],\n          [\n            -99.9004,\n            31.9738\n          ]\n        ]\n      ]\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.84,\n    \"model_version\": \"trajectory-v2.0.1\",\n    \"calibration_age_days\": 30,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"telemetry:drone-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 102\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Graph API",
      "description": "Spatial graph operations — influence spread, evacuation routing, upstream tracing.",
      "item": [
        {
          "name": "Downstream influence spread from a node",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/graph/influence?source_id=sensor_h2s_023",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "graph",
                "influence"
              ],
              "query": [
                {
                  "key": "source_id",
                  "value": "sensor_h2s_023",
                  "description": "Source node ID (device, asset, or event location).",
                  "disabled": false
                },
                {
                  "key": "edge_type",
                  "value": "causal",
                  "description": "Edge type to traverse. atmospheric = plume, fluid = pipe/stream, rf = signal, causal = all. Default: causal.",
                  "disabled": true
                },
                {
                  "key": "max_hops",
                  "value": "5",
                  "description": "Maximum graph traversal depth. Default 5.",
                  "disabled": true
                },
                {
                  "key": "time_horizon_min",
                  "value": "0",
                  "description": "Restrict to nodes reachable within this time in minutes. Default unlimited.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns all nodes in the sensor graph that are \"downstream\" of a source event —\nentities likely to be affected if the source produces an event. Edge weights reflect\npropagation physics (plume transport, fluid flow, RF signal paths). Results are\nordered by predicted arrival time and estimated impact magnitude.\n\n**Pricing:** $0.005 / call\n\n`GET /graph/influence`\n\n_operationId:_ `getGraphInfluence`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Downstream influenced entities returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/graph/influence?source_id=sensor_h2s_023",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "graph",
                    "influence"
                  ],
                  "query": [
                    {
                      "key": "source_id",
                      "value": "sensor_h2s_023",
                      "description": "Source node ID (device, asset, or event location).",
                      "disabled": false
                    },
                    {
                      "key": "edge_type",
                      "value": "causal",
                      "description": "Edge type to traverse. atmospheric = plume, fluid = pipe/stream, rf = signal, causal = all. Default: causal.",
                      "disabled": true
                    },
                    {
                      "key": "max_hops",
                      "value": "5",
                      "description": "Maximum graph traversal depth. Default 5.",
                      "disabled": true
                    },
                    {
                      "key": "time_horizon_min",
                      "value": "0",
                      "description": "Restrict to nodes reachable within this time in minutes. Default unlimited.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns all nodes in the sensor graph that are \"downstream\" of a source event —\nentities likely to be affected if the source produces an event. Edge weights reflect\npropagation physics (plume transport, fluid flow, RF signal paths). Results are\nordered by predicted arrival time and estimated impact magnitude.\n\n**Pricing:** $0.005 / call\n\n`GET /graph/influence`\n\n_operationId:_ `getGraphInfluence`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Downstream influenced entities returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"source\": \"sensor_h2s_023\",\n    \"downstream_nodes\": [\n      {\n        \"id\": \"sensor_h2s_024\",\n        \"arrival_min\": 1.2,\n        \"edge_type\": \"atmospheric\",\n        \"impact_score\": 0.78\n      },\n      {\n        \"id\": \"personnel_zone_C\",\n        \"arrival_min\": 4.6,\n        \"edge_type\": \"atmospheric\",\n        \"impact_score\": 0.41\n      },\n      {\n        \"id\": \"wellhead_07\",\n        \"arrival_min\": 7.9,\n        \"edge_type\": \"atmospheric\",\n        \"impact_score\": 0.22\n      }\n    ]\n  },\n  \"meta\": {\n    \"confidence\": 0.87,\n    \"model_version\": \"graph-influence-v1.6.0\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"graph:facility-2026-04-21\",\n      \"met:NOAA-HRRR-2026-04-21T03Z\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 88\n  }\n}"
            }
          ]
        },
        {
          "name": "Evacuation routing given current hazard state",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/graph/evacuate?from_ids=personnel_zone_C,personnel_zone_D",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "graph",
                "evacuate"
              ],
              "query": [
                {
                  "key": "from_ids",
                  "value": "personnel_zone_C,personnel_zone_D",
                  "description": "Comma-separated entity or zone IDs to evacuate from (personnel IDs, zone IDs).",
                  "disabled": false
                },
                {
                  "key": "to_ids",
                  "value": "",
                  "description": "Comma-separated target safe zone IDs. Default all registered safe zones in the facility.",
                  "disabled": true
                },
                {
                  "key": "avoid_job_ids",
                  "value": "job_01hxyz",
                  "description": "Comma-separated simulation job IDs whose result polygons to treat as impassable (live plume, flood, fire footprints).",
                  "disabled": true
                },
                {
                  "key": "site_id",
                  "value": "wellpad_07",
                  "description": "Site context for indoor/outdoor routing graph selection.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns optimal evacuation routes from specified locations to safe zones, routing around\nactive hazard polygons (from live plume, fire, or flood simulations). Uses pgRouting on\nthe facility graph with real-time hazard avoidance.\n\n**Pricing:** $0.01 / call\n\n`GET /graph/evacuate`\n\n_operationId:_ `getGraphEvacuate`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Evacuation routes returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/graph/evacuate?from_ids=personnel_zone_C,personnel_zone_D",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "graph",
                    "evacuate"
                  ],
                  "query": [
                    {
                      "key": "from_ids",
                      "value": "personnel_zone_C,personnel_zone_D",
                      "description": "Comma-separated entity or zone IDs to evacuate from (personnel IDs, zone IDs).",
                      "disabled": false
                    },
                    {
                      "key": "to_ids",
                      "value": "",
                      "description": "Comma-separated target safe zone IDs. Default all registered safe zones in the facility.",
                      "disabled": true
                    },
                    {
                      "key": "avoid_job_ids",
                      "value": "job_01hxyz",
                      "description": "Comma-separated simulation job IDs whose result polygons to treat as impassable (live plume, flood, fire footprints).",
                      "disabled": true
                    },
                    {
                      "key": "site_id",
                      "value": "wellpad_07",
                      "description": "Site context for indoor/outdoor routing graph selection.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns optimal evacuation routes from specified locations to safe zones, routing around\nactive hazard polygons (from live plume, fire, or flood simulations). Uses pgRouting on\nthe facility graph with real-time hazard avoidance.\n\n**Pricing:** $0.01 / call\n\n`GET /graph/evacuate`\n\n_operationId:_ `getGraphEvacuate`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Evacuation routes returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"routes\": [\n      {\n        \"entity_id\": \"personnel_zone_C\",\n        \"route\": {\n          \"type\": \"LineString\",\n          \"coordinates\": [\n            [\n              -99.9018,\n              31.9686\n            ],\n            [\n              -99.902,\n              31.9692\n            ],\n            [\n              -99.9028,\n              31.97\n            ],\n            [\n              -99.9036,\n              31.971\n            ]\n          ]\n        },\n        \"distance_m\": 412.0,\n        \"eta_min\": 5.4\n      },\n      {\n        \"entity_id\": \"personnel_zone_D\",\n        \"route\": {\n          \"type\": \"LineString\",\n          \"coordinates\": [\n            [\n              -99.9012,\n              31.969\n            ],\n            [\n              -99.9015,\n              31.9696\n            ],\n            [\n              -99.9024,\n              31.9706\n            ],\n            [\n              -99.9036,\n              31.971\n            ]\n          ]\n        },\n        \"distance_m\": 478.0,\n        \"eta_min\": 6.2\n      }\n    ]\n  },\n  \"meta\": {\n    \"confidence\": 0.93,\n    \"model_version\": \"graph-evac-v2.1.0\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"graph:facility-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 71\n  }\n}"
            }
          ]
        },
        {
          "name": "Upstream sensor identification for a gauge",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/graph/upstream?entity_id=gauge_colorado_a7",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "graph",
                "upstream"
              ],
              "query": [
                {
                  "key": "entity_id",
                  "value": "gauge_colorado_a7",
                  "description": "Stream gauge or sensor ID.",
                  "disabled": false
                },
                {
                  "key": "max_distance_km",
                  "value": "50",
                  "description": "Maximum upstream search distance in kilometres. Default 50 km.",
                  "disabled": true
                }
              ]
            },
            "description": "For a given stream gauge or sensor, identifies all upstream contributing sensors\nin the watershed or pipeline network, ordered by distance and travel time.\n\n**Pricing:** $0.003 / call\n\n`GET /graph/upstream`\n\n_operationId:_ `getGraphUpstream`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Upstream sensors returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/graph/upstream?entity_id=gauge_colorado_a7",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "graph",
                    "upstream"
                  ],
                  "query": [
                    {
                      "key": "entity_id",
                      "value": "gauge_colorado_a7",
                      "description": "Stream gauge or sensor ID.",
                      "disabled": false
                    },
                    {
                      "key": "max_distance_km",
                      "value": "50",
                      "description": "Maximum upstream search distance in kilometres. Default 50 km.",
                      "disabled": true
                    }
                  ]
                },
                "description": "For a given stream gauge or sensor, identifies all upstream contributing sensors\nin the watershed or pipeline network, ordered by distance and travel time.\n\n**Pricing:** $0.003 / call\n\n`GET /graph/upstream`\n\n_operationId:_ `getGraphUpstream`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Upstream sensors returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"entity_id\": \"gauge_colorado_a7\",\n    \"upstream_sensors\": [\n      {\n        \"id\": \"gauge_colorado_a3\",\n        \"distance_km\": 8.2,\n        \"travel_time_hr\": 1.4\n      },\n      {\n        \"id\": \"gauge_colorado_a1\",\n        \"distance_km\": 17.6,\n        \"travel_time_hr\": 3.1\n      },\n      {\n        \"id\": \"rain_gauge_07\",\n        \"distance_km\": 22.4,\n        \"travel_time_hr\": 4.2\n      }\n    ]\n  },\n  \"meta\": {\n    \"confidence\": 0.95,\n    \"model_version\": \"graph-upstream-v1.2.0\",\n    \"calibration_age_days\": 30,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"watershed:USGS-WBD-2025\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 58\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Calibration",
      "description": "Site-specific model calibration state.",
      "item": [
        {
          "name": "Site-specific model calibration state",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/model/calibration?model=plume&site_id=wellpad_07",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "model",
                "calibration"
              ],
              "query": [
                {
                  "key": "model",
                  "value": "plume",
                  "description": "Propagation model to query calibration state for.",
                  "disabled": false
                },
                {
                  "key": "site_id",
                  "value": "wellpad_07",
                  "description": "Site identifier.",
                  "disabled": false
                }
              ]
            },
            "description": "Returns the current calibration state for a given propagation model and site —\nincluding calibration age, parameter corrections applied, and prediction accuracy\nmetrics over the last 30/90 days.\n\nRequires Site Calibration plan.\n\n**Pricing:** $0.001 / call (Site Calibration plan only)\n\n`GET /model/calibration`\n\n_operationId:_ `getModelCalibration`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Calibration state returned.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/model/calibration?model=plume&site_id=wellpad_07",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "model",
                    "calibration"
                  ],
                  "query": [
                    {
                      "key": "model",
                      "value": "plume",
                      "description": "Propagation model to query calibration state for.",
                      "disabled": false
                    },
                    {
                      "key": "site_id",
                      "value": "wellpad_07",
                      "description": "Site identifier.",
                      "disabled": false
                    }
                  ]
                },
                "description": "Returns the current calibration state for a given propagation model and site —\nincluding calibration age, parameter corrections applied, and prediction accuracy\nmetrics over the last 30/90 days.\n\nRequires Site Calibration plan.\n\n**Pricing:** $0.001 / call (Site Calibration plan only)\n\n`GET /model/calibration`\n\n_operationId:_ `getModelCalibration`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Calibration state returned.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"model\": \"plume\",\n    \"site_id\": \"wellpad_07\",\n    \"calibration_age_days\": 47,\n    \"last_calibrated_at\": \"2026-03-05T14:22:00Z\",\n    \"accuracy_30d\": {\n      \"mean_absolute_error\": 0.18,\n      \"r_squared\": 0.94\n    },\n    \"corrections_applied\": {\n      \"stability_correction\": 0.05,\n      \"terrain_correction_factor\": 1.12,\n      \"effective_emission_height_m\": 14.2\n    }\n  },\n  \"meta\": {\n    \"confidence\": 0.97,\n    \"model_version\": \"plume-v4.1.2\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"calibration:wellpad_07-2026-03-05\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 42\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Jobs",
      "description": "Async job status polling.",
      "item": [
        {
          "name": "Poll async job status and retrieve result",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/jobs/:job_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "jobs",
                ":job_id"
              ],
              "variable": [
                {
                  "key": "job_id",
                  "value": "",
                  "description": "Job ID returned from a POST /simulate/* or other async endpoint."
                }
              ]
            },
            "description": "Returns the current status of an async simulation job. When status is `complete`,\nthe full result is included in the `result` field of the response envelope.\nJobs expire 48 hours after completion.\n\n`GET /jobs/{job_id}`\n\n_operationId:_ `getJob`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Job status (and result if complete).",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/jobs/:job_id",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "jobs",
                    ":job_id"
                  ],
                  "variable": [
                    {
                      "key": "job_id",
                      "value": "",
                      "description": "Job ID returned from a POST /simulate/* or other async endpoint."
                    }
                  ]
                },
                "description": "Returns the current status of an async simulation job. When status is `complete`,\nthe full result is included in the `result` field of the response envelope.\nJobs expire 48 hours after completion.\n\n`GET /jobs/{job_id}`\n\n_operationId:_ `getJob`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Job status (and result if complete).",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"job\": {\n    \"id\": \"job_01hx2a3f9k8qmzn7p\",\n    \"type\": \"simulate/plume\",\n    \"status\": \"complete\",\n    \"eta_seconds\": null,\n    \"webhook_delivered\": true\n  },\n  \"result\": {\n    \"isopleths\": [\n      {\n        \"concentration_ppm\": 10,\n        \"polygon\": {\n          \"type\": \"Polygon\",\n          \"coordinates\": [\n            [\n              [\n                -99.905,\n                31.9645\n              ],\n              [\n                -99.902,\n                31.9648\n              ],\n              [\n                -99.9018,\n                31.967\n              ],\n              [\n                -99.9048,\n                31.9667\n              ],\n              [\n                -99.905,\n                31.9645\n              ]\n            ]\n          ]\n        }\n      }\n    ],\n    \"max_concentration_ppm\": 58.1,\n    \"receptors\": [\n      {\n        \"device_id\": \"sensor_h2s_023\",\n        \"concentration_ppm\": 4.7\n      }\n    ]\n  },\n  \"meta\": {\n    \"confidence\": 0.92,\n    \"model_version\": \"plume-v4.1.2\",\n    \"calibration_age_days\": 47,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"met:NOAA-HRRR-2026-04-21T03Z\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 17\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Webhooks",
      "description": "Register HTTPS callbacks to receive async job results, signed with HMAC-SHA256.",
      "item": [
        {
          "name": "List all registered webhooks for the account",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks"
              ],
              "query": [
                {
                  "key": "active",
                  "value": "False",
                  "description": "If supplied, filters the result to only active (`true`) or paused (`false`) webhooks.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns every webhook registered on the calling account, ordered by `created_at` descending.\nThe signing `secret` is **never** returned by this endpoint — it is only available on the\ninitial `POST /webhooks` response. To rotate a secret, delete the webhook and register a new one.\n\n`GET /webhooks`\n\n_operationId:_ `listWebhooks`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Array of webhook records (without `secret`).",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks"
                  ],
                  "query": [
                    {
                      "key": "active",
                      "value": "False",
                      "description": "If supplied, filters the result to only active (`true`) or paused (`false`) webhooks.",
                      "disabled": true
                    }
                  ]
                },
                "description": "Returns every webhook registered on the calling account, ordered by `created_at` descending.\nThe signing `secret` is **never** returned by this endpoint — it is only available on the\ninitial `POST /webhooks` response. To rotate a secret, delete the webhook and register a new one.\n\n`GET /webhooks`\n\n_operationId:_ `listWebhooks`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Array of webhook records (without `secret`).",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": [\n    {\n      \"id\": \"whk_01hx2f8q7n3tdvm5j\",\n      \"url\": \"https://api.acme.com/hooks/geog\",\n      \"events\": [\n        \"job.complete\",\n        \"job.failed\",\n        \"webhook.disabled\"\n      ],\n      \"description\": \"Production plume results \\u2192 SOC pipeline\",\n      \"active\": true,\n      \"disabled_at\": null,\n      \"created_at\": \"2026-04-21T03:14:22Z\"\n    },\n    {\n      \"id\": \"whk_01hx2f9r1k4uxwn6m\",\n      \"url\": \"https://api.acme.com/hooks/geog-staging\",\n      \"events\": [\n        \"job.complete\"\n      ],\n      \"description\": \"Staging mirror\",\n      \"active\": false,\n      \"disabled_at\": \"2026-04-21T03:48:11Z\",\n      \"disabled_reason\": \"auto_failure_rate\",\n      \"created_at\": \"2026-04-15T09:02:11Z\"\n    }\n  ],\n  \"meta\": {\n    \"confidence\": 1.0,\n    \"model_version\": \"webhooks-v1.0.0\",\n    \"calibration_age_days\": 0,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 22\n  }\n}"
            }
          ]
        },
        {
          "name": "Register a webhook endpoint to receive async job results",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks"
              ]
            },
            "description": "Registers an HTTPS callback URL on your account. Once registered, every async job your\naccount creates (`/simulate/*`, `/rf/mesh/viability`, `/rf/optimize/placement`,\n`/optimize/*`) will POST its full result envelope to this URL when it transitions to\n`complete` or `failed`. Per-job overrides can still be supplied via the `webhook_url`\nfield on the job request body.\n\n## Delivery payload\n\nEach delivery is a `POST` with `Content-Type: application/json` containing the same\nresponse envelope returned by `GET /jobs/{job_id}` when the job is complete.\n\nThe following headers are always set on the delivery:\n\n| Header | Description |\n| --- | --- |\n| `X-Geog-Signature` | Hex-encoded HMAC-SHA256 of `{timestamp}.{raw_body}` using the webhook secret. Format: `t=<unix_ts>,v1=<hex_digest>` |\n| `X-Geog-Event` | Event type (`job.complete`, `job.failed`, `calibration.updated`) |\n| `X-Geog-Delivery` | Unique delivery ID — safe to use for idempotency on the receiver side |\n| `X-Geog-Webhook-Id` | ID of the registered webhook that produced this delivery |\n| `X-Geog-Test` | Present and set to `true` only on deliveries produced by `POST /webhooks/{id}/test`. Absent on real job-driven deliveries — receivers can use it to short-circuit production side-effects for synthetic traffic |\n\n## Verifying the signature (HMAC-SHA256)\n\n1. Read the `X-Geog-Signature` header and parse the comma-separated `t=` (unix timestamp,\n   seconds) and `v1=` (hex digest) parts.\n2. Reject the delivery if `|now - t| > 300` seconds to mitigate replay attacks.\n3. Concatenate `t`, a literal `.`, and the raw request body bytes.\n4. Compute `HMAC-SHA256(secret, payload).hexdigest()` and compare it to `v1` using a\n   constant-time comparison (e.g. `hmac.compare_digest`). Reject on mismatch.\n\n## Retry behaviour\n\nNon-2xx responses (or no response within 10 seconds) trigger automatic retries with\nexponential backoff at 30s, 2m, 10m, 30m, 2h, 6h, and 24h. After 7 failed attempts the\ndelivery is marked `undeliverable`. If 50% of deliveries in the last hour have failed\nthe webhook is automatically disabled (`active=false`, `disabled_reason=auto_failure_rate`)\nand an email is sent to the account owner. To detect this auto-disable programmatically\nrather than relying on the owner's inbox, either subscribe to the `webhook.disabled`\nevent (delivered on the final attempt before the webhook is paused — best subscribed on\na separately-monitored receiver) or poll `GET /webhooks/{id}/health`, which returns the\ncurrent rolling-hour failure rate, the auto-disable threshold, and the `disabled_at`\ntimestamp once tripped. All deliveries (including failures) are visible on the dashboard\nfor 30 days.\n\n`POST /webhooks`\n\n_operationId:_ `registerWebhook`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://api.acme.com/hooks/geog\",\n  \"events\": [\n    \"job.complete\",\n    \"job.failed\",\n    \"webhook.disabled\"\n  ],\n  \"description\": \"Production plume results \\u2192 SOC pipeline\",\n  \"active\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "200 Webhook registered successfully. The `secret` field is retur",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks"
                  ]
                },
                "description": "Registers an HTTPS callback URL on your account. Once registered, every async job your\naccount creates (`/simulate/*`, `/rf/mesh/viability`, `/rf/optimize/placement`,\n`/optimize/*`) will POST its full result envelope to this URL when it transitions to\n`complete` or `failed`. Per-job overrides can still be supplied via the `webhook_url`\nfield on the job request body.\n\n## Delivery payload\n\nEach delivery is a `POST` with `Content-Type: application/json` containing the same\nresponse envelope returned by `GET /jobs/{job_id}` when the job is complete.\n\nThe following headers are always set on the delivery:\n\n| Header | Description |\n| --- | --- |\n| `X-Geog-Signature` | Hex-encoded HMAC-SHA256 of `{timestamp}.{raw_body}` using the webhook secret. Format: `t=<unix_ts>,v1=<hex_digest>` |\n| `X-Geog-Event` | Event type (`job.complete`, `job.failed`, `calibration.updated`) |\n| `X-Geog-Delivery` | Unique delivery ID — safe to use for idempotency on the receiver side |\n| `X-Geog-Webhook-Id` | ID of the registered webhook that produced this delivery |\n| `X-Geog-Test` | Present and set to `true` only on deliveries produced by `POST /webhooks/{id}/test`. Absent on real job-driven deliveries — receivers can use it to short-circuit production side-effects for synthetic traffic |\n\n## Verifying the signature (HMAC-SHA256)\n\n1. Read the `X-Geog-Signature` header and parse the comma-separated `t=` (unix timestamp,\n   seconds) and `v1=` (hex digest) parts.\n2. Reject the delivery if `|now - t| > 300` seconds to mitigate replay attacks.\n3. Concatenate `t`, a literal `.`, and the raw request body bytes.\n4. Compute `HMAC-SHA256(secret, payload).hexdigest()` and compare it to `v1` using a\n   constant-time comparison (e.g. `hmac.compare_digest`). Reject on mismatch.\n\n## Retry behaviour\n\nNon-2xx responses (or no response within 10 seconds) trigger automatic retries with\nexponential backoff at 30s, 2m, 10m, 30m, 2h, 6h, and 24h. After 7 failed attempts the\ndelivery is marked `undeliverable`. If 50% of deliveries in the last hour have failed\nthe webhook is automatically disabled (`active=false`, `disabled_reason=auto_failure_rate`)\nand an email is sent to the account owner. To detect this auto-disable programmatically\nrather than relying on the owner's inbox, either subscribe to the `webhook.disabled`\nevent (delivered on the final attempt before the webhook is paused — best subscribed on\na separately-monitored receiver) or poll `GET /webhooks/{id}/health`, which returns the\ncurrent rolling-hour failure rate, the auto-disable threshold, and the `disabled_at`\ntimestamp once tripped. All deliveries (including failures) are visible on the dashboard\nfor 30 days.\n\n`POST /webhooks`\n\n_operationId:_ `registerWebhook`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"url\": \"https://api.acme.com/hooks/geog\",\n  \"events\": [\n    \"job.complete\",\n    \"job.failed\",\n    \"webhook.disabled\"\n  ],\n  \"description\": \"Production plume results \\u2192 SOC pipeline\",\n  \"active\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Webhook registered successfully. The `secret` field is returned only on this initial response.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"id\": \"whk_01hx2f8q7n3tdvm5j\",\n    \"url\": \"https://api.acme.com/hooks/geog\",\n    \"events\": [\n      \"job.complete\",\n      \"job.failed\",\n      \"webhook.disabled\"\n    ],\n    \"description\": \"Production plume results \\u2192 SOC pipeline\",\n    \"active\": true,\n    \"disabled_at\": null,\n    \"secret\": \"whsec_8k3Jq2pNvR7tYxL4mZ9cFwH1bD5sQ6aU\",\n    \"created_at\": \"2026-04-21T03:14:22Z\"\n  },\n  \"meta\": {\n    \"confidence\": 1.0,\n    \"model_version\": \"webhooks-v1.0.0\",\n    \"calibration_age_days\": 0,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 27\n  }\n}"
            }
          ]
        },
        {
          "name": "Retrieve a single registered webhook",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks/:webhook_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                ":webhook_id"
              ],
              "variable": [
                {
                  "key": "webhook_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Returns the current configuration of one webhook. The signing `secret` is **not**\nreturned — it is only available on the original `POST /webhooks` response. Rotate by\ndeleting and re-registering.\n\n`GET /webhooks/{webhook_id}`\n\n_operationId:_ `getWebhook`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Webhook record (without `secret`).",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks/:webhook_id",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks",
                    ":webhook_id"
                  ],
                  "variable": [
                    {
                      "key": "webhook_id",
                      "value": "",
                      "description": ""
                    }
                  ]
                },
                "description": "Returns the current configuration of one webhook. The signing `secret` is **not**\nreturned — it is only available on the original `POST /webhooks` response. Rotate by\ndeleting and re-registering.\n\n`GET /webhooks/{webhook_id}`\n\n_operationId:_ `getWebhook`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Webhook record (without `secret`).",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"id\": \"whk_01hx2f8q7n3tdvm5j\",\n    \"url\": \"https://api.acme.com/hooks/geog\",\n    \"events\": [\n      \"job.complete\",\n      \"job.failed\",\n      \"webhook.disabled\"\n    ],\n    \"description\": \"Production plume results \\u2192 SOC pipeline\",\n    \"active\": true,\n    \"disabled_at\": null,\n    \"created_at\": \"2026-04-21T03:14:22Z\"\n  },\n  \"meta\": {\n    \"confidence\": 1.0,\n    \"model_version\": \"webhooks-v1.0.0\",\n    \"calibration_age_days\": 0,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 19\n  }\n}"
            }
          ]
        },
        {
          "name": "Update a registered webhook",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks/:webhook_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                ":webhook_id"
              ],
              "variable": [
                {
                  "key": "webhook_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Partially updates a webhook. Send only the fields you want to change. Common uses:\ntoggling `active` to pause/resume deliveries, re-pointing `url` after a backend\nmigration, or narrowing the subscribed `events`.\n\nThe signing `secret` cannot be changed via this endpoint. To rotate it, `DELETE` the\nwebhook and register a new one with `POST /webhooks` — store the new secret from that\nresponse, then cut over your verification code.\n\n`PATCH /webhooks/{webhook_id}`\n\n_operationId:_ `updateWebhook`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://api.acme.com/hooks/geog-v2\",\n  \"events\": [\n    \"job.complete\",\n    \"job.failed\",\n    \"webhook.disabled\"\n  ],\n  \"description\": \"Production plume results \\u2192 SOC pipeline (v2)\",\n  \"active\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "200 Updated webhook record (without `secret`).",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks/:webhook_id",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks",
                    ":webhook_id"
                  ],
                  "variable": [
                    {
                      "key": "webhook_id",
                      "value": "",
                      "description": ""
                    }
                  ]
                },
                "description": "Partially updates a webhook. Send only the fields you want to change. Common uses:\ntoggling `active` to pause/resume deliveries, re-pointing `url` after a backend\nmigration, or narrowing the subscribed `events`.\n\nThe signing `secret` cannot be changed via this endpoint. To rotate it, `DELETE` the\nwebhook and register a new one with `POST /webhooks` — store the new secret from that\nresponse, then cut over your verification code.\n\n`PATCH /webhooks/{webhook_id}`\n\n_operationId:_ `updateWebhook`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"url\": \"https://api.acme.com/hooks/geog-v2\",\n  \"events\": [\n    \"job.complete\",\n    \"job.failed\",\n    \"webhook.disabled\"\n  ],\n  \"description\": \"Production plume results \\u2192 SOC pipeline (v2)\",\n  \"active\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Updated webhook record (without `secret`).",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"id\": \"whk_01hx2f8q7n3tdvm5j\",\n    \"url\": \"https://api.acme.com/hooks/geog-v2\",\n    \"events\": [\n      \"job.complete\",\n      \"job.failed\",\n      \"webhook.disabled\"\n    ],\n    \"description\": \"Production plume results \\u2192 SOC pipeline (v2)\",\n    \"active\": false,\n    \"disabled_at\": \"2026-04-21T03:48:11Z\",\n    \"disabled_reason\": \"manual\",\n    \"created_at\": \"2026-04-21T03:14:22Z\"\n  },\n  \"meta\": {\n    \"confidence\": 1.0,\n    \"model_version\": \"webhooks-v1.0.0\",\n    \"calibration_age_days\": 0,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 24\n  }\n}"
            }
          ]
        },
        {
          "name": "Delete a registered webhook",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks/:webhook_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                ":webhook_id"
              ],
              "variable": [
                {
                  "key": "webhook_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Permanently removes a webhook. Deliveries already in flight may still arrive briefly,\nbut no new deliveries will be queued. Use this to revoke a leaked endpoint or to rotate\nthe signing secret (delete, then `POST /webhooks` to register a fresh one).\n\n`DELETE /webhooks/{webhook_id}`\n\n_operationId:_ `deleteWebhook`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "Send a synthetic event to a webhook to verify the receiver",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks/:id/test",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                ":id",
                "test"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": "",
                  "description": "Webhook identifier returned from `POST /webhooks` (prefix `whk_`)."
                }
              ]
            },
            "description": "Generates a synthetic delivery for the registered webhook and POSTs it to the URL\nexactly as a real event would be sent — same envelope shape, same `X-Geog-Signature`\nHMAC, same retry rules. Designed for day-one verification of a brand-new receiver\nbefore any real job has run: confirm that the URL is reachable, the TLS certificate\nis valid, and the receiver's signature-verification code accepts the payload.\n\n## Distinguishing test deliveries\n\nTest deliveries carry an additional `X-Geog-Test: true` header on the outbound POST,\nand the resulting `WebhookDelivery` record reports `test: true`. The synthetic\n`job_id` is prefixed `job_test_` so it cannot collide with a real job. Either signal\nis safe to gate on; the header is recommended so the receiver can short-circuit\nproduction side-effects (alerting, billing, downstream writes) before parsing the\nbody.\n\nTest deliveries appear in `GET /webhooks/{id}/deliveries` alongside real ones, are\nsubject to the same retry schedule and auto-disable rules, and are throttled to 60\ntest deliveries per webhook per hour (`TEST_RATE_LIMITED`).\n\n`POST /webhooks/{id}/test`\n\n_operationId:_ `sendWebhookTestEvent`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event\": \"job.complete\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 Test delivery accepted and queued. The returned `WebhookDeli",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks/:id/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks",
                    ":id",
                    "test"
                  ],
                  "variable": [
                    {
                      "key": "id",
                      "value": "",
                      "description": "Webhook identifier returned from `POST /webhooks` (prefix `whk_`)."
                    }
                  ]
                },
                "description": "Generates a synthetic delivery for the registered webhook and POSTs it to the URL\nexactly as a real event would be sent — same envelope shape, same `X-Geog-Signature`\nHMAC, same retry rules. Designed for day-one verification of a brand-new receiver\nbefore any real job has run: confirm that the URL is reachable, the TLS certificate\nis valid, and the receiver's signature-verification code accepts the payload.\n\n## Distinguishing test deliveries\n\nTest deliveries carry an additional `X-Geog-Test: true` header on the outbound POST,\nand the resulting `WebhookDelivery` record reports `test: true`. The synthetic\n`job_id` is prefixed `job_test_` so it cannot collide with a real job. Either signal\nis safe to gate on; the header is recommended so the receiver can short-circuit\nproduction side-effects (alerting, billing, downstream writes) before parsing the\nbody.\n\nTest deliveries appear in `GET /webhooks/{id}/deliveries` alongside real ones, are\nsubject to the same retry schedule and auto-disable rules, and are throttled to 60\ntest deliveries per webhook per hour (`TEST_RATE_LIMITED`).\n\n`POST /webhooks/{id}/test`\n\n_operationId:_ `sendWebhookTestEvent`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"event\": \"job.complete\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Test delivery accepted and queued. The returned `WebhookDelivery` reflects the new `pending` state with `test: true`.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"id\": \"whd_01hx2g4n8p7rqzm3k\",\n    \"webhook_id\": \"whk_01hx2f8q7n3tdvm5j\",\n    \"event\": \"job.complete\",\n    \"job_id\": \"job_test_01hx2a3f9k8qmzn7p\",\n    \"status\": \"pending\",\n    \"attempt_count\": 1,\n    \"response_code\": null,\n    \"response_ms\": null,\n    \"response_body_excerpt\": null,\n    \"error\": null,\n    \"signature_timestamp\": 1745211262,\n    \"created_at\": \"2026-04-21T03:14:22Z\",\n    \"last_attempt_at\": null,\n    \"delivered_at\": null,\n    \"next_attempt_at\": \"2026-04-21T03:14:22Z\",\n    \"test\": true\n  },\n  \"meta\": {\n    \"confidence\": 1.0,\n    \"model_version\": \"webhooks-v1.0.0\",\n    \"calibration_age_days\": 0,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 33\n  }\n}"
            }
          ]
        },
        {
          "name": "List recent deliveries for a webhook",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks/:id/deliveries",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                ":id",
                "deliveries"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "failed",
                  "description": "Filter results to a single delivery status. Default returns all statuses.",
                  "disabled": true
                },
                {
                  "key": "event",
                  "value": "job.complete",
                  "description": "Filter results to a single event type.",
                  "disabled": true
                },
                {
                  "key": "test",
                  "value": "True",
                  "description": "Filter by delivery origin. `true` returns only synthetic deliveries produced\nby `POST /webhooks/{id}/test`; `false` returns only real job-driven\ndeliveries. Omit (the default) to return both kinds.\n\nComposes with `status` and `event` using AND semantics — for example,\n`?test=true&status=failed` returns only failed test deliveries, useful when\nverifying a brand-new receiver without scrolling past real job results.\n",
                  "disabled": true
                },
                {
                  "key": "created_after",
                  "value": "2026-04-21T02:00:00Z",
                  "description": "Inclusive lower bound on the delivery's `created_at` timestamp (ISO 8601, UTC).\nOnly deliveries first queued at or after this instant are returned.\n\nComposes with `status`, `event`, and `test` using AND semantics — for example,\n`?status=failed&created_after=2026-04-21T02:00:00Z&created_before=2026-04-21T03:00:00Z`\nreturns only failed deliveries queued during that one-hour window, useful for\nscoping a debug session to a known outage. Bounded by the 30-day retention window.\n",
                  "disabled": true
                },
                {
                  "key": "created_before",
                  "value": "2026-04-21T03:00:00Z",
                  "description": "Exclusive upper bound on the delivery's `created_at` timestamp (ISO 8601, UTC).\nOnly deliveries first queued strictly before this instant are returned.\n\nMay be combined with `created_after` to define a closed-open `[after, before)`\nrange, or used on its own to scope to \"everything older than X\". Composes with\n`status`, `event`, and `test` using AND semantics, identical to the other filters.\n",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "25",
                  "description": "Page size (max 100).",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Opaque pagination cursor returned as `meta.next_cursor` on the previous page. Omit for the first page.",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "id",
                  "value": "",
                  "description": "Webhook identifier returned from `POST /webhooks` (prefix `whk_`)."
                }
              ]
            },
            "description": "Returns a paginated list of delivery attempts for the given webhook, newest first.\nMirrors the delivery log shown on the dashboard and is intended for debugging\nreceiver-side bugs without waiting for the next real job.\n\nDeliveries are retained for 30 days; older records return an empty page rather than\nan error. Use the `status` filter to narrow to actively-failing deliveries you may\nwant to replay after fixing your handler.\n\n`GET /webhooks/{id}/deliveries`\n\n_operationId:_ `listWebhookDeliveries`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Page of webhook deliveries, newest first.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks/:id/deliveries",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks",
                    ":id",
                    "deliveries"
                  ],
                  "query": [
                    {
                      "key": "status",
                      "value": "failed",
                      "description": "Filter results to a single delivery status. Default returns all statuses.",
                      "disabled": true
                    },
                    {
                      "key": "event",
                      "value": "job.complete",
                      "description": "Filter results to a single event type.",
                      "disabled": true
                    },
                    {
                      "key": "test",
                      "value": "True",
                      "description": "Filter by delivery origin. `true` returns only synthetic deliveries produced\nby `POST /webhooks/{id}/test`; `false` returns only real job-driven\ndeliveries. Omit (the default) to return both kinds.\n\nComposes with `status` and `event` using AND semantics — for example,\n`?test=true&status=failed` returns only failed test deliveries, useful when\nverifying a brand-new receiver without scrolling past real job results.\n",
                      "disabled": true
                    },
                    {
                      "key": "created_after",
                      "value": "2026-04-21T02:00:00Z",
                      "description": "Inclusive lower bound on the delivery's `created_at` timestamp (ISO 8601, UTC).\nOnly deliveries first queued at or after this instant are returned.\n\nComposes with `status`, `event`, and `test` using AND semantics — for example,\n`?status=failed&created_after=2026-04-21T02:00:00Z&created_before=2026-04-21T03:00:00Z`\nreturns only failed deliveries queued during that one-hour window, useful for\nscoping a debug session to a known outage. Bounded by the 30-day retention window.\n",
                      "disabled": true
                    },
                    {
                      "key": "created_before",
                      "value": "2026-04-21T03:00:00Z",
                      "description": "Exclusive upper bound on the delivery's `created_at` timestamp (ISO 8601, UTC).\nOnly deliveries first queued strictly before this instant are returned.\n\nMay be combined with `created_after` to define a closed-open `[after, before)`\nrange, or used on its own to scope to \"everything older than X\". Composes with\n`status`, `event`, and `test` using AND semantics, identical to the other filters.\n",
                      "disabled": true
                    },
                    {
                      "key": "limit",
                      "value": "25",
                      "description": "Page size (max 100).",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "Opaque pagination cursor returned as `meta.next_cursor` on the previous page. Omit for the first page.",
                      "disabled": true
                    }
                  ],
                  "variable": [
                    {
                      "key": "id",
                      "value": "",
                      "description": "Webhook identifier returned from `POST /webhooks` (prefix `whk_`)."
                    }
                  ]
                },
                "description": "Returns a paginated list of delivery attempts for the given webhook, newest first.\nMirrors the delivery log shown on the dashboard and is intended for debugging\nreceiver-side bugs without waiting for the next real job.\n\nDeliveries are retained for 30 days; older records return an empty page rather than\nan error. Use the `status` filter to narrow to actively-failing deliveries you may\nwant to replay after fixing your handler.\n\n`GET /webhooks/{id}/deliveries`\n\n_operationId:_ `listWebhookDeliveries`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Page of webhook deliveries, newest first.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": [\n    {\n      \"id\": \"whd_01hx2g4n8p7rqzm3k\",\n      \"webhook_id\": \"whk_01hx2f8q7n3tdvm5j\",\n      \"event\": \"job.complete\",\n      \"job_id\": \"job_01hx2a3f9k8qmzn7p\",\n      \"status\": \"failed\",\n      \"attempt_count\": 3,\n      \"response_code\": 502,\n      \"response_ms\": 482,\n      \"response_body_excerpt\": \"<html><head><title>502 Bad Gateway</title></head>...\",\n      \"error\": null,\n      \"signature_timestamp\": 1745211262,\n      \"created_at\": \"2026-04-21T03:14:22Z\",\n      \"last_attempt_at\": \"2026-04-21T03:24:51Z\",\n      \"delivered_at\": null,\n      \"next_attempt_at\": \"2026-04-21T03:34:51Z\",\n      \"test\": false\n    },\n    {\n      \"id\": \"whd_01hx2g4n8p7rqzm3l\",\n      \"webhook_id\": \"whk_01hx2f8q7n3tdvm5j\",\n      \"event\": \"job.complete\",\n      \"job_id\": \"job_01hx2a3f9k8qmzn7q\",\n      \"status\": \"success\",\n      \"attempt_count\": 1,\n      \"response_code\": 200,\n      \"response_ms\": 144,\n      \"response_body_excerpt\": \"{\\\"received\\\":true}\",\n      \"error\": null,\n      \"signature_timestamp\": 1745210500,\n      \"created_at\": \"2026-04-21T03:01:40Z\",\n      \"last_attempt_at\": \"2026-04-21T03:01:40Z\",\n      \"delivered_at\": \"2026-04-21T03:01:40Z\",\n      \"next_attempt_at\": null,\n      \"test\": false\n    }\n  ],\n  \"meta\": {\n    \"request_id\": \"req_01hx2g5p3q8wnzvr4\",\n    \"next_cursor\": \"eyJ0IjoxNzQ1MjEwMDAwLCJpZCI6IndoZF8wMWh4MmcxIn0\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Re-send a previously attempted webhook delivery",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks/:id/deliveries/:delivery_id/replay",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                ":id",
                "deliveries",
                ":delivery_id",
                "replay"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": "",
                  "description": "Webhook identifier (prefix `whk_`)."
                },
                {
                  "key": "delivery_id",
                  "value": "",
                  "description": "Delivery identifier returned by `GET /webhooks/{id}/deliveries` (prefix `whd_`)."
                }
              ]
            },
            "description": "Re-queues a previously attempted delivery for immediate re-send to the webhook's\ncurrently registered URL. Useful after fixing a receiver-side bug — there is no need\nto wait for the next real job.\n\n**Replays use the original payload and signature timestamp.** The exact bytes that\nwere originally signed are re-sent, and the original `X-Geog-Signature` (including\nits `t=` value) and `X-Geog-Delivery` ID are reused. This means:\n\n- HMAC verification on the receiver behaves identically to the original delivery.\n- The 5-minute replay-window check (`|now - t| > 300`) **will reject the request**\n  if the original signature timestamp is older than 5 minutes. Receivers that need\n  to accept replays of old deliveries should relax this check for requests carrying\n  a known `X-Geog-Delivery` ID.\n- Idempotent receivers keyed on `X-Geog-Delivery` will naturally deduplicate.\n\nThe replay attempt counts toward the webhook's retry budget and the delivery's\n`attempt_count` is incremented. Calling replay on a delivery whose `status` is\nalready `pending` returns `409 DELIVERY_ALREADY_PENDING`.\n\n`POST /webhooks/{id}/deliveries/{delivery_id}/replay`\n\n_operationId:_ `replayWebhookDelivery`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "202 Replay accepted and queued. The returned `WebhookDelivery` r",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks/:id/deliveries/:delivery_id/replay",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks",
                    ":id",
                    "deliveries",
                    ":delivery_id",
                    "replay"
                  ],
                  "variable": [
                    {
                      "key": "id",
                      "value": "",
                      "description": "Webhook identifier (prefix `whk_`)."
                    },
                    {
                      "key": "delivery_id",
                      "value": "",
                      "description": "Delivery identifier returned by `GET /webhooks/{id}/deliveries` (prefix `whd_`)."
                    }
                  ]
                },
                "description": "Re-queues a previously attempted delivery for immediate re-send to the webhook's\ncurrently registered URL. Useful after fixing a receiver-side bug — there is no need\nto wait for the next real job.\n\n**Replays use the original payload and signature timestamp.** The exact bytes that\nwere originally signed are re-sent, and the original `X-Geog-Signature` (including\nits `t=` value) and `X-Geog-Delivery` ID are reused. This means:\n\n- HMAC verification on the receiver behaves identically to the original delivery.\n- The 5-minute replay-window check (`|now - t| > 300`) **will reject the request**\n  if the original signature timestamp is older than 5 minutes. Receivers that need\n  to accept replays of old deliveries should relax this check for requests carrying\n  a known `X-Geog-Delivery` ID.\n- Idempotent receivers keyed on `X-Geog-Delivery` will naturally deduplicate.\n\nThe replay attempt counts toward the webhook's retry budget and the delivery's\n`attempt_count` is incremented. Calling replay on a delivery whose `status` is\nalready `pending` returns `409 DELIVERY_ALREADY_PENDING`.\n\n`POST /webhooks/{id}/deliveries/{delivery_id}/replay`\n\n_operationId:_ `replayWebhookDelivery`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Replay accepted and queued. The returned `WebhookDelivery` reflects the new `pending` state.",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"id\": \"whd_01hx2g4n8p7rqzm3k\",\n    \"webhook_id\": \"whk_01hx2f8q7n3tdvm5j\",\n    \"event\": \"job.complete\",\n    \"job_id\": \"job_01hx2a3f9k8qmzn7p\",\n    \"status\": \"pending\",\n    \"attempt_count\": 4,\n    \"response_code\": null,\n    \"response_ms\": null,\n    \"response_body_excerpt\": null,\n    \"error\": null,\n    \"signature_timestamp\": 1745211262,\n    \"created_at\": \"2026-04-21T03:14:22Z\",\n    \"last_attempt_at\": \"2026-04-21T03:24:51Z\",\n    \"delivered_at\": null,\n    \"next_attempt_at\": \"2026-04-21T03:48:31Z\",\n    \"test\": false\n  },\n  \"meta\": {\n    \"confidence\": 1.0,\n    \"model_version\": \"webhooks-v1.0.0\",\n    \"calibration_age_days\": 0,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 31\n  }\n}"
            }
          ]
        },
        {
          "name": "Read the rolling-hour delivery health for a webhook",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/webhooks/:id/health",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                ":id",
                "health"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": "",
                  "description": "Webhook identifier returned from `POST /webhooks` (prefix `whk_`)."
                }
              ]
            },
            "description": "Returns the same rolling-window failure-rate counters that drive the platform's\nauto-disable rule, plus the current `active` / `disabled_reason` state. Use this\nendpoint to detect — programmatically, without depending on the account owner's\ninbox — when a webhook has been auto-disabled after sustained delivery failures\n(≥50% failed deliveries in the last hour), or is trending toward it.\n\nTypical patterns:\n\n- **Polling guard.** Call once a minute from the same job that registered the\n  webhook. Alert your own on-call channel as soon as `status == \"degraded\"`\n  (failure rate has crossed 25%) so you can fix the receiver before the platform\n  auto-disables it. Treat `status == \"disabled\"` with `disabled_reason ==\n  \"auto_failure_rate\"` as a hard incident.\n- **Post-mortem.** After receiving a `webhook.disabled` event delivery (or the\n  owner-email alert), call this endpoint to read `failure_rate`, `failed_count`,\n  `undeliverable_count`, and `last_success_at` to understand exactly what tripped\n  the auto-disable rule.\n\nThis endpoint is read-only and cheap — it does not consume webhook delivery quota\nand is rate-limited only by the standard account-level rate limit.\n\n`GET /webhooks/{id}/health`\n\n_operationId:_ `getWebhookHealth`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Current health snapshot.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/webhooks/:id/health",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "webhooks",
                    ":id",
                    "health"
                  ],
                  "variable": [
                    {
                      "key": "id",
                      "value": "",
                      "description": "Webhook identifier returned from `POST /webhooks` (prefix `whk_`)."
                    }
                  ]
                },
                "description": "Returns the same rolling-window failure-rate counters that drive the platform's\nauto-disable rule, plus the current `active` / `disabled_reason` state. Use this\nendpoint to detect — programmatically, without depending on the account owner's\ninbox — when a webhook has been auto-disabled after sustained delivery failures\n(≥50% failed deliveries in the last hour), or is trending toward it.\n\nTypical patterns:\n\n- **Polling guard.** Call once a minute from the same job that registered the\n  webhook. Alert your own on-call channel as soon as `status == \"degraded\"`\n  (failure rate has crossed 25%) so you can fix the receiver before the platform\n  auto-disables it. Treat `status == \"disabled\"` with `disabled_reason ==\n  \"auto_failure_rate\"` as a hard incident.\n- **Post-mortem.** After receiving a `webhook.disabled` event delivery (or the\n  owner-email alert), call this endpoint to read `failure_rate`, `failed_count`,\n  `undeliverable_count`, and `last_success_at` to understand exactly what tripped\n  the auto-disable rule.\n\nThis endpoint is read-only and cheap — it does not consume webhook delivery quota\nand is rate-limited only by the standard account-level rate limit.\n\n`GET /webhooks/{id}/health`\n\n_operationId:_ `getWebhookHealth`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Current health snapshot.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"result\": {\n    \"webhook_id\": \"whk_01hx2f8q7n3tdvm5j\",\n    \"active\": false,\n    \"status\": \"disabled\",\n    \"disabled_at\": \"2026-04-21T03:48:11Z\",\n    \"disabled_reason\": \"auto_failure_rate\",\n    \"window_seconds\": 3600,\n    \"as_of\": \"2026-04-21T03:48:11Z\",\n    \"delivery_count\": 42,\n    \"success_count\": 18,\n    \"failed_count\": 3,\n    \"undeliverable_count\": 21,\n    \"pending_count\": 0,\n    \"failure_rate\": 0.571,\n    \"auto_disable_threshold\": 0.5,\n    \"consecutive_failures\": 7,\n    \"last_success_at\": \"2026-04-21T03:11:08Z\",\n    \"last_failure_at\": \"2026-04-21T03:47:54Z\"\n  },\n  \"meta\": {\n    \"confidence\": 1.0,\n    \"model_version\": \"webhooks-v1.0.0\",\n    \"calibration_age_days\": 0,\n    \"site_calibrated\": true,\n    \"provenance\": [\n      \"registry:tenant-2026-04-21\"\n    ],\n    \"request_id\": \"req_01hx29sknd4bqyt8r\",\n    \"latency_ms\": 18\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "STAC Catalog",
      "description": "",
      "item": [
        {
          "name": "STAC catalog root",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac"
              ]
            },
            "description": "STAC-API §1.0.0 catalog root. Carries the conformance set and\nnavigation links. Tenant-scoped: collections listed are filtered\nto the caller's `vertical_ids` and own `tenant_id`.\n\n**Conformance set:** Core, Collections, OGC API Features, Item Search\n(GET + POST). CQL2 filter is intentionally **not** advertised — see\nthe geog.ai roadmap entry `geog-ai-15` for the planned addition.\n\n**Pricing:** $0.002 / call (read family, 2.0 cost units).\n\n`GET /v1/stac/`\n\n_operationId:_ `stacRoot`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 STAC Catalog object.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/stac/",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "stac"
                  ]
                },
                "description": "STAC-API §1.0.0 catalog root. Carries the conformance set and\nnavigation links. Tenant-scoped: collections listed are filtered\nto the caller's `vertical_ids` and own `tenant_id`.\n\n**Conformance set:** Core, Collections, OGC API Features, Item Search\n(GET + POST). CQL2 filter is intentionally **not** advertised — see\nthe geog.ai roadmap entry `geog-ai-15` for the planned addition.\n\n**Pricing:** $0.002 / call (read family, 2.0 cost units).\n\n`GET /v1/stac/`\n\n_operationId:_ `stacRoot`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "STAC Catalog object.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"type\": \"Catalog\",\n  \"stac_version\": \"1.0.0\",\n  \"id\": \"geog-ai-catalog\",\n  \"title\": \"geog.ai STAC Catalog\",\n  \"description\": \"Tenant-scoped STAC catalog of completed simulation jobs.\",\n  \"conformsTo\": [\n    \"https://api.stacspec.org/v1.0.0/core\",\n    \"https://api.stacspec.org/v1.0.0/collections\",\n    \"https://api.stacspec.org/v1.0.0/ogcapi-features\",\n    \"https://api.stacspec.org/v1.0.0/item-search\"\n  ],\n  \"links\": [\n    {\n      \"rel\": \"self\",\n      \"href\": \"https://api.geog.ai/v1/stac/\",\n      \"type\": \"application/json\"\n    },\n    {\n      \"rel\": \"root\",\n      \"href\": \"https://api.geog.ai/v1/stac/\",\n      \"type\": \"application/json\"\n    },\n    {\n      \"rel\": \"conformance\",\n      \"href\": \"https://api.geog.ai/v1/stac/conformance\",\n      \"type\": \"application/json\"\n    },\n    {\n      \"rel\": \"data\",\n      \"href\": \"https://api.geog.ai/v1/stac/collections\",\n      \"type\": \"application/json\"\n    },\n    {\n      \"rel\": \"search\",\n      \"href\": \"https://api.geog.ai/v1/stac/search\",\n      \"type\": \"application/geo+json\",\n      \"method\": \"GET\"\n    },\n    {\n      \"rel\": \"search\",\n      \"href\": \"https://api.geog.ai/v1/stac/search\",\n      \"type\": \"application/geo+json\",\n      \"method\": \"POST\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "STAC conformance classes implemented by this server",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/conformance",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac",
                "conformance"
              ]
            },
            "description": "`GET /v1/stac/conformance`\n\n_operationId:_ `stacConformance`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 STAC §3 Conformance object.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/stac/conformance",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "stac",
                    "conformance"
                  ]
                },
                "description": "`GET /v1/stac/conformance`\n\n_operationId:_ `stacConformance`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "STAC §3 Conformance object.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"conformsTo\": [\n    \"https://api.stacspec.org/v1.0.0/core\",\n    \"https://api.stacspec.org/v1.0.0/collections\",\n    \"https://api.stacspec.org/v1.0.0/ogcapi-features\",\n    \"https://api.stacspec.org/v1.0.0/item-search\"\n  ]\n}"
            }
          ]
        },
        {
          "name": "List STAC Collections visible to the caller",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/collections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac",
                "collections"
              ]
            },
            "description": "One Collection per `(engine, vertical_id)` tuple the tenant has\nproduced jobs for. Each Collection carries `extent.spatial.bbox`,\n`extent.temporal.interval`, a per-tenant `license` (varies by plan),\nand a `providers` chain naming geog.ai as licensor and the engine\nas processor.\n\n`GET /v1/stac/collections`\n\n_operationId:_ `stacCollections`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 Collection list.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/stac/collections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "stac",
                    "collections"
                  ]
                },
                "description": "One Collection per `(engine, vertical_id)` tuple the tenant has\nproduced jobs for. Each Collection carries `extent.spatial.bbox`,\n`extent.temporal.interval`, a per-tenant `license` (varies by plan),\nand a `providers` chain naming geog.ai as licensor and the engine\nas processor.\n\n`GET /v1/stac/collections`\n\n_operationId:_ `stacCollections`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "Collection list.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"collections\": [\n    {\n      \"type\": \"Collection\",\n      \"stac_version\": \"1.0.0\",\n      \"id\": \"plume_aermod__oilgas\",\n      \"title\": \"AERMOD plume runs (oil & gas vertical)\",\n      \"description\": \"Completed AERMOD plume jobs for the oil & gas vertical.\",\n      \"license\": \"proprietary-pro\",\n      \"providers\": [\n        {\n          \"name\": \"geog.ai\",\n          \"roles\": [\n            \"licensor\",\n            \"host\"\n          ],\n          \"url\": \"https://geog.ai\"\n        },\n        {\n          \"name\": \"aermod\",\n          \"roles\": [\n            \"processor\"\n          ]\n        }\n      ],\n      \"extent\": {\n        \"spatial\": {\n          \"bbox\": [\n            [\n              -104.5,\n              30.5,\n              -94.0,\n              36.5\n            ]\n          ]\n        },\n        \"temporal\": {\n          \"interval\": [\n            [\n              \"2026-01-01T00:00:00Z\",\n              null\n            ]\n          ]\n        }\n      },\n      \"links\": [\n        {\n          \"rel\": \"self\",\n          \"href\": \"https://api.geog.ai/v1/stac/collections/plume_aermod__oilgas\",\n          \"type\": \"application/json\"\n        },\n        {\n          \"rel\": \"items\",\n          \"href\": \"https://api.geog.ai/v1/stac/collections/plume_aermod__oilgas/items\",\n          \"type\": \"application/geo+json\"\n        },\n        {\n          \"rel\": \"parent\",\n          \"href\": \"https://api.geog.ai/v1/stac/\",\n          \"type\": \"application/json\"\n        }\n      ]\n    }\n  ],\n  \"links\": [\n    {\n      \"rel\": \"self\",\n      \"href\": \"https://api.geog.ai/v1/stac/collections\",\n      \"type\": \"application/json\"\n    },\n    {\n      \"rel\": \"root\",\n      \"href\": \"https://api.geog.ai/v1/stac/\",\n      \"type\": \"application/json\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Fetch a single STAC Collection",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/collections/:collection_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac",
                "collections",
                ":collection_id"
              ],
              "variable": [
                {
                  "key": "collection_id",
                  "value": "",
                  "description": "Composite collection id — `{engine}__{vertical_id}` (e.g.\n`plume_aermod__oilgas`). Use `_unscoped` as the vertical\nsentinel for legacy rows that carry no vertical_id.\n"
                }
              ]
            },
            "description": "`GET /v1/stac/collections/{collection_id}`\n\n_operationId:_ `stacCollection`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "200 STAC Collection.",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/stac/collections/:collection_id",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "stac",
                    "collections",
                    ":collection_id"
                  ],
                  "variable": [
                    {
                      "key": "collection_id",
                      "value": "",
                      "description": "Composite collection id — `{engine}__{vertical_id}` (e.g.\n`plume_aermod__oilgas`). Use `_unscoped` as the vertical\nsentinel for legacy rows that carry no vertical_id.\n"
                    }
                  ]
                },
                "description": "`GET /v1/stac/collections/{collection_id}`\n\n_operationId:_ `stacCollection`",
                "auth": {
                  "type": "bearer",
                  "bearer": [
                    {
                      "key": "token",
                      "value": "{{api_key}}",
                      "type": "string"
                    }
                  ]
                }
              },
              "status": "STAC Collection.",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"type\": \"Collection\",\n  \"stac_version\": \"1.0.0\",\n  \"id\": \"plume_aermod__oilgas\",\n  \"title\": \"AERMOD plume runs (oil & gas vertical)\",\n  \"description\": \"Completed AERMOD plume jobs for the oil & gas vertical.\",\n  \"license\": \"proprietary-pro\",\n  \"providers\": [\n    {\n      \"name\": \"geog.ai\",\n      \"roles\": [\n        \"licensor\",\n        \"host\"\n      ],\n      \"url\": \"https://geog.ai\"\n    },\n    {\n      \"name\": \"aermod\",\n      \"roles\": [\n        \"processor\"\n      ]\n    }\n  ],\n  \"extent\": {\n    \"spatial\": {\n      \"bbox\": [\n        [\n          -104.5,\n          30.5,\n          -94.0,\n          36.5\n        ]\n      ]\n    },\n    \"temporal\": {\n      \"interval\": [\n        [\n          \"2026-01-01T00:00:00Z\",\n          null\n        ]\n      ]\n    }\n  },\n  \"links\": [\n    {\n      \"rel\": \"self\",\n      \"href\": \"https://api.geog.ai/v1/stac/collections/plume_aermod__oilgas\",\n      \"type\": \"application/json\"\n    },\n    {\n      \"rel\": \"items\",\n      \"href\": \"https://api.geog.ai/v1/stac/collections/plume_aermod__oilgas/items\",\n      \"type\": \"application/geo+json\"\n    },\n    {\n      \"rel\": \"parent\",\n      \"href\": \"https://api.geog.ai/v1/stac/\",\n      \"type\": \"application/json\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "List STAC Items within a Collection",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/collections/:collection_id/items",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac",
                "collections",
                ":collection_id",
                "items"
              ],
              "query": [
                {
                  "key": "bbox",
                  "value": "",
                  "description": "WGS84 bbox `min_lng,min_lat,max_lng,max_lat`. Pushed into PostGIS via ST_Intersects.",
                  "disabled": true
                },
                {
                  "key": "datetime",
                  "value": "",
                  "description": "ISO 8601 instant (`2024-01-01T00:00:00Z`) or interval (`start/end`, `..` for open ends).",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Opaque HMAC-signed pagination cursor returned by the previous page's `next` link.",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "collection_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "`GET /v1/stac/collections/{collection_id}/items`\n\n_operationId:_ `stacCollectionItems`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "Fetch a single STAC Item",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/collections/:collection_id/items/:item_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac",
                "collections",
                ":collection_id",
                "items",
                ":item_id"
              ],
              "variable": [
                {
                  "key": "collection_id",
                  "value": "",
                  "description": ""
                },
                {
                  "key": "item_id",
                  "value": "",
                  "description": "geo_simulation_jobs.job_id"
                }
              ]
            },
            "description": "`GET /v1/stac/collections/{collection_id}/items/{item_id}`\n\n_operationId:_ `stacItem`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "STAC Item Search (GET)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/search",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac",
                "search"
              ],
              "query": [
                {
                  "key": "bbox",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "datetime",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "collections",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "description": "STAC §15 Item Search. Supported predicates:\n  - `bbox` — pushed into PostGIS via `ST_Intersects`.\n  - `datetime` — ISO instant or `start/end` interval.\n  - `collections` — comma-separated `{engine}__{vertical_id}` list.\n  - `limit` / `cursor` — opaque signed pagination.\n\nTenant-scoped: every result row is intersected against the caller's\n`vertical_ids` and `tenant_id` (per Phase 3 §3.11 acceptance\ncriterion 9). CQL2 filtering is **not** supported on this\nendpoint — see roadmap entry `geog-ai-15`.\n\n`GET /v1/stac/search`\n\n_operationId:_ `stacSearchGet`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "STAC Item Search (POST)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/stac/search",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stac",
                "search"
              ]
            },
            "description": "Identical predicate set to `GET /v1/stac/search`, sent as a JSON\nbody. STAC clients use this surface when query strings would\nexceed proxy URL-length limits, or when posting array-shaped\n`bbox` / `collections` values.\n\n`POST /v1/stac/search`\n\n_operationId:_ `stacSearchPost`",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"bbox\": [\n    -100.0,\n    31.0,\n    -99.5,\n    32.0\n  ],\n  \"datetime\": \"2026-04-01T00:00:00Z/2026-04-30T23:59:59Z\",\n  \"collections\": [\n    \"plume_aermod__oilgas\"\n  ],\n  \"limit\": 50\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.geog.ai/v1",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "geog_test_sk_replace_me",
      "type": "string"
    }
  ]
}
