{"openapi":"3.0.0","info":{"title":"Huntertech Public API","version":"25.0.0","description":"Huntertech public infrastructure API for programmatic access to vendor incidents, maintenance, advisories, and updates.\n\n**Base URL:** `https://www.huntertech.io/api/v1/infrastructure`\n\n**OpenAPI JSON:** [`https://docs.huntertech.io/openapi.json`](https://docs.huntertech.io/openapi.json)\n\n**Interactive docs:** [https://docs.huntertech.io](https://docs.huntertech.io) (also at `/docs/api` on www)\n\n**Manage keys:** [/account/api-keys](/account/api-keys) (Pro plan and above)\n\n## Choose your endpoint\n\n| Goal | Use |\n|------|-----|\n| Discover vendor slugs | `GET /vendor-list` (or `/vendors`) |\n| One vendor, one data type | `GET /vendors/{vendor}/{dataType}` (e.g. `/vendors/zscaler/incidents`) |\n| Vendor compliance snapshot | `GET /vendors/{vendor}/compliance` (Standard plan+, e.g. `/vendors/zscaler/compliance`) |\n| All vendors, poll periodically | `GET /incidents` or `GET /maintenance` (every 60-120s) |\n| All vendors, subset of slugs | `GET /incidents?vendor=zscaler,cloudflare` |\n| Real-time incident updates | `GET /incidents/stream` (SSE, not polling) |\n| Vendor health snapshot | `GET /vendor-status/{vendor}` |\n| Reliability stats | `GET /vendor-stats/{vendor}` |\n| Manage your watchlist | `GET /watchlist`, `PUT /watchlist`, `POST /watchlist/{vendor}`, `DELETE /watchlist/{vendor}` |\n| Notification settings | `GET /notification-preferences`, `PUT /notification-preferences` |\n\nPaths ending in `-unified` (e.g. `/incidents-unified`) are **legacy names** for the same handlers as `/incidents` and `/maintenance`.\n\n## Quick start\n\n```bash\n# 1. List vendors (discover slugs and supported data types)\ncurl -sS -H \"X-API-Key: htk_live_your_key_here\" \\\n  \"https://www.huntertech.io/api/v1/infrastructure/vendor-list\"\n\n# 2. Fetch incidents for one vendor\ncurl -sS -H \"X-API-Key: htk_live_your_key_here\" \\\n  \"https://www.huntertech.io/api/v1/infrastructure/vendors/zscaler/incidents?timePeriod=30d\"\n\n# 2b. Fetch compliance certifications (Standard plan or higher)\ncurl -sS -H \"X-API-Key: htk_live_your_key_here\" \\\n  \"https://www.huntertech.io/api/v1/infrastructure/vendors/zscaler/compliance\"\n\n# 3. Poll all vendors (respect ~60s cache; do not poll faster)\ncurl -sS -H \"X-API-Key: htk_live_your_key_here\" \\\n  \"https://www.huntertech.io/api/v1/infrastructure/incidents?activeOnly=true&limit=50\"\n```\n\n## Authentication\n\nInclude your API key on every programmatic request:\n\n```\nX-API-Key: htk_live_your_key_here\n```\n\nOr use a Bearer token:\n\n```\nAuthorization: Bearer htk_live_your_key_here\n```\n\nCreate and manage keys at [/account/api-keys](/account/api-keys). **Requires a Standard plan or above** ([/pricing](/pricing)).\n\n## Rate limits (by plan)\n\n| Plan | Per minute | Per day |\n|------|------------|---------|\n| Standard | 60 | 1,000 |\n| Pro | 120 | 3,000 |\n| Enterprise / VIP | 120 | 10,000 |\n\nExceeded limits return **HTTP 429** with `retryAfter` (seconds). Successful responses may include `X-Cache: HIT|MISS|BYPASS`.\n\n## Response format\n\nList endpoints return JSON with `success: true` and an `items` array. Unified cross-vendor endpoints also include `total`, `fetchedAt`, and `source` fields.\n\n## Error codes\n\n| Status | Meaning |\n|--------|---------|\n| **401** | Missing or invalid API key |\n| **403** | Direct API call blocked (no Origin header and no valid key) |\n| **404** | Unknown vendor slug or unsupported data type |\n| **429** | Rate limit exceeded (see `retryAfter`) |\n| **500** | Server error (retry with backoff) |\n\n## Caching and polling\n\nUnified list and vendor-status responses are cached server-side (~60s incidents/maintenance, ~30s status). Poll no faster than every **60 seconds**. For live incident feeds, prefer `GET /incidents/stream` (SSE).\n\nUse `skipCache=true` only for debugging.\n\n## Browser vs programmatic access\n\nWhen `VENDOR_API_REQUIRE_API_KEY` is enabled, direct curl requests require a valid API key. Browser traffic from huntertech.io continues to work via Origin validation.","contact":{"name":"Huntertech Support","url":"https://www.huntertech.io/pricing"},"license":{"name":"Proprietary","url":"https://www.huntertech.io/legal/terms"}},"servers":[{"url":"https://www.huntertech.io","description":"Production API"},{"url":"https://docs.huntertech.io","description":"API reference docs host"}],"components":{"schemas":{"ApiError":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Rate limit exceeded"},"message":{"type":"string","example":"You have exceeded your daily limit of 1000 API requests."},"limit":{"type":"integer","example":1000},"used":{"type":"integer","example":1000},"retryAfter":{"type":"integer","example":86400,"description":"Seconds until the limit resets"},"currentPlan":{"type":"string","example":"standard"}}},"InfrastructureListResponse":{"type":"object","required":["success","items"],"properties":{"success":{"type":"boolean","example":true},"items":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Incident, maintenance, advisory, or update records"},"total":{"type":"integer","example":42},"fetchedAt":{"type":"string","format":"date-time"},"source":{"type":"string","example":"local-data"},"lastUpdated":{"type":"string","format":"date-time"}}},"VendorListResponse":{"type":"object","required":["success","vendors"],"properties":{"success":{"type":"boolean","example":true},"vendors":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"zscaler"},"name":{"type":"string","example":"Zscaler"},"website":{"type":"string","format":"uri"},"availableDataTypes":{"type":"array","items":{"type":"string"},"example":["incidents","maintenance","advisories"]}}}}}},"WatchlistResponse":{"type":"object","required":["success","vendors","count"],"properties":{"success":{"type":"boolean","example":true},"vendors":{"type":"array","items":{"type":"string"},"example":["zscaler","cloudflare"]},"count":{"type":"integer","example":2},"limit":{"type":"integer","example":10},"remaining":{"type":"integer","example":8},"isUnlimited":{"type":"boolean","example":false}}},"NotificationPreferencesResponse":{"type":"object","required":["success","preferences"],"properties":{"success":{"type":"boolean","example":true},"preferences":{"type":"object","description":"Sanitized notification settings (secrets such as RSS tokens and PagerDuty keys are omitted or masked).","additionalProperties":true}}},"ComplianceResponse":{"type":"object","required":["success","items"],"properties":{"success":{"type":"boolean","example":true},"vendor":{"type":"string","example":"zscaler"},"sourceUrl":{"type":"string","format":"uri","nullable":true},"sourceType":{"type":"string","example":"compliance"},"lastUpdated":{"type":"string","format":"date-time","nullable":true},"itemCount":{"type":"integer","example":31},"message":{"type":"string","nullable":true,"description":"Present when the vendor has no certifications in the current snapshot."},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"SOC 2 Type 2"},"description":{"type":"string"},"category":{"type":"string","example":"commercial"},"compliancePageLink":{"type":"string","format":"uri","nullable":true},"researchedAt":{"type":"string","format":"date-time","nullable":true}}}},"scorecard":{"type":"object","description":"Rollup counts by certification category.","additionalProperties":true}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"success":false,"error":"Unauthorized","message":"Valid API key required. Create one at /account/api-keys (Pro plan and above)."}}}},"Forbidden":{"description":"Direct API call blocked without a valid key or browser Origin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"success":false,"error":"Direct API calls not allowed","message":"This endpoint requires requests from an authorized web application or a valid API key.","hint":"Obtain an API key at /account/api-keys (Pro plan and above)."}}}},"RateLimited":{"description":"Plan rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"},"example":{"success":false,"error":"Rate limit exceeded","message":"You have exceeded your daily limit of 1000 API requests.","limit":1000,"used":1000,"retryAfter":86400,"currentPlan":"standard"}}}},"NotFound":{"description":"Unknown vendor or unsupported data type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key (htk_live_…). Create keys at /account/api-keys (Pro plan and above). Bearer token auth is also supported."}}},"security":[{"apiKeyAuth":[]}],"paths":{"/api/v1/infrastructure/incidents/stream":{"get":{"summary":"Stream incidents (SSE)","description":"**Real-time** server-sent events for incident changes across vendors. Prefer this over polling `/incidents` when you need push-style updates.\n\nConnect with an EventSource client. Requires browser Origin or API key when `VENDOR_API_REQUIRE_API_KEY` is enabled.","tags":["Incidents"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Number of items to return"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Number of items to skip"},{"name":"vendor","in":"query","schema":{"type":"string"},"description":"Filter by vendor"},{"name":"status","in":"query","schema":{"type":"string","enum":["resolved","investigating","monitoring"]},"description":"Filter by status"}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-stats/{vendor}":{"get":{"summary":"Vendor statistics","description":"Incident and reliability statistics for a single vendor.","tags":["Analytics"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"},{"name":"timePeriod","in":"query","schema":{"type":"string","example":"30d"},"description":"History window (e.g. 7d, 30d, 90d). Capped by your plan data window (Standard: 30d, Pro: 90d, Enterprise: unlimited)."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-stats-aggregate":{"get":{"summary":"Aggregate vendor statistics","description":"Rollup statistics across all vendors (counts, badge breakdowns, etc.).","tags":["Analytics"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-stats-favorites":{"get":{"summary":"Batch vendor stats for favorites","description":"Returns per-vendor stats for a comma-separated `vendors` query list. Prefer `POST /dashboard-favorites` with `sections: [\"stats\"]` for large favorite lists.","tags":["Analytics"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"timePeriod","in":"query","schema":{"type":"string","example":"30d"},"description":"History window (e.g. 7d, 30d, 90d). Capped by your plan data window (Standard: 30d, Pro: 90d, Enterprise: unlimited)."},{"name":"vendor","in":"query","schema":{"type":"string","example":"zscaler,cloudflare"},"description":"Filter to one or more vendor slugs (comma-separated). Alias: vendors."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-info/{vendor}":{"get":{"summary":"Vendor profile","description":"Metadata for a single vendor (name, description, website, category).","tags":["Vendors"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-status/{vendor}":{"get":{"summary":"Vendor status","description":"Current operational status summary for a vendor (active incidents, maintenance, etc.).","tags":["Vendors"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-capabilities/{vendor}":{"get":{"summary":"Vendor capabilities","description":"Which data types and features are available for a vendor.","tags":["Vendors"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-list":{"get":{"summary":"List vendors","description":"Returns all tracked vendors with display names, websites, and supported data types (incidents, maintenance, advisories, updates). **Start here** to discover vendor slugs for other endpoints.","tags":["Discovery"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/incidents-unified":{"get":{"summary":"List incidents (all vendors)","description":"**Canonical path:** prefer `GET /incidents` (this `-unified` URL is the legacy name; same handler).\n\nReturns incidents across every vendor in one request. Filter with `timePeriod`, `activeOnly`, or `vendor`. For one vendor only, `GET /vendors/{vendor}/incidents` is often simpler.\n\n**When to use:** polling all vendors every 60-120s. For live updates, use `GET /incidents/stream` (SSE).","tags":["Incidents"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Number of items to return"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Number of items to skip"},{"name":"vendor","in":"query","schema":{"type":"string"},"description":"Filter by vendor"},{"name":"status","in":"query","schema":{"type":"string","enum":["resolved","investigating","monitoring"]},"description":"Filter by status"},{"name":"timePeriod","in":"query","schema":{"type":"string","example":"30d"},"description":"History window (e.g. 7d, 30d, 90d). Capped by your plan data window (Standard: 30d, Pro: 90d, Enterprise: unlimited)."},{"name":"activeOnly","in":"query","schema":{"type":"boolean"},"description":"When true, return only ongoing (unresolved) incidents."},{"name":"skipCache","in":"query","schema":{"type":"boolean"},"description":"When true, bypass server-side cache and fetch fresh data (debugging only)."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/maintenance-unified":{"get":{"summary":"List maintenance (all vendors)","description":"**Canonical path:** prefer `GET /maintenance` (this `-unified` URL is the legacy name; same handler).\n\nScheduled and historical maintenance across all vendors. Filter with `scheduledOnly`, `limit`, or `vendor`.","tags":["Maintenance"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"scheduledOnly","in":"query","schema":{"type":"boolean"},"description":"When true, return only upcoming (not completed) maintenance windows."},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"Maximum number of records to return."},{"name":"vendor","in":"query","schema":{"type":"string","example":"zscaler,cloudflare"},"description":"Filter to one or more vendor slugs (comma-separated). Alias: vendors."},{"name":"skipCache","in":"query","schema":{"type":"boolean"},"description":"When true, bypass server-side cache and fetch fresh data (debugging only)."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/advisories-unified":{"get":{"summary":"List security advisories (all vendors)","description":"Cross-vendor security advisories in one request. Filter with `timePeriod`, `limit`, or `vendor` (comma-separated slugs). Used by the dashboard Security column and Recent Activity feed.","tags":["Advisories"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"timePeriod","in":"query","schema":{"type":"string","example":"30d"},"description":"History window (e.g. 7d, 30d, 90d). Capped by your plan data window (Standard: 30d, Pro: 90d, Enterprise: unlimited)."},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"Maximum number of records to return."},{"name":"vendor","in":"query","schema":{"type":"string","example":"zscaler,cloudflare"},"description":"Filter to one or more vendor slugs (comma-separated). Alias: vendors."},{"name":"skipCache","in":"query","schema":{"type":"boolean"},"description":"When true, bypass server-side cache and fetch fresh data (debugging only)."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/dashboard-recent-activity":{"get":{"summary":"Dashboard recent activity (merged feed)","description":"Merged incidents, maintenance, advisories, updates, and press across favorite vendors in one request. Prefer `POST /dashboard-favorites` with `sections: [\"recentActivity\"]` when loading 50+ vendors (no URL length limits).","tags":["Dashboard"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"timePeriod","in":"query","schema":{"type":"string","example":"30d"},"description":"History window (e.g. 7d, 30d, 90d). Capped by your plan data window (Standard: 30d, Pro: 90d, Enterprise: unlimited)."},{"name":"vendor","in":"query","schema":{"type":"string","example":"zscaler,cloudflare"},"description":"Filter to one or more vendor slugs (comma-separated). Alias: vendors."},{"name":"skipCache","in":"query","schema":{"type":"boolean"},"description":"When true, bypass server-side cache and fetch fresh data (debugging only)."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendor-count":{"get":{"summary":"Vendor count","description":"Total number of vendors tracked by Huntertech.","tags":["Discovery"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendors/{vendor}/compliance":{"get":{"summary":"Get vendor compliance data","description":"Returns certifications, frameworks, and scorecard statistics for a vendor compliance snapshot.\n\n**Requires Standard plan or higher** (same as the web compliance pages). Use `GET /vendor-capabilities/{vendor}` to see whether compliance is available for a slug.\n\nExample: `/api/v1/infrastructure/vendors/zscaler/compliance`\n\nLegacy alias: `/api/v1/infrastructure/zscaler-compliance` (same response).","tags":["Compliance"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplianceResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendors":{"get":{"summary":"List vendors (alias)","description":"Alias for GET /vendor-list. Same response.","tags":["Discovery"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/incidents":{"get":{"summary":"List incidents (recommended)","description":"**Recommended** cross-vendor incidents endpoint. Same handler and response as `/incidents-unified`.\n\nUse `vendor=zscaler,cloudflare` to limit fan-out to specific slugs.","tags":["Incidents"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Number of items to return"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Number of items to skip"},{"name":"vendor","in":"query","schema":{"type":"string"},"description":"Filter by vendor"},{"name":"status","in":"query","schema":{"type":"string","enum":["resolved","investigating","monitoring"]},"description":"Filter by status"},{"name":"timePeriod","in":"query","schema":{"type":"string","example":"30d"},"description":"History window (e.g. 7d, 30d, 90d). Capped by your plan data window (Standard: 30d, Pro: 90d, Enterprise: unlimited)."},{"name":"activeOnly","in":"query","schema":{"type":"boolean"},"description":"When true, return only ongoing (unresolved) incidents."},{"name":"skipCache","in":"query","schema":{"type":"boolean"},"description":"When true, bypass server-side cache and fetch fresh data (debugging only)."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/maintenance":{"get":{"summary":"List maintenance (recommended)","description":"**Recommended** cross-vendor maintenance endpoint. Same handler and response as `/maintenance-unified`.","tags":["Maintenance"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"scheduledOnly","in":"query","schema":{"type":"boolean"},"description":"When true, return only upcoming (not completed) maintenance windows."},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"Maximum number of records to return."},{"name":"vendor","in":"query","schema":{"type":"string","example":"zscaler,cloudflare"},"description":"Filter to one or more vendor slugs (comma-separated). Alias: vendors."},{"name":"skipCache","in":"query","schema":{"type":"boolean"},"description":"When true, bypass server-side cache and fetch fresh data (debugging only)."}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/watchlist":{"get":{"summary":"Manage vendor watchlist","description":"Read or replace the authenticated user's vendor watchlist. Watchlist vendors drive dashboard filters and notification scope in the web app.\n\n**Requires authentication** (API key or logged-in session). Free plans are limited to 10 vendors; paid plans are unlimited.\n\nUse `GET /vendor-list` to discover valid vendor slugs.","tags":["Watchlist"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[],"security":[{"apiKeyAuth":[]}]},"put":{"summary":"Manage vendor watchlist","description":"Read or replace the authenticated user's vendor watchlist. Watchlist vendors drive dashboard filters and notification scope in the web app.\n\n**Requires authentication** (API key or logged-in session). Free plans are limited to 10 vendors; paid plans are unlimited.\n\nUse `GET /vendor-list` to discover valid vendor slugs.","tags":["Watchlist"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Request body","properties":{"data":{"type":"object","description":"Request data"}}}}}},"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/watchlist/{vendor}":{"post":{"summary":"Add or remove watchlist vendor","description":"Add (`POST`) or remove (`DELETE`) a single vendor slug from the authenticated user's watchlist. Adding an existing vendor is idempotent.","tags":["Watchlist"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Request body","properties":{"data":{"type":"object","description":"Request data"}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"}],"security":[{"apiKeyAuth":[]}]},"delete":{"summary":"Add or remove watchlist vendor","description":"Add (`POST`) or remove (`DELETE`) a single vendor slug from the authenticated user's watchlist. Adding an existing vendor is idempotent.","tags":["Watchlist"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"}],"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/dashboard-favorites":{"post":{"summary":"Dashboard favorites bundle","description":"**Requires authentication.** Single POST for dashboard data across many favorite vendors. JSON body: `{ vendors: string[], sections?: string[], timePeriod?: string }`. Sections: `stats`, `maintenance`, `advisories`, `recentActivity` (default: first three). Avoids URL vendor-list limits and browser fan-out.","tags":["Dashboard"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Request body","properties":{"data":{"type":"object","description":"Request data"}}}}}},"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/notification-preferences":{"get":{"summary":"Notification preferences","description":"Read or update the authenticated user's notification delivery settings (in-app, email, Slack, webhook, PagerDuty, RSS, newsletter, muted vendors, and content filters).\n\n**Requires authentication** (API key or logged-in session). Send a partial object on `PUT`; omitted fields are unchanged. Slack linking remains OAuth-only via the web app (`slack_connection` is ignored on PUT).\n\nWatchlist vendors scope which vendors notifications apply to unless overridden per channel.","tags":["Notifications"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[],"security":[{"apiKeyAuth":[]}]},"put":{"summary":"Notification preferences","description":"Read or update the authenticated user's notification delivery settings (in-app, email, Slack, webhook, PagerDuty, RSS, newsletter, muted vendors, and content filters).\n\n**Requires authentication** (API key or logged-in session). Send a partial object on `PUT`; omitted fields are unchanged. Slack linking remains OAuth-only via the web app (`slack_connection` is ignored on PUT).\n\nWatchlist vendors scope which vendors notifications apply to unless overridden per channel.","tags":["Notifications"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Request body","properties":{"data":{"type":"object","description":"Request data"}}}}}},"security":[{"apiKeyAuth":[]}]}},"/api/v1/infrastructure/vendors/{vendor}/{dataType}":{"get":{"summary":"Get vendor data","description":"Primary endpoint for vendor-scoped data. Replace `{vendor}` with a slug from vendor-list and `{dataType}` with incidents, maintenance, advisories, or updates.\n\nExample: `/api/v1/infrastructure/vendors/zscaler/incidents`","tags":["Vendors"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfrastructureListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"message":{"type":"string"}}}}}}},"parameters":[{"name":"vendor","in":"path","required":true,"schema":{"type":"string"},"description":"vendor parameter"},{"name":"dataType","in":"path","required":true,"schema":{"type":"string"},"description":"dataType parameter"},{"name":"timePeriod","in":"query","schema":{"type":"string","example":"30d"},"description":"History window (e.g. 7d, 30d, 90d). Capped by your plan data window (Standard: 30d, Pro: 90d, Enterprise: unlimited)."},{"name":"activeOnly","in":"query","schema":{"type":"boolean"},"description":"When true, return only ongoing (unresolved) incidents."},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"Maximum number of records to return."}],"security":[{"apiKeyAuth":[]}]}}},"x-tagGroups":[{"name":"Getting started","tags":["Discovery"]},{"name":"Vendor data","tags":["Vendors","Incidents","Maintenance","Compliance"]},{"name":"Analytics","tags":["Analytics"]},{"name":"Account","tags":["Watchlist","Notifications"]}]}