Files
andreicscs-HoneyWire/Docs/API.md
T

14 KiB

HoneyWire Hub — API Reference

All Hub routes are prefixed with /api/v1 unless otherwise noted.

Authentication

HoneyWire uses two separate authentication methods.

Dashboard (UI) routes

Dashboard endpoints are protected by an HTTP-only session cookie named hw_auth. The cookie is issued by POST /login and is valid for 30 days.

Agent (sensor) routes

Sensor/agent endpoints are authenticated with a node API key using the Authorization header:

Authorization: Bearer <HW_NODE_KEY>

Public Endpoints

GET /api/v1/version

Returns the running Hub version.

Response:

{ "version": "2.0.0" }

POST /login

Authenticates a dashboard user and sets the hw_auth cookie.

Request:

{ "password": "your_password" }

Response: 200 OK with cookie on success.

Errors: 401 Unauthorized for invalid credentials, 429 Too Many Requests after repeated failures.

POST /logout

Invalidates the current dashboard session and redirects the client to /.

Response: 303 See Other

GET /api/v1/setup/status

Returns whether the Hub requires initial setup. When HW_DASHBOARD_PASSWORD is set, setup is considered locked and this endpoint returns requires_setup: false.

Response:

{ "requiresSetup": true }

POST /api/v1/setup

Completes first-time hub setup and stores the hashed admin password, hub endpoint, and hub API key. If HW_DASHBOARD_PASSWORD is set, setup is blocked.

Request:

{
  "password": "super_secure_password123",
  "hubEndpoint": "https://honeywire.my-domain.com",
  "hubKey": "hw_sk_randomstring"
}

Response: 200 OK

Errors: 403 Forbidden if setup is locked or already complete.

These endpoints require a valid hw_auth session cookie.

GET /api/v1/ws

Upgrades the connection to a WebSocket for realtime dashboard updates.

All messages use the envelope:

{ "type": "<MESSAGE_TYPE>", "payload": { ... } }

Common message types:

  • NEW_EVENT — a sensor reported an event.
  • NEW_SENSOR — a new sensor was discovered.
  • SENSOR_HEARTBEAT — a sensor heartbeat was received.
  • NODE_SYNCED — a node reported that pending config was applied.
  • SILENCE_SENSOR — a sensor silence state changed.
  • SYNC_CHARTS — instructs UIs to refresh chart data.

GET /api/v1/manifests

Fetches the sensor manifest catalog from RegistryURL or the default public manifest registry.

GET /api/v1/manifests/{sensorId}/versions

Fetches a specific historical version schema of a sensor manifest from the registry.

Query parameters:

  • version — The exact version string to fetch (e.g. 2.0.6).

POST /api/v1/compose/generate

Generates a docker-compose.yml preview from the selected sensor manifests and UI-provided environment values.

Request:

{
  "hubEndpoint": "https://honeywire.my-domain.com",
  "hubKey": "hub_key_abc",
  "sensors": [
    {
      "sensorId": "alpha-node-01",
      "envValues": {
        "HW_SEVERITY": "medium"
      },
      "manifest": { ... }
    }
  ]
}

Response: application/x-yaml compose payload.

Nodes and Sensors

POST /api/v1/nodes

Creates a new node entry and returns the generated node credentials.

Request:

{
  "alias": "production-db-node",
  "tags": ["database", "prod"]
}

Response:

{
  "api_key": "hw_key_abcd1234...",
  "alias": "production-db-node"
}

GET /api/v1/nodes

Returns all registered nodes and their installed sensors. Each node includes current status, heartbeat metadata, and pending config state.

Response:

[
  {
    "nodeId": "node-alpha",
    "alias": "Production Web Server",
    "activeRevision": "rev_e4f2a1",
    "desiredRevision": "rev_b7c9d0",
    "hasPendingConfig": true,
    "hasUpdateAvailable": true,
    "status": "online",
    "installedSensors": [
      {
        "sensorId": "hw-tcp-tarpit",
        "customName": "SSH Decoy",
        "updateAvailable": true
      }
    ]
  }
]

GET /api/v1/nodes/{nodeId}

Returns details for a single node, including installed sensors and per-sensor event counts.

PATCH /api/v1/nodes/{nodeId}

Updates a node's alias, tags, public IP, or private IP.

Request:

{
  "alias": "prod-db-node",
  "tags": ["database","primary"],
  "publicIp": "198.51.100.12",
  "privateIp": "10.0.0.12"
}

POST /api/v1/nodes/{nodeId}/upgrade

Triggers a fleet-wide sync command over WebSockets to force the node to pull the newest compose definitions and automatically pull the latest manifest versions for all of its installed sensors.

