{
 "openapi": "3.1.0",
 "info": {
  "title": "hw-cloud",
  "description": "The hw-cloud cloud: account registers and their state, alerts, events and metrics, commands to registers and receipts through the cloud.\n\nKey — the `X-Api-Key: hwk_…` header (hw-connector.ru cabinet → Cloud). A register of another account — `404`.\nErrors — `application/problem+json` with a machine code in the `code` field. Lists — `limit` and `offset`, total — in the `X-Total-Count` header.\nThe agent API on a register through the cloud — `/agent/api/v1/**` (the same API as on `http://localhost:7790`).",
  "version": "v1"
 },
 "servers": [
  {
   "url": "https://cloud.hw-connector.ru",
   "description": "hw-connector cloud"
  }
 ],
 "security": [
  {
   "apiKey": []
  }
 ],
 "paths": {
  "/api/v1/receipts": {
   "get": {
    "tags": [
     "Receipts"
    ],
    "summary": "Recent receipts",
    "description": "Newest first; deviceId — only this register, idempotencyKey — find a receipt by your key",
    "operationId": "list",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "idempotencyKey",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deviceId",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 50
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/ReceiptView"
         }
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "Receipts"
    ],
    "summary": "Print a receipt on an account register",
    "description": "A receipt — as in the agent API (POST /api/v1/registers/{n}/receipts). New — 202, the same key — 200 with the same receipt, the same key with another receipt — 409. Register offline — the receipt waits in the queue up to cloud.receipts.ttl-hours; Prefer: wait=N — wait for the result up to 60 s. Trial plan over the limit — 402",
    "operationId": "create",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Prefer",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReceiptRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "$ref": "#/components/schemas/ReceiptView"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/devices/{id}/commands": {
   "post": {
    "tags": [
     "Commands"
    ],
    "summary": "Command to a register (envelope)",
    "description": "A request to the agent API in the body {method, path, body, idempotencyKey}; the agent response as is. The same without an envelope, with files and headers — the /agent/api/v1/** proxy. Offline — 503, no answer — 504 (a retry with the same idempotencyKey never runs the operation twice), disabled — 403 DEVICE_DISABLED",
    "operationId": "command",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CommandRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/devices/{id}": {
   "get": {
    "tags": [
     "Registers"
    ],
    "summary": "Register card",
    "description": "The register, whether it is online, latest metric values for 7 days, open alerts and recent events",
    "operationId": "device",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     },
     {
      "name": "events",
      "in": "query",
      "description": "How many recent events (1–500)",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 20
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "$ref": "#/components/schemas/DeviceDetail"
        }
       }
      }
     }
    }
   },
   "patch": {
    "tags": [
     "Registers"
    ],
    "summary": "Rename or disable a register",
    "description": "label — your own name (the agent does not overwrite it), disabled — switch off: commands and the proxy answer 403 DEVICE_DISABLED, receipts are not sent to it",
    "operationId": "update",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DevicePatch"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "$ref": "#/components/schemas/DeviceView"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/summary": {
   "get": {
    "tags": [
     "Monitoring"
    ],
    "summary": "Account summary",
    "description": "How many registers are online, agent versions, open alerts by code, agent requests in the last day — the fleet state in one request",
    "operationId": "summary",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "$ref": "#/components/schemas/Summary"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/requests": {
   "get": {
    "tags": [
     "Commands"
    ],
    "summary": "Agent request log",
    "description": "Requests through the /agent/api/v1/** proxy and POST /api/v1/devices/{id}/commands: register, method, path without the query string, response status, proxy error, ms. Bodies are not stored; kept 30 days",
    "operationId": "requests",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deviceId",
      "in": "query",
      "description": "Only this register",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     },
     {
      "name": "failed",
      "in": "query",
      "description": "Only failed: proxy errors and 4xx/5xx responses",
      "required": false,
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 100
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 0
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/LogEntry"
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/receipts/{id}": {
   "get": {
    "tags": [
     "Receipts"
    ],
    "summary": "Receipt",
    "description": "status: QUEUED, SENDING, DONE, FAILED, UNKNOWN, EXPIRED; result — FD number, fiscal sign, receipt link for the customer",
    "operationId": "get",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "$ref": "#/components/schemas/ReceiptView"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/receipts/stats": {
   "get": {
    "tags": [
     "Receipts"
    ],
    "summary": "Receipt accounting by point for a month",
    "description": "How many receipts and for what sum each register printed, the plan and the trial limit; month=2026-11",
    "operationId": "stats",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "month",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "$ref": "#/components/schemas/Stats"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/metrics/latest": {
   "get": {
    "tags": [
     "Monitoring"
    ],
    "summary": "Latest metric value per register",
    "description": "For example name=fn.days_left — days left on the fiscal drive of each account register; the value for the last 7 days, one per register and label set",
    "operationId": "latest",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "in": "query",
      "description": "Metric name: fn.days_left, ofd.not_sent, shift.open, register.ok, agent.up…",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deviceId",
      "in": "query",
      "description": "Only this register",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/LatestMetric"
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/events": {
   "get": {
    "tags": [
     "Monitoring"
    ],
    "summary": "Register events",
    "description": "Failed operations, printers, power, register not answering — newest first; total — in X-Total-Count",
    "operationId": "events",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deviceId",
      "in": "query",
      "description": "Only this register",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     },
     {
      "name": "type",
      "in": "query",
      "description": "Event type: operation.failed, printer, power, register.unavailable…",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "since",
      "in": "query",
      "description": "Not earlier than this time (ISO 8601)",
      "required": false,
      "schema": {
       "type": "string",
       "format": "date-time"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 100
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 0
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/EventView"
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/devices": {
   "get": {
    "tags": [
     "Registers"
    ],
    "summary": "Account registers",
    "description": "Agent version, online now, last seen, open alerts. Filters — online, q (name, installation id), pages — limit/offset, total — in X-Total-Count",
    "operationId": "list_1",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "online",
      "in": "query",
      "description": "true — only online, false — only offline",
      "required": false,
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "q",
      "in": "query",
      "description": "Part of the name, own name or installation id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 1000
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 0
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/DeviceView"
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/devices/{id}/metrics": {
   "get": {
    "tags": [
     "Registers"
    ],
    "summary": "Register metrics",
    "description": "Values for the whole retention period, newest first; name — only this metric",
    "operationId": "metrics",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     },
     {
      "name": "name",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int32",
       "default": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/MetricPoint"
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/alerts": {
   "get": {
    "tags": [
     "Monitoring"
    ],
    "summary": "Register alerts",
    "description": "FN_EXPIRING (fiscal drive ≤ 30 days, ≤ 7 — critical), OFD_BACKLOG, SHIFT_EXPIRED, REGISTER_UNAVAILABLE, DEVICE_OFFLINE. They open and close by themselves; open=false — closed ones too",
    "operationId": "alerts",
    "parameters": [
     {
      "name": "X-Api-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "open",
      "in": "query",
      "required": false,
      "schema": {
       "type": "boolean",
       "default": true
      }
     },
     {
      "name": "deviceId",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "format": "int64"
      }
     },
     {
      "name": "code",
      "in": "query",
      "description": "Only this code: FN_EXPIRING, OFD_BACKLOG…",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "severity",
      "in": "query",
      "description": "WARNING or CRITICAL",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "*/*": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/Alert"
         }
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "ReceiptRequest": {
    "type": "object",
    "properties": {
     "idempotencyKey": {
      "type": "string",
      "maxLength": 100,
      "minLength": 0
     },
     "deviceId": {
      "type": "integer",
      "format": "int64"
     },
     "register": {
      "type": "integer",
      "format": "int32",
      "maximum": 99,
      "minimum": 1
     },
     "receipt": {
      "type": "object"
     },
     "callbackUrl": {
      "type": "string",
      "maxLength": 500,
      "minLength": 0,
      "pattern": "https?://.+"
     }
    },
    "required": [
     "receipt"
    ]
   },
   "Error": {
    "type": "object",
    "properties": {
     "code": {
      "type": "string"
     },
     "message": {
      "type": "string"
     }
    }
   },
   "ReceiptView": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer",
      "format": "int64"
     },
     "idempotencyKey": {
      "type": "string"
     },
     "status": {
      "type": "string"
     },
     "deviceId": {
      "type": "integer",
      "format": "int64"
     },
     "register": {
      "type": "integer",
      "format": "int32"
     },
     "total": {
      "type": "integer",
      "format": "int64"
     },
     "attempts": {
      "type": "integer",
      "format": "int32"
     },
     "createdAt": {
      "type": "string",
      "format": "date-time"
     },
     "doneAt": {
      "type": "string",
      "format": "date-time"
     },
     "result": {
      "$ref": "#/components/schemas/Result"
     },
     "error": {
      "$ref": "#/components/schemas/Error"
     }
    }
   },
   "Result": {
    "type": "object",
    "properties": {
     "fdNumber": {
      "type": "integer",
      "format": "int64"
     },
     "fiscalSign": {
      "type": "string"
     },
     "shiftNumber": {
      "type": "integer",
      "format": "int32"
     },
     "receiptNumber": {
      "type": "integer",
      "format": "int32"
     },
     "fnNumber": {
      "type": "string"
     },
     "registrationNumber": {
      "type": "string"
     },
     "dateTime": {
      "type": "string"
     },
     "qrCode": {
      "type": "string"
     },
     "fnsUrl": {
      "type": "string"
     },
     "link": {
      "type": "string"
     }
    }
   },
   "CommandRequest": {
    "type": "object",
    "properties": {
     "method": {
      "type": "string",
      "pattern": "GET|POST|PUT|DELETE|PATCH"
     },
     "path": {
      "type": "string",
      "minLength": 1,
      "pattern": "/api/v1/.*"
     },
     "body": {},
     "idempotencyKey": {
      "type": "string"
     }
    },
    "required": [
     "path"
    ]
   },
   "DevicePatch": {
    "type": "object",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 200,
      "minLength": 0
     },
     "disabled": {
      "type": "boolean"
     }
    }
   },
   "DeviceView": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer",
      "format": "int64"
     },
     "machineId": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "agentVersion": {
      "type": "string"
     },
     "os": {
      "type": "string"
     },
     "lastSeenAt": {
      "type": "string",
      "format": "date-time"
     },
     "online": {
      "type": "boolean"
     },
     "label": {
      "type": "string"
     },
     "disabled": {
      "type": "boolean"
     },
     "openAlerts": {
      "type": "integer",
      "format": "int32"
     }
    }
   },
   "Summary": {
    "type": "object",
    "properties": {
     "devices": {
      "type": "object",
      "additionalProperties": {
       "type": "integer",
       "format": "int64"
      }
     },
     "agentVersions": {
      "type": "object",
      "additionalProperties": {
       "type": "integer",
       "format": "int64"
      }
     },
     "alerts": {
      "type": "object",
      "additionalProperties": {}
     },
     "requests": {
      "type": "object",
      "additionalProperties": {
       "type": "integer",
       "format": "int64"
      }
     }
    }
   },
   "LogEntry": {
    "type": "object",
    "properties": {
     "at": {
      "type": "string",
      "format": "date-time"
     },
     "deviceId": {
      "type": "integer",
      "format": "int64"
     },
     "method": {
      "type": "string"
     },
     "path": {
      "type": "string"
     },
     "status": {
      "type": "integer",
      "format": "int32"
     },
     "error": {
      "type": "string"
     },
     "ms": {
      "type": "integer",
      "format": "int32"
     },
     "source": {
      "type": "string"
     }
    }
   },
   "PointStats": {
    "type": "object",
    "properties": {
     "deviceId": {
      "type": "integer",
      "format": "int64"
     },
     "name": {
      "type": "string"
     },
     "done": {
      "type": "integer",
      "format": "int64"
     },
     "failed": {
      "type": "integer",
      "format": "int64"
     },
     "pending": {
      "type": "integer",
      "format": "int64"
     },
     "total": {
      "type": "integer",
      "format": "int64"
     }
    }
   },
   "Stats": {
    "type": "object",
    "properties": {
     "month": {
      "type": "string"
     },
     "plan": {
      "type": "string"
     },
     "paidPoints": {
      "type": "integer",
      "format": "int32"
     },
     "trialMonthly": {
      "type": "integer",
      "format": "int32"
     },
     "trialUsed": {
      "type": "integer",
      "format": "int64"
     },
     "points": {
      "type": "integer",
      "format": "int64"
     },
     "done": {
      "type": "integer",
      "format": "int64"
     },
     "failed": {
      "type": "integer",
      "format": "int64"
     },
     "total": {
      "type": "integer",
      "format": "int64"
     },
     "byPoint": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/PointStats"
      }
     }
    }
   },
   "LatestMetric": {
    "type": "object",
    "properties": {
     "deviceId": {
      "type": "integer",
      "format": "int64"
     },
     "at": {
      "type": "string",
      "format": "date-time"
     },
     "name": {
      "type": "string"
     },
     "value": {
      "type": "number",
      "format": "double"
     },
     "labels": {
      "type": "string"
     }
    }
   },
   "EventView": {
    "type": "object",
    "properties": {
     "at": {
      "type": "string",
      "format": "date-time"
     },
     "type": {
      "type": "string"
     },
     "payload": {
      "type": "object"
     },
     "deviceId": {
      "type": "integer",
      "format": "int64"
     }
    }
   },
   "Alert": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer",
      "format": "int64"
     },
     "deviceId": {
      "type": "integer",
      "format": "int64"
     },
     "code": {
      "type": "string"
     },
     "subject": {
      "type": "string"
     },
     "severity": {
      "type": "string"
     },
     "message": {
      "type": "string"
     },
     "value": {
      "type": "number",
      "format": "double"
     },
     "openedAt": {
      "type": "string",
      "format": "date-time"
     },
     "updatedAt": {
      "type": "string",
      "format": "date-time"
     },
     "closedAt": {
      "type": "string",
      "format": "date-time"
     }
    }
   },
   "DeviceDetail": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer",
      "format": "int64"
     },
     "name": {
      "type": "string"
     },
     "machineId": {
      "type": "string"
     },
     "agentVersion": {
      "type": "string"
     },
     "os": {
      "type": "string"
     },
     "createdAt": {
      "type": "string",
      "format": "date-time"
     },
     "lastSeenAt": {
      "type": "string",
      "format": "date-time"
     },
     "online": {
      "type": "boolean"
     },
     "metrics": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/MetricPoint"
      }
     },
     "alerts": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Alert"
      }
     },
     "events": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/EventView"
      }
     },
     "label": {
      "type": "string"
     },
     "disabled": {
      "type": "boolean"
     }
    }
   },
   "MetricPoint": {
    "type": "object",
    "properties": {
     "at": {
      "type": "string",
      "format": "date-time"
     },
     "name": {
      "type": "string"
     },
     "value": {
      "type": "number",
      "format": "double"
     },
     "labels": {
      "type": "string"
     }
    }
   }
  },
  "securitySchemes": {
   "apiKey": {
    "type": "apiKey",
    "name": "X-Api-Key",
    "in": "header"
   }
  }
 }
}