From e7dd207a62f78ad3f8807cbcbd7b602788ee69ef Mon Sep 17 00:00:00 2001 From: Phillip Tarrant Date: Wed, 19 Nov 2025 19:56:28 -0600 Subject: [PATCH] Fix AlertRule initialization to use config_id instead of config_file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated init_db.py to use config_id field after database migration, fixing container startup error on new systems. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/init_db.py | 4 +- docs/API_REFERENCE.md | 906 +++++++++++++++++++++++++++--------------- 2 files changed, 586 insertions(+), 324 deletions(-) diff --git a/app/init_db.py b/app/init_db.py index 12650d2..edad5d4 100755 --- a/app/init_db.py +++ b/app/init_db.py @@ -98,7 +98,7 @@ def init_default_alert_rules(session): 'webhook_enabled': False, 'severity': 'critical', 'filter_conditions': None, - 'config_file': None + 'config_id': None } ] @@ -113,7 +113,7 @@ def init_default_alert_rules(session): webhook_enabled=rule_data['webhook_enabled'], severity=rule_data['severity'], filter_conditions=rule_data['filter_conditions'], - config_file=rule_data['config_file'], + config_id=rule_data['config_id'], created_at=datetime.now(timezone.utc), updated_at=datetime.now(timezone.utc) ) diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md index 47e73e9..f20b3b4 100644 --- a/docs/API_REFERENCE.md +++ b/docs/API_REFERENCE.md @@ -1,22 +1,23 @@ # SneakyScanner Web API Reference -**Version:** 5.0 (Phase 5) +**Version:** 6.0 (Database-Based Configuration) **Base URL:** `http://localhost:5000` **Authentication:** Session-based (Flask-Login) ## Table of Contents 1. [Authentication](#authentication) -2. [Scans API](#scans-api) +2. [Sites API](#sites-api) 3. [Configs API](#configs-api) -4. [Schedules API](#schedules-api) -5. [Stats API](#stats-api) -6. [Settings API](#settings-api) -7. [Alerts API](#alerts-api) -8. [Webhooks API](#webhooks-api) -9. [Error Handling](#error-handling) -10. [Status Codes](#status-codes) -11. [Request/Response Examples](#request-response-examples) +4. [Scans API](#scans-api) +5. [Schedules API](#schedules-api) +6. [Stats API](#stats-api) +7. [Settings API](#settings-api) +8. [Alerts API](#alerts-api) +9. [Webhooks API](#webhooks-api) +10. [Error Handling](#error-handling) +11. [Status Codes](#status-codes) +12. [Request/Response Examples](#request-response-examples) --- @@ -96,6 +97,543 @@ Destroy the current session. --- +## Sites API + +Manage reusable site definitions, including CIDR ranges and IP-level overrides. Sites are the building blocks for scan configurations. + +### List Sites + +Retrieve a paginated list of all sites. + +**Endpoint:** `GET /api/sites` + +**Authentication:** Required + +**Query Parameters:** + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `page` | integer | No | 1 | Page number (1-indexed) | +| `per_page` | integer | No | 20 | Items per page (1-100) | +| `all` | string | No | - | Set to "true" to return all sites without pagination | + +**Success Response (200 OK):** +```json +{ + "sites": [ + { + "id": 1, + "name": "Production DC", + "description": "Production datacenter servers", + "ip_count": 25, + "created_at": "2025-11-19T10:30:00Z", + "updated_at": "2025-11-19T10:30:00Z" + } + ], + "total": 5, + "page": 1, + "per_page": 20, + "total_pages": 1, + "has_prev": false, + "has_next": false +} +``` + +**Usage Example:** +```bash +# List first page +curl -X GET http://localhost:5000/api/sites \ + -b cookies.txt + +# Get all sites (for dropdowns) +curl -X GET "http://localhost:5000/api/sites?all=true" \ + -b cookies.txt +``` + +### Get Site + +Retrieve details for a specific site including all IPs. + +**Endpoint:** `GET /api/sites/{id}` + +**Authentication:** Required + +**Path Parameters:** + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | integer | Yes | Site ID | + +**Success Response (200 OK):** +```json +{ + "id": 1, + "name": "Production DC", + "description": "Production datacenter servers", + "ip_count": 25, + "created_at": "2025-11-19T10:30:00Z", + "updated_at": "2025-11-19T10:30:00Z" +} +``` + +**Usage Example:** +```bash +curl -X GET http://localhost:5000/api/sites/1 \ + -b cookies.txt +``` + +### Create Site + +Create a new site. + +**Endpoint:** `POST /api/sites` + +**Authentication:** Required + +**Request Body:** +```json +{ + "name": "Production DC", + "description": "Production datacenter servers" +} +``` + +**Request Body Fields:** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | Yes | Site name (must be unique) | +| `description` | string | No | Site description | + +**Success Response (201 Created):** +```json +{ + "id": 1, + "name": "Production DC", + "description": "Production datacenter servers", + "ip_count": 0, + "created_at": "2025-11-19T10:30:00Z", + "updated_at": "2025-11-19T10:30:00Z" +} +``` + +**Usage Example:** +```bash +curl -X POST http://localhost:5000/api/sites \ + -H "Content-Type: application/json" \ + -d '{"name":"Production DC","description":"Production servers"}' \ + -b cookies.txt +``` + +### Update Site + +Update site metadata. + +**Endpoint:** `PUT /api/sites/{id}` + +**Authentication:** Required + +**Path Parameters:** + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | integer | Yes | Site ID | + +**Request Body:** +```json +{ + "name": "Updated Name", + "description": "Updated description" +} +``` + +**Success Response (200 OK):** +```json +{ + "id": 1, + "name": "Updated Name", + "description": "Updated description", + "ip_count": 25, + "created_at": "2025-11-19T10:30:00Z", + "updated_at": "2025-11-19T11:00:00Z" +} +``` + +### Delete Site + +Delete a site. Fails if site is used in any scan. + +**Endpoint:** `DELETE /api/sites/{id}` + +**Authentication:** Required + +**Success Response (200 OK):** +```json +{ + "message": "Site 1 deleted successfully" +} +``` + +### Bulk Add IPs + +Add multiple IPs to a site from CIDR or list. + +**Endpoint:** `POST /api/sites/{id}/ips/bulk` + +**Authentication:** Required + +**Request Body (CIDR):** +```json +{ + "source_type": "cidr", + "cidr": "10.0.0.0/24", + "expected_ping": true, + "expected_tcp_ports": [22, 80, 443], + "expected_udp_ports": [53] +} +``` + +**Request Body (List):** +```json +{ + "source_type": "list", + "ips": ["10.0.0.1", "10.0.0.2", "10.0.0.3"], + "expected_ping": true, + "expected_tcp_ports": [22, 80, 443], + "expected_udp_ports": [] +} +``` + +**Success Response (201 Created):** +```json +{ + "ip_count": 254, + "errors": [] +} +``` + +### List IPs in Site + +List IPs in a site with pagination. + +**Endpoint:** `GET /api/sites/{id}/ips` + +**Authentication:** Required + +**Query Parameters:** + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `page` | integer | No | 1 | Page number | +| `per_page` | integer | No | 50 | Items per page (max: 200) | + +**Success Response (200 OK):** +```json +{ + "ips": [ + { + "id": 1, + "ip_address": "10.0.0.1", + "expected_ping": true, + "expected_tcp_ports": [22, 80, 443], + "expected_udp_ports": [] + } + ], + "total": 254, + "page": 1, + "per_page": 50, + "total_pages": 6, + "has_prev": false, + "has_next": true +} +``` + +### Add Standalone IP + +Add a single IP to a site. + +**Endpoint:** `POST /api/sites/{id}/ips` + +**Authentication:** Required + +**Request Body:** +```json +{ + "ip_address": "10.0.0.100", + "expected_ping": true, + "expected_tcp_ports": [22, 443], + "expected_udp_ports": [] +} +``` + +**Success Response (201 Created):** +```json +{ + "id": 100, + "ip_address": "10.0.0.100", + "expected_ping": true, + "expected_tcp_ports": [22, 443], + "expected_udp_ports": [] +} +``` + +### Update IP Settings + +Update settings for an individual IP. + +**Endpoint:** `PUT /api/sites/{site_id}/ips/{ip_id}` + +**Authentication:** Required + +**Request Body:** +```json +{ + "expected_ping": false, + "expected_tcp_ports": [443, 8080], + "expected_udp_ports": [53] +} +``` + +### Remove IP + +Remove an IP from a site. + +**Endpoint:** `DELETE /api/sites/{site_id}/ips/{ip_id}` + +**Authentication:** Required + +**Success Response (200 OK):** +```json +{ + "message": "IP 100 removed successfully" +} +``` + +### Get Site Usage + +Get list of scans that use this site. + +**Endpoint:** `GET /api/sites/{id}/usage` + +**Authentication:** Required + +**Success Response (200 OK):** +```json +{ + "site_id": 1, + "site_name": "Production DC", + "scans": [ + { + "id": 42, + "title": "Production Scan", + "timestamp": "2025-11-19T10:30:00Z" + } + ], + "count": 1 +} +``` + +--- + +## Configs API + +Manage scan configurations stored in the database. Configs reference one or more sites to define what to scan. + +### List Configs + +Retrieve all scan configurations. + +**Endpoint:** `GET /api/configs` + +**Authentication:** Required + +**Success Response (200 OK):** +```json +{ + "configs": [ + { + "id": 1, + "title": "Production Scan", + "description": "Weekly production scan", + "site_count": 3, + "sites": [ + {"id": 1, "name": "Production DC"}, + {"id": 2, "name": "DMZ"} + ], + "created_at": "2025-11-19T10:30:00Z", + "updated_at": "2025-11-19T10:30:00Z" + } + ] +} +``` + +### Get Config + +Retrieve a specific configuration by ID. + +**Endpoint:** `GET /api/configs/{id}` + +**Authentication:** Required + +**Path Parameters:** + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | integer | Yes | Config ID | + +**Success Response (200 OK):** +```json +{ + "id": 1, + "title": "Production Scan", + "description": "Weekly production scan", + "site_count": 3, + "sites": [ + { + "id": 1, + "name": "Production DC", + "description": "Production servers", + "ip_count": 25 + } + ], + "created_at": "2025-11-19T10:30:00Z", + "updated_at": "2025-11-19T10:30:00Z" +} +``` + +### Create Config + +Create a new scan configuration. + +**Endpoint:** `POST /api/configs` + +**Authentication:** Required + +**Request Body:** +```json +{ + "title": "Production Scan", + "description": "Weekly production scan", + "site_ids": [1, 2, 3] +} +``` + +**Request Body Fields:** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `title` | string | Yes | Config title | +| `description` | string | No | Config description | +| `site_ids` | array | Yes | Array of site IDs to include | + +**Success Response (201 Created):** +```json +{ + "success": true, + "config": { + "id": 1, + "title": "Production Scan", + "description": "Weekly production scan", + "site_count": 3, + "sites": [...], + "created_at": "2025-11-19T10:30:00Z", + "updated_at": "2025-11-19T10:30:00Z" + } +} +``` + +**Usage Example:** +```bash +curl -X POST http://localhost:5000/api/configs \ + -H "Content-Type: application/json" \ + -d '{"title":"My Scan","site_ids":[1,2]}' \ + -b cookies.txt +``` + +### Update Config + +Update an existing configuration. + +**Endpoint:** `PUT /api/configs/{id}` + +**Authentication:** Required + +**Request Body:** +```json +{ + "title": "Updated Title", + "description": "Updated description", + "site_ids": [1, 2, 3, 4] +} +``` + +**Note:** All fields are optional. Only provided fields will be updated. + +**Success Response (200 OK):** +```json +{ + "success": true, + "config": {...} +} +``` + +### Delete Config + +Delete a configuration. + +**Endpoint:** `DELETE /api/configs/{id}` + +**Authentication:** Required + +**Success Response (200 OK):** +```json +{ + "success": true, + "message": "Config deleted successfully" +} +``` + +### Add Site to Config + +Add a site to an existing config. + +**Endpoint:** `POST /api/configs/{config_id}/sites` + +**Authentication:** Required + +**Request Body:** +```json +{ + "site_id": 5 +} +``` + +**Success Response (200 OK):** +```json +{ + "success": true, + "config": {...} +} +``` + +### Remove Site from Config + +Remove a site from a config. + +**Endpoint:** `DELETE /api/configs/{config_id}/sites/{site_id}` + +**Authentication:** Required + +**Success Response (200 OK):** +```json +{ + "success": true, + "config": {...} +} +``` + +--- + ## Scans API Manage network scans: trigger, list, view, and delete. @@ -111,10 +649,16 @@ Start a new background scan. **Request Body:** ```json { - "config_file": "/app/configs/example-site.yaml" + "config_id": 1 } ``` +**Request Body Fields:** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `config_id` | integer | Yes | Database config ID | + **Success Response (201 Created):** ```json { @@ -126,19 +670,19 @@ Start a new background scan. **Error Responses:** -*400 Bad Request* - Invalid config file: +*400 Bad Request* - Invalid or missing config_id: ```json { - "error": "Invalid config file", - "message": "Config file does not exist or is not valid YAML" + "error": "Invalid request", + "message": "config_id is required" } ``` -*500 Internal Server Error* - Scan queue failure: +*400 Bad Request* - Config not found: ```json { - "error": "Failed to queue scan", - "message": "Internal server error" + "error": "Invalid request", + "message": "Config with ID 99 not found" } ``` @@ -146,7 +690,7 @@ Start a new background scan. ```bash curl -X POST http://localhost:5000/api/scans \ -H "Content-Type: application/json" \ - -d '{"config_file":"/app/configs/production.yaml"}' \ + -d '{"config_id":1}' \ -b cookies.txt ``` @@ -540,293 +1084,6 @@ Check API health status. --- -## Configs API - -Manage scan configuration files including creation, upload, editing, and deletion. - -### List Configs - -Retrieve a list of all available configuration files. - -**Endpoint:** `GET /api/configs` - -**Authentication:** Required - -**Success Response (200 OK):** -```json -{ - "configs": [ - { - "filename": "prod-scan.yaml", - "title": "Production Scan", - "path": "/app/configs/prod-scan.yaml", - "created_at": "2025-11-15T10:30:00Z", - "size_bytes": 1234, - "used_by_schedules": ["Daily Production Scan"] - } - ] -} -``` - -**Usage Example:** -```bash -curl -X GET http://localhost:5000/api/configs \ - -b cookies.txt -``` - -### Get Config - -Retrieve a specific configuration file's content and parsed data. - -**Endpoint:** `GET /api/configs/{filename}` - -**Authentication:** Required - -**Path Parameters:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `filename` | string | Yes | Config filename | - -**Success Response (200 OK):** -```json -{ - "filename": "prod-scan.yaml", - "content": "title: Production Scan\nsites:\n - ...", - "parsed": { - "title": "Production Scan", - "sites": [...] - } -} -``` - -**Error Responses:** - -*404 Not Found* - Config file doesn't exist: -```json -{ - "error": "Not found", - "message": "Config file not found" -} -``` - -*400 Bad Request* - Invalid YAML: -```json -{ - "error": "Invalid config", - "message": "YAML parsing error details" -} -``` - -**Usage Example:** -```bash -curl -X GET http://localhost:5000/api/configs/prod-scan.yaml \ - -b cookies.txt -``` - -### Create Config from CIDR - -Create a new configuration file from a CIDR range. - -**Endpoint:** `POST /api/configs/create-from-cidr` - -**Authentication:** Required - -**Request Body:** -```json -{ - "title": "My Network Scan", - "cidr": "10.0.0.0/24", - "site_name": "Production Network", - "ping_default": false -} -``` - -**Success Response (200 OK):** -```json -{ - "success": true, - "filename": "my-network-scan.yaml", - "preview": "title: My Network Scan\nsites:\n - ..." -} -``` - -**Error Responses:** - -*400 Bad Request* - Missing required fields or invalid CIDR: -```json -{ - "error": "Validation error", - "message": "Invalid CIDR range" -} -``` - -**Usage Example:** -```bash -curl -X POST http://localhost:5000/api/configs/create-from-cidr \ - -H "Content-Type: application/json" \ - -d '{"title":"My Scan","cidr":"10.0.0.0/24"}' \ - -b cookies.txt -``` - -### Upload YAML Config - -Upload a YAML configuration file directly. - -**Endpoint:** `POST /api/configs/upload-yaml` - -**Authentication:** Required - -**Request Body:** -```multipart/form-data -file: -filename: "custom-name.yaml" (optional) -``` - -**Success Response (200 OK):** -```json -{ - "success": true, - "filename": "custom-name.yaml" -} -``` - -**Error Responses:** - -*400 Bad Request* - No file or invalid YAML: -```json -{ - "error": "Validation error", - "message": "File must be a YAML file (.yaml or .yml extension)" -} -``` - -**Usage Example:** -```bash -curl -X POST http://localhost:5000/api/configs/upload-yaml \ - -F "file=@/path/to/config.yaml" \ - -b cookies.txt -``` - -### Download Config - -Download an existing configuration file. - -**Endpoint:** `GET /api/configs/{filename}/download` - -**Authentication:** Required - -**Path Parameters:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `filename` | string | Yes | Config filename | - -**Success Response (200 OK):** -Returns YAML file as download. - -**Usage Example:** -```bash -curl -X GET http://localhost:5000/api/configs/prod-scan.yaml/download \ - -b cookies.txt \ - -o prod-scan.yaml -``` - -### Update Config - -Update an existing configuration file with new YAML content. - -**Endpoint:** `PUT /api/configs/{filename}` - -**Authentication:** Required - -**Path Parameters:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `filename` | string | Yes | Config filename | - -**Request Body:** -```json -{ - "content": "title: Updated Scan\nsites:\n - ..." -} -``` - -**Success Response (200 OK):** -```json -{ - "success": true, - "message": "Config updated successfully" -} -``` - -**Error Responses:** - -*404 Not Found* - Config file doesn't exist: -```json -{ - "error": "Not found", - "message": "Config file not found" -} -``` - -*400 Bad Request* - Invalid YAML: -```json -{ - "error": "Validation error", - "message": "Invalid YAML structure" -} -``` - -**Usage Example:** -```bash -curl -X PUT http://localhost:5000/api/configs/prod-scan.yaml \ - -H "Content-Type: application/json" \ - -d '{"content":"title: Updated\nsites: []"}' \ - -b cookies.txt -``` - -### Delete Config - -Delete a configuration file and cascade delete associated schedules. - -**Endpoint:** `DELETE /api/configs/{filename}` - -**Authentication:** Required - -**Path Parameters:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `filename` | string | Yes | Config filename | - -**Success Response (200 OK):** -```json -{ - "success": true, - "message": "Config deleted successfully" -} -``` - -**Error Responses:** - -*404 Not Found* - Config file doesn't exist: -```json -{ - "error": "Not found", - "message": "Config file not found" -} -``` - -**Usage Example:** -```bash -curl -X DELETE http://localhost:5000/api/configs/prod-scan.yaml \ - -b cookies.txt -``` - ---- - ## Schedules API Manage scheduled scans including creation, updates, and manual triggering. @@ -1717,7 +1974,8 @@ List all configured alert rules. "filter_conditions": { "ip_pattern": "192.168.*" }, - "config_file": "/app/configs/production.yaml", + "config_id": 1, + "config_title": "Production Scan", "created_at": "2025-11-01T10:00:00Z", "updated_at": "2025-11-15T08:30:00Z" } @@ -1753,7 +2011,7 @@ Create a new alert rule. "filter_conditions": { "ip_pattern": "192.168.*" }, - "config_file": "/app/configs/production.yaml" + "config_id": 1 } ``` @@ -1769,7 +2027,7 @@ Create a new alert rule. | `webhook_enabled` | boolean | No | Send webhook for this rule (default: false) | | `severity` | string | No | Alert severity: critical, warning, info (default: warning) | | `filter_conditions` | object | No | JSON object with filter conditions | -| `config_file` | string | No | Config file to apply rule to (null for all configs) | +| `config_id` | integer | No | Config ID to apply rule to (null for all configs) | **Success Response (201 Created):** ```json @@ -1788,7 +2046,8 @@ Create a new alert rule. "filter_conditions": { "ip_pattern": "192.168.*" }, - "config_file": "/app/configs/production.yaml", + "config_id": 1, + "config_title": "Production Scan", "created_at": "2025-11-18T10:00:00Z", "updated_at": "2025-11-18T10:00:00Z" } @@ -1843,7 +2102,7 @@ curl -X POST http://localhost:5000/api/alerts/rules \ "rule_type": "drift_detection", "threshold": 10, "severity": "critical", - "config_file": "/app/configs/production.yaml", + "config_id": 1, "email_enabled": true, "webhook_enabled": true }' \ @@ -1892,7 +2151,8 @@ Update an existing alert rule. "webhook_enabled": false, "severity": "critical", "filter_conditions": null, - "config_file": "/app/configs/production.yaml", + "config_id": 1, + "config_title": "Production Scan", "created_at": "2025-11-01T10:00:00Z", "updated_at": "2025-11-18T10:00:00Z" } @@ -2901,7 +3161,7 @@ curl -X POST http://localhost:5000/auth/login \ # 2. Trigger a new scan RESPONSE=$(curl -s -X POST http://localhost:5000/api/scans \ -H "Content-Type: application/json" \ - -d '{"config_file":"/app/configs/production.yaml"}' \ + -d '{"config_id":1}' \ -b cookies.txt) # Extract scan ID from response @@ -3021,26 +3281,28 @@ All inputs are validated: ## Versioning -**Current Version:** 5.0 (Phase 5) +**Current Version:** 6.0 (Database-Based Configuration) -API versioning will be implemented in future phases. For now, the API is considered stable for Phase 5 features. +API versioning will be implemented in future releases. The API is considered stable for Version 6.0 features. **Recent Breaking Changes:** - Phase 2 → Phase 3: Added scan comparison endpoint, schedules API - Phase 3 → Phase 4: Added configs API, stats API, multiple settings endpoints - Phase 4 → Phase 5: Full alerts API implementation with filtering, acknowledgment, and statistics +- Phase 5 → Version 6.0: **Major** - Migrated from file-based configs to database. Added Sites API. Scans now use `config_id` instead of `config_file`. Alert rules use `config_id` and `config_title`. **Upcoming Changes:** -- Phase 6+: API versioning with backward compatibility guarantees +- API versioning with backward compatibility guarantees --- ## API Summary -### Implemented APIs (Phase 5) +### Implemented APIs (Version 6.0) - **Authentication API** - Login, logout, setup +- **Sites API** - Site definitions with IPs, bulk import from CIDR/list, per-IP settings +- **Configs API** - Database-based configurations referencing sites - **Scans API** - Full CRUD, status polling, comparison -- **Configs API** - File management, CIDR generation, YAML upload - **Schedules API** - CRUD operations, manual triggering, APScheduler integration - **Stats API** - Trends, summaries, historical data - **Settings API** - Application configuration, password management @@ -3048,8 +3310,8 @@ API versioning will be implemented in future phases. For now, the API is conside - **Webhooks API** - Webhook management, delivery tracking, authentication support, retry logic ### Endpoint Count -- Total endpoints: 67+ -- Authenticated endpoints: 62+ +- Total endpoints: 80+ +- Authenticated endpoints: 75+ - Public endpoints: 5 (login, setup, health checks) --- @@ -3062,6 +3324,6 @@ For issues, questions, or feature requests: --- -**Last Updated:** 2025-11-18 -**Phase:** 5 - Alerts Management & Custom Webhook Templates -**Next Update:** Phase 6 - Future Enhancements +**Last Updated:** 2025-11-19 +**Version:** 6.0 - Database-Based Configuration with Sites API +**Previous:** Phase 5 - Alerts Management & Custom Webhook Templates