DELETE /api/v1/nodes/{nodeId}

Deletes a node and cascades to remove its sensors, event history, and heartbeat records.

POST /api/v1/nodes/{nodeId}/sensors

Adds a sensor to a node and flags the node as pending configuration sync.

Request:

{
  "sensorId": "hw-tcp-tarpit",
  "customName": "TCP Tarpit",
  "configValues": {
    "HW_SEVERITY": "high"
  }
}

PUT /api/v1/nodes/{nodeId}/sensors/{sensorId}

Updates a sensor's custom name and config values and marks the parent node pending sync.

DELETE /api/v1/nodes/{nodeId}/sensors/{sensorId}

Removes a sensor from the node and marks the node pending sync.

POST /api/v1/nodes/{nodeId}/sensors/{sensorId}/upgrade

Upgrades a specific sensor to the latest available manifest version listed in the registry, and marks the node pending sync.

PATCH /api/v1/nodes/{nodeId}/sensors/{sensorId}/silence

Toggles a sensor's silence state. Silenced sensors still log events but suppress push notifications.

Request:

{ "isSilenced": true }

Response:

{
  "status": "success",
  "sensorId": "hw-tcp-tarpit",
  "isSilenced": true
}

Configuration and System Settings

GET /api/v1/config

Returns runtime configuration loaded from SQLite.

Response Schema:

Field Type Description
hubEndpoint string The fully qualified URL of the Hub (e.g., https://hub.example.com).
autoArchiveDays integer Days before active events are moved to the archive. 0 = Keep forever.
autoPurgeDays integer Days before archived events are permanently deleted. 0 = Keep forever.
webhookType string The active push notification provider (ntfy, gotify, discord, slack, none).
webhookUrl string The target URL for the selected webhook provider.
webhookEvents string[] Array of severity levels that trigger a notification (e.g., ["critical", "high"]).
siemAddress string Address for RFC5424 syslog forwarding (e.g., 10.0.0.50:514). Empty if disabled.
siemProtocol string Protocol for SIEM forwarding (tcp, udp).

Response:

{
  "hubEndpoint": "https://honeywire.my-domain.com",
  "autoArchiveDays": 90,
  "autoPurgeDays": 180,
  "webhookType": "none",
  "webhookUrl": "",
  "webhookEvents": [],
  "siemAddress": "",
  "siemProtocol": "tcp"
}

PATCH /api/v1/config

Updates runtime settings. Only supported fields are applied. This endpoint also hot-reloads webhook and SIEM configuration.

Accepted Fields:

  • hubEndpoint
  • autoArchiveDays
  • autoPurgeDays
  • webhookType (ntfy, gotify, discord, slack, none)
  • webhookUrl
  • webhookEvents
  • siemAddress
  • siemProtocol (tcp, udp)

Request example:

{
  "autoArchiveDays": 14,
  "webhookType": "discord",
  "webhookUrl": "https://discord.com/api/webhooks/...",
  "webhookEvents": ["critical", "high"]
}

GET /api/v1/system/state

Returns whether the Hub is armed.

Response:

{ "isArmed": true }

PATCH /api/v1/system/state

Sets the armed/disarmed state.

Request:

{ "isArmed": false }

PATCH /api/v1/system/password

Changes the dashboard admin password. When HW_DASHBOARD_PASSWORD is set, this operation is forbidden.

Request:

{
  "currentPassword": "oldPassword",
  "newPassword": "newPassword"
}

POST /api/v1/system/reset

Performs a full factory reset of the runtime database, clearing events, sensors, heartbeats, and config. Requires the current admin password.

Request:

{ "password": "your_master_password" }

Response: 200 OK

Fleet and Events

GET /api/v1/events/unread

Returns the count of active, unread events.

Response:

{ "count": 12 }

GET /api/v1/events

Returns a list of events, newest first.

Query parameters:

  • archivedtrue or false (default: false)
  • nodeId — filter by node ID
  • sensorId — filter by sensor ID

PATCH /api/v1/events/read

Marks all active events as read.

PATCH /api/v1/events/{eventId}/read

Marks a single event as read.

PATCH /api/v1/events/{eventId}/archive

Archives a single event and marks it as read.

PATCH /api/v1/events/archive-all

Archives all active events.

DELETE /api/v1/events

Deletes all events permanently.

Query parameters:

  • dryrun=true — return the count of deletable events without deleting them.

Response (dryrun):

{
  "status": "success",
  "dryrun": true,
  "would_delete": 4512
}

Response:

{ "status": "success", "dryrun": false }

GET /api/v1/events/severity

Returns severity distribution analytics for the fleet.

Query parameters:

  • timeframe — timeframe filter (e.g. alltime, 24H) (default: alltime)
  • node — filter by node ID (optional)
  • sensor — filter by sensor ID (optional)
  • viewingArchivetrue, 1, false, or 0 (default: false)

Example Response:

{
  "timeframe": "24H",
  "total": 80,
  "critical": 5,
  "high": 12,
  "medium": 25,
  "low": 8,
  "info": 30
}

GET /api/v1/events/velocity

Returns time-bucketed velocity analytics for the fleet.

Query parameters:

  • timeframe — timeframe filter (1H, 24H, 7D, 30D) (default: 24H)
  • nodeId — filter by node ID (optional)
  • sensorId — filter by sensor ID (optional)
  • archived — include archived events (true or false) (default: false)

Example Response:

{
  "timeframe": "24H", 
  "bucketSizeMs": 3600000,
  "generatedAt": 1716552000000,
  "bucketTimestamps": [1716465600000, 1716469200000],
  "labels": ["-23h", "-22h", "Now"],
  "exactTimes": ["May 23, 08:00 AM", "May 23, 09:00 AM"],
  "series": {
    "critical": [0, 1, 0],
    "high": [2, 0, 5],
    "medium": [0, 0, 0],
    "low": [0, 0, 0],
    "info": [1, 3, 2]
  },
  "recentEventCount": 14
}

Uptime and Health

GET /api/v1/uptime

Returns uptime blocks for fleet health charts.

Query parameters:

  • timeframe1H, 24H, 7D, 30D (default: 24H)

Example Response:

{
  "timeframe": "24H", 
  "generatedAt": "2024-05-24T10:00:00Z",
  "summary": {
    "overallUptime": 98.5
  },
  "groups": [
    {
      "nodeId": "node-alpha",
      "nodeAlias": "Production Web Server",
      "worstStatus": "degraded",
      "sensors": [
        {
          "sensorId": "hw-tcp-tarpit",
          "displayName": "TCP Tarpit",
          "status": "up",
          "isSilenced": false,
          "blocks": [
            { "status": "up", "label": "Online", "timeLabel": "-23h" },
            { "status": "up", "label": "Online", "timeLabel": "-22h" },
            { "status": "up", "label": "Online", "timeLabel": "Current" }
          ]
        },
        {
          "sensorId": "hw-file-canary",
          "displayName": "File Integrity Monitor",
          "status": "degraded",
          "isSilenced": false,
          "blocks": [
            { "status": "up", "label": "Online", "timeLabel": "-23h" },
            { "status": "degraded", "label": "Degraded (50/60 pings)", "timeLabel": "-22h" },
            { "status": "up", "label": "Online", "timeLabel": "Current" }
          ]
        }
      ]
    },
    {
      "nodeId": "node-beta",
      "nodeAlias": "Dev Database",
      "worstStatus": "down",
      "sensors": [
        {
          "sensorId": "hw-network-scan",
          "displayName": "Network Scan Detector",
          "status": "down",
          "isSilenced": true,
          "blocks": [
            { "status": "down", "label": "Offline", "timeLabel": "-23h" },
            { "status": "down", "label": "Offline", "timeLabel": "-22h" },
            { "status": "down", "label": "Offline", "timeLabel": "Current" }
          ]
        }
      ]
    }
  ]
}

Node Compose

GET /api/v1/nodes/compose

Returns a generated docker-compose.yml for a node based on the node's current installed sensors.

Authentication: Authorization: Bearer <HW_NODE_KEY>

This endpoint is read-only for node deployment: it returns the current or requested HW_CONFIG_REV without marking the node as synced. The node is marked synced only when its heartbeat reports the expected revision.

Agent Endpoints

These endpoints are used by sensor agents and require the node API key bearer token.

POST /api/v1/heartbeat

Reports a sensor heartbeat and updates runtime metadata.

Request:

{
  "sensorId": "alpha-node-01",
  "metadata": {
    "agent_version": "1.0.0",
    "contract_version": "1.0",
    "sensor_type": "tarpit",
    "HW_CONFIG_REV": "rev_abc123"
  }
}

Response:

{ "status": "alive" }

POST /api/v1/event

Reports an intrusion event to the Hub.

Request:

📖 View the Universal Event Standard Contract

Severity values: info, low, medium, high, critical

Response:

{ "status": "success" }

Errors:

  • 400 Bad Request for invalid JSON or missing required fields.
  • 426 Upgrade Required if the sensor major version does not match the Hub. Required` if the sensor major version does not match the Hub.