{
  "openapi": "3.0.3",
  "info": {
    "title": "vNOC42 Status API",
    "version": "1.0.0",
    "description": "Read-only API for the status of the monitored objects of one vNOC42 account. Every key belongs to exactly one account, is bound to an IP allowlist and expires after at most 12 months. Keys are created by the account administrator under Account - API keys. All times are UTC (ISO 8601). Status codes: -1 deactivated, 0 neutral, 1 ok, 2 warning, 3 alarm, 4 critical. Rate limit: 120 requests per minute and key. Authentication errors always answer 401 without details; 429 means slow down (see Retry-After).",
    "contact": { "name": "Keppler IT-Systems GmbH", "email": "info@keppler.de" }
  },
  "servers": [ { "url": "https://noc26.virtual42.com/api/v1" } ],
  "security": [ { "bearer": [] } ],
  "components": {
    "securitySchemes": {
      "bearer": { "type": "http", "scheme": "bearer", "description": "Authorization: Bearer vnoc_<id>_<secret>" }
    },
    "schemas": {
      "Level": {
        "type": "object",
        "properties": {
          "code": { "type": "integer", "minimum": -1, "maximum": 4 },
          "name": { "type": "string", "enum": ["deactivated", "neutral", "ok", "warning", "alarm", "critical"] },
          "label": { "type": "string", "description": "German display label" }
        }
      },
      "Object": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "type": { "type": "string" },
          "status": { "$ref": "#/components/schemas/Level" },
          "last_seen": { "type": "string", "format": "date-time", "nullable": true, "description": "Latest report of any sensor bound to the object" },
          "open_alerts": { "type": "integer" }
        }
      },
      "Alert": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "label": { "type": "string" },
          "parameter": { "type": "string" },
          "condition": { "type": "object", "properties": { "operator": { "type": "string" }, "threshold": { "type": "string" }, "unit": { "type": "string", "nullable": true } } },
          "level": { "$ref": "#/components/schemas/Level" },
          "since": { "type": "string", "format": "date-time", "nullable": true },
          "muted_until": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "time": { "type": "string", "format": "date-time" },
          "type": { "type": "string", "enum": ["first_report", "value_change", "alarm", "all_clear"] },
          "level": { "$ref": "#/components/schemas/Level" },
          "object_id": { "type": "integer", "nullable": true },
          "object_name": { "type": "string", "nullable": true },
          "parameter": { "type": "string" },
          "value": { "type": "string", "nullable": true },
          "previous": { "type": "string", "nullable": true },
          "alert_label": { "type": "string", "nullable": true }
        }
      },
      "Error": {
        "type": "object",
        "properties": { "error": { "type": "string" }, "detail": { "type": "string" } }
      }
    },
    "responses": {
      "Unauthorized": { "description": "Missing, invalid, expired or revoked key, or request from an address outside the allowlist", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Forbidden": { "description": "The key lacks the required scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "TooMany": { "description": "Rate limit exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  },
  "paths": {
    "/summary": {
      "get": {
        "summary": "Overall status of the account (scope status:read)",
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": {
            "api_version": { "type": "integer" },
            "generated_at": { "type": "string", "format": "date-time" },
            "status": { "$ref": "#/components/schemas/Level" },
            "objects": { "type": "integer" },
            "by_status": { "type": "object", "additionalProperties": { "type": "integer" } },
            "open_alerts": { "type": "integer" },
            "muted_alerts": { "type": "integer" },
            "oldest_report": { "type": "string", "format": "date-time", "nullable": true }
          } } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/TooMany" }
        }
      }
    },
    "/objects": {
      "get": {
        "summary": "Monitored objects with status (scope objects:read)",
        "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma separated codes or names, e.g. 2,3,4 or warning,alarm" } ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": {
            "api_version": { "type": "integer" },
            "generated_at": { "type": "string", "format": "date-time" },
            "objects": { "type": "array", "items": { "$ref": "#/components/schemas/Object" } }
          } } } } },
          "400": { "description": "Invalid filter" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/TooMany" }
        }
      }
    },
    "/objects/{id}": {
      "get": {
        "summary": "One object with its firing alerts (scope objects:read)",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": {
            "api_version": { "type": "integer" },
            "generated_at": { "type": "string", "format": "date-time" },
            "object": { "allOf": [ { "$ref": "#/components/schemas/Object" }, { "type": "object", "properties": { "alerts": { "type": "array", "items": { "$ref": "#/components/schemas/Alert" } } } } ] }
          } } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "description": "No such object for this key" },
          "429": { "$ref": "#/components/responses/TooMany" }
        }
      }
    },
    "/events": {
      "get": {
        "summary": "Event journal, oldest first (scope events:read)",
        "parameters": [
          { "name": "since", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Default: 24 hours ago; at most 30 days back" },
          { "name": "after_id", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Continue after this event id (use the last id of the previous page)" },
          { "name": "types", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma separated: first_report, value_change, alarm, all_clear" },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 500 } }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": {
            "api_version": { "type": "integer" },
            "generated_at": { "type": "string", "format": "date-time" },
            "since": { "type": "string", "format": "date-time" },
            "events": { "type": "array", "items": { "$ref": "#/components/schemas/Event" } },
            "has_more": { "type": "boolean" }
          } } } } },
          "400": { "description": "Invalid parameter" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/TooMany" }
        }
      }
    }
  }
}
