{
 "openapi": "3.1.0",
 "info": {
  "title": "uclogserver API",
  "version": "1.0.0",
  "description": "Firmware distribution, device registry and log storage. Human documentation: /docs. Scopes required per operation are listed in `x-required-scope`."
 },
 "servers": [
  {
   "url": "/"
  }
 ],
 "tags": [
  {
   "name": "Firmware"
  },
  {
   "name": "Log data"
  },
  {
   "name": "Devices"
  },
  {
   "name": "Tags"
  },
  {
   "name": "Downloads"
  },
  {
   "name": "Tokens"
  },
  {
   "name": "Members"
  },
  {
   "name": "Stats"
  },
  {
   "name": "Auth"
  },
  {
   "name": "Health"
  },
  {
   "name": "Admin"
  }
 ],
 "paths": {
  "/healthz": {
   "get": {
    "tags": [
     "Health"
    ],
    "summary": "Liveness",
    "security": [],
    "responses": {
     "200": {
      "description": "Process alive",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string",
         "example": "ok\n"
        }
       }
      }
     }
    }
   }
  },
  "/readyz": {
   "get": {
    "tags": [
     "Health"
    ],
    "summary": "Readiness (database + object store)",
    "security": [],
    "responses": {
     "200": {
      "description": "Ready",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Ready"
        }
       }
      }
     },
     "503": {
      "description": "Not ready",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Ready"
        }
       }
      }
     }
    }
   }
  },
  "/status": {
   "get": {
    "tags": [
     "Health"
    ],
    "summary": "Service status document",
    "security": [],
    "responses": {
     "200": {
      "description": "Status (ok/degraded)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Status"
        }
       }
      }
     },
     "503": {
      "description": "Database down",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Status"
        }
       }
      }
     }
    }
   }
  },
  "/health/history": {
   "get": {
    "tags": [
     "Health"
    ],
    "summary": "Daily uptime history",
    "security": [],
    "parameters": [
     {
      "name": "days",
      "in": "query",
      "required": false,
      "description": "1\u2013400, default 90",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 400,
       "default": 90
      }
     }
    ],
    "responses": {
     "200": {
      "description": "History",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HealthHistory"
        }
       }
      }
     }
    }
   }
  },
  "/.well-known/jwks.json": {
   "get": {
    "tags": [
     "Auth"
    ],
    "summary": "Public JWT signing keys (JWK set)",
    "security": [],
    "responses": {
     "200": {
      "description": "JWK set",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "keys": {
           "type": "array",
           "items": {
            "type": "object"
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/metrics": {
   "get": {
    "tags": [
     "Health"
    ],
    "summary": "Prometheus metrics",
    "description": "`Authorization: Bearer <METRICS_TOKEN>` or an admin credential.",
    "security": [
     {
      "metricsToken": []
     },
     {
      "bearer": []
     }
    ],
    "responses": {
     "200": {
      "description": "Prometheus text",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     }
    }
   }
  },
  "/openapi.json": {
   "get": {
    "tags": [
     "Health"
    ],
    "summary": "This OpenAPI document",
    "security": [],
    "responses": {
     "200": {
      "description": "OpenAPI 3.1",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  },
  "/dl/{token}": {
   "get": {
    "tags": [
     "Downloads"
    ],
    "summary": "Use a download link",
    "security": [],
    "description": "Validates the signed token (5-minute expiry), counts the download, then redirects (302) to a 60-second pre-signed object-store URL or streams the file (200).",
    "parameters": [
     {
      "name": "token",
      "in": "path",
      "required": true,
      "description": "Signed download token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "302": {
      "description": "Redirect to the object store",
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "200": {
      "description": "File (proxy mode)",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "410": {
      "$ref": "#/components/responses/P410"
     },
     "429": {
      "$ref": "#/components/responses/P429"
     }
    }
   },
   "head": {
    "tags": [
     "Downloads"
    ],
    "summary": "Use a download link",
    "security": [],
    "description": "Validates the signed token (5-minute expiry), counts the download, then redirects (302) to a 60-second pre-signed object-store URL or streams the file (200).",
    "parameters": [
     {
      "name": "token",
      "in": "path",
      "required": true,
      "description": "Signed download token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "302": {
      "description": "Redirect to the object store",
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "200": {
      "description": "File (proxy mode)",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "410": {
      "$ref": "#/components/responses/P410"
     },
     "429": {
      "$ref": "#/components/responses/P429"
     }
    }
   }
  },
  "/firmware/{domain}/{hw_name}/{hw_version}/{fw_name}/{fw_version}": {
   "get": {
    "tags": [
     "Firmware"
    ],
    "summary": "Update check",
    "security": [],
    "description": "Newer builds than `fw_version`: general releases, plus (when the device's HW id is given as the last path segment) builds sharing a tag with that device (an unknown or withdrawn device counts as no HW id). Errors are text/plain unless `Accept: application/json` (then application/problem+json).",
    "parameters": [
     {
      "name": "domain",
      "in": "path",
      "required": true,
      "description": "Customer domain name, e.g. example.com",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_name",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_version",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_name",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_version",
      "in": "path",
      "required": true,
      "description": "Current full version, e.g. 1.6.0-10-g30d0049",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "in": "query",
      "required": false,
      "description": "AFI (default), `all`, or comma list of AFI/EFI/MFI",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "latest",
      "in": "query",
      "required": false,
      "description": "true: only the newest build",
      "schema": {
       "type": "boolean"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Update list (oldest newer build first)",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/CompatUpdateItem"
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/T400"
     },
     "404": {
      "$ref": "#/components/responses/T404"
     },
     "429": {
      "$ref": "#/components/responses/T429"
     }
    }
   }
  },
  "/firmware/{domain}/{hw_name}/{hw_version}/{fw_name}/{fw_version}/{hwid}": {
   "get": {
    "tags": [
     "Firmware"
    ],
    "summary": "Update check for a specific device (adds tag-matched builds)",
    "security": [],
    "description": "Newer builds than `fw_version`: general releases, plus (when the device's HW id is given as the last path segment) builds sharing a tag with that device (an unknown or withdrawn device counts as no HW id). Errors are text/plain unless `Accept: application/json` (then application/problem+json).",
    "parameters": [
     {
      "name": "domain",
      "in": "path",
      "required": true,
      "description": "Customer domain name, e.g. example.com",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_name",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_version",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_name",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_version",
      "in": "path",
      "required": true,
      "description": "Current full version, e.g. 1.6.0-10-g30d0049",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     },
     {
      "name": "type",
      "in": "query",
      "required": false,
      "description": "AFI (default), `all`, or comma list of AFI/EFI/MFI",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "latest",
      "in": "query",
      "required": false,
      "description": "true: only the newest build",
      "schema": {
       "type": "boolean"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Update list (oldest newer build first)",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/CompatUpdateItem"
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/T400"
     },
     "404": {
      "$ref": "#/components/responses/T404"
     },
     "429": {
      "$ref": "#/components/responses/T429"
     }
    }
   }
  },
  "/auth/login": {
   "post": {
    "tags": [
     "Auth"
    ],
    "summary": "Request a login code (invite only)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "email"
        ],
        "properties": {
         "email": {
          "type": "string",
          "format": "email"
         }
        }
       }
      }
     }
    },
    "responses": {
     "202": {
      "description": "Always accepted",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "sent": {
           "type": "boolean"
          },
          "detail": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "429": {
      "$ref": "#/components/responses/P429"
     }
    }
   }
  },
  "/auth/verify": {
   "post": {
    "tags": [
     "Auth"
    ],
    "summary": "Verify a login code and start a session",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "email",
         "code"
        ],
        "properties": {
         "email": {
          "type": "string"
         },
         "code": {
          "type": "string",
          "pattern": "^[0-9]{6}$"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Session started (Set-Cookie)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Me"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "429": {
      "$ref": "#/components/responses/P429"
     }
    }
   }
  },
  "/auth/me": {
   "get": {
    "tags": [
     "Auth"
    ],
    "summary": "Current identity",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "responses": {
     "200": {
      "description": "Identity",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Me"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     }
    }
   }
  },
  "/auth/refresh": {
   "post": {
    "tags": [
     "Auth"
    ],
    "summary": "Rotate the refresh cookie, issue a new access cookie",
    "security": [
     {
      "session": []
     }
    ],
    "parameters": [
     {
      "name": "X-CSRF-Token",
      "in": "header",
      "required": true,
      "description": "CSRF token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Refreshed",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/auth/switch": {
   "post": {
    "tags": [
     "Auth"
    ],
    "summary": "Switch the active customer",
    "security": [
     {
      "session": []
     }
    ],
    "parameters": [
     {
      "name": "X-CSRF-Token",
      "in": "header",
      "required": true,
      "description": "CSRF token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "domain"
        ],
        "properties": {
         "domain": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Switched",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Me"
        }
       }
      }
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/auth/logout": {
   "post": {
    "tags": [
     "Auth"
    ],
    "summary": "End the session",
    "security": [
     {
      "session": []
     }
    ],
    "parameters": [
     {
      "name": "X-CSRF-Token",
      "in": "header",
      "required": true,
      "description": "CSRF token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Logged out"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/auth/magic": {
   "get": {
    "tags": [
     "Auth"
    ],
    "summary": "Magic login link (GET shows a confirmation page, POST logs in)",
    "security": [],
    "parameters": [
     {
      "name": "c",
      "in": "query",
      "required": true,
      "description": "Challenge id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "t",
      "in": "query",
      "required": true,
      "description": "Link token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "HTML page"
     },
     "303": {
      "description": "Logged in; redirect to the console"
     }
    }
   },
   "post": {
    "tags": [
     "Auth"
    ],
    "summary": "Magic login link (GET shows a confirmation page, POST logs in)",
    "security": [],
    "parameters": [
     {
      "name": "c",
      "in": "query",
      "required": true,
      "description": "Challenge id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "t",
      "in": "query",
      "required": true,
      "description": "Link token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "HTML page"
     },
     "303": {
      "description": "Logged in; redirect to the console"
     }
    }
   }
  },
  "/firmware": {
   "put": {
    "tags": [
     "Firmware"
    ],
    "summary": "Upload firmware (what string complete)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:write",
    "description": "Content negotiation: replies `OK` and text/plain errors by default; send `Accept: application/json` for JSON (201 + Location for a new object) and problem+json errors.",
    "parameters": [
     {
      "name": "what_index",
      "in": "query",
      "required": false,
      "description": "Choose among several what strings",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "general_release",
      "in": "query",
      "required": false,
      "description": "Publish immediately",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "fw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_version",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_type",
      "in": "query",
      "required": false,
      "description": "AFI/EFI/MFI",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_version",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "build_date",
      "in": "query",
      "required": false,
      "description": "RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/FirmwareUpload"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Stored (new or identical re-upload). Body `OK`; with `Accept: application/json` the stored record (200 = identical re-upload).",
      "content": {
       "text/html": {
        "schema": {
         "type": "string",
         "example": "OK"
        }
       }
      }
     },
     "201": {
      "description": "Created (with Accept: application/json)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Firmware"
        }
       }
      },
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/T400"
     },
     "401": {
      "$ref": "#/components/responses/T401"
     },
     "403": {
      "$ref": "#/components/responses/T403"
     },
     "404": {
      "$ref": "#/components/responses/T404"
     },
     "409": {
      "$ref": "#/components/responses/T409"
     },
     "413": {
      "$ref": "#/components/responses/T413"
     },
     "422": {
      "$ref": "#/components/responses/T422"
     },
     "503": {
      "$ref": "#/components/responses/T503"
     }
    }
   },
   "get": {
    "tags": [
     "Firmware"
    ],
    "summary": "List firmware",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_version",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_type",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tag",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "description": "active|withdrawn",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "general",
      "in": "query",
      "required": false,
      "description": "general releases only (true) or not (false)",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "order",
      "in": "query",
      "required": false,
      "description": "asc (default desc)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1\u2013500 (100)",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Page",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Firmware"
           }
          },
          "next_offset": {
           "type": [
            "integer",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/firmware/": {
   "put": {
    "tags": [
     "Firmware"
    ],
    "summary": "Upload firmware (what string complete)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:write",
    "description": "Content negotiation: replies `OK` and text/plain errors by default; send `Accept: application/json` for JSON (201 + Location for a new object) and problem+json errors.",
    "parameters": [
     {
      "name": "what_index",
      "in": "query",
      "required": false,
      "description": "Choose among several what strings",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "general_release",
      "in": "query",
      "required": false,
      "description": "Publish immediately",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "fw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_version",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_type",
      "in": "query",
      "required": false,
      "description": "AFI/EFI/MFI",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_version",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "build_date",
      "in": "query",
      "required": false,
      "description": "RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/FirmwareUpload"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Stored (new or identical re-upload). Body `OK`; with `Accept: application/json` the stored record (200 = identical re-upload).",
      "content": {
       "text/html": {
        "schema": {
         "type": "string",
         "example": "OK"
        }
       }
      }
     },
     "201": {
      "description": "Created (with Accept: application/json)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Firmware"
        }
       }
      },
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/T400"
     },
     "401": {
      "$ref": "#/components/responses/T401"
     },
     "403": {
      "$ref": "#/components/responses/T403"
     },
     "404": {
      "$ref": "#/components/responses/T404"
     },
     "409": {
      "$ref": "#/components/responses/T409"
     },
     "413": {
      "$ref": "#/components/responses/T413"
     },
     "422": {
      "$ref": "#/components/responses/T422"
     },
     "503": {
      "$ref": "#/components/responses/T503"
     }
    }
   }
  },
  "/firmware/{hw_name}/{hw_version}/{fw_name}": {
   "put": {
    "tags": [
     "Firmware"
    ],
    "summary": "Upload firmware, supplying fields in the path",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:write",
    "description": "Content negotiation: replies `OK` and text/plain errors by default; send `Accept: application/json` for JSON (201 + Location for a new object) and problem+json errors.",
    "parameters": [
     {
      "name": "hw_name",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_version",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_name",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "what_index",
      "in": "query",
      "required": false,
      "description": "Choose among several what strings",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "general_release",
      "in": "query",
      "required": false,
      "description": "Publish immediately",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "fw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_name",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hw_version",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_type",
      "in": "query",
      "required": false,
      "description": "AFI/EFI/MFI",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fw_version",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "build_date",
      "in": "query",
      "required": false,
      "description": "RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/FirmwareUpload"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Stored (new or identical re-upload). Body `OK`; with `Accept: application/json` the stored record (200 = identical re-upload).",
      "content": {
       "text/html": {
        "schema": {
         "type": "string",
         "example": "OK"
        }
       }
      }
     },
     "201": {
      "description": "Created (with Accept: application/json)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Firmware"
        }
       }
      },
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/T400"
     },
     "401": {
      "$ref": "#/components/responses/T401"
     },
     "403": {
      "$ref": "#/components/responses/T403"
     },
     "404": {
      "$ref": "#/components/responses/T404"
     },
     "409": {
      "$ref": "#/components/responses/T409"
     },
     "413": {
      "$ref": "#/components/responses/T413"
     },
     "422": {
      "$ref": "#/components/responses/T422"
     },
     "503": {
      "$ref": "#/components/responses/T503"
     }
    }
   }
  },
  "/logdata/{name}": {
   "put": {
    "tags": [
     "Log data"
    ],
    "summary": "Upload a log file",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "logdata:write",
    "description": "Content negotiation: replies `OK` and text/plain errors by default; send `Accept: application/json` for JSON (201 + Location for a new object) and problem+json errors.",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "description": "Log file name: exactly 128 hex characters (512 bits)",
      "schema": {
       "type": "string",
       "pattern": "^[0-9a-fA-F]{128}$"
      }
     },
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Stored (new or identical re-upload). Body `OK`; with `Accept: application/json` the stored record (200 = identical re-upload).",
      "content": {
       "text/html": {
        "schema": {
         "type": "string",
         "example": "OK"
        }
       }
      }
     },
     "201": {
      "description": "Created (with Accept: application/json)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Logdata"
        }
       }
      },
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/T400"
     },
     "401": {
      "$ref": "#/components/responses/T401"
     },
     "403": {
      "$ref": "#/components/responses/T403"
     },
     "404": {
      "$ref": "#/components/responses/T404"
     },
     "409": {
      "$ref": "#/components/responses/T409"
     },
     "413": {
      "$ref": "#/components/responses/T413"
     },
     "503": {
      "$ref": "#/components/responses/T503"
     }
    }
   },
   "get": {
    "tags": [
     "Log data"
    ],
    "summary": "Download a log file (302 to a /dl link)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "logdata:read",
    "description": "Content negotiation: replies `OK` and text/plain errors by default; send `Accept: application/json` for JSON (201 + Location for a new object) and problem+json errors.",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "description": "Log file name: exactly 128 hex characters (512 bits)",
      "schema": {
       "type": "string",
       "pattern": "^[0-9a-fA-F]{128}$"
      }
     },
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "302": {
      "description": "Redirect to a 5-minute `/dl/\u2026` download link",
      "headers": {
       "Location": {
        "schema": {
         "type": "string",
         "format": "uri"
        }
       }
      },
      "content": {
       "text/html": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/T400"
     },
     "401": {
      "$ref": "#/components/responses/T401"
     },
     "403": {
      "$ref": "#/components/responses/T403"
     },
     "404": {
      "$ref": "#/components/responses/T404"
     }
    }
   },
   "head": {
    "tags": [
     "Log data"
    ],
    "summary": "Size, type and SHA-256 ETag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "logdata:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "in": "path",
      "required": true,
      "description": "Log file name: exactly 128 hex characters (512 bits)",
      "schema": {
       "type": "string",
       "pattern": "^[0-9a-fA-F]{128}$"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Headers only",
      "headers": {
       "ETag": {
        "schema": {
         "type": "string"
        }
       },
       "Content-Length": {
        "schema": {
         "type": "integer"
        }
       }
      }
     },
     "404": {
      "description": "Not found"
     }
    }
   }
  },
  "/logdata": {
   "get": {
    "tags": [
     "Log data"
    ],
    "summary": "List log files",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "logdata:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "prefix",
      "in": "query",
      "required": false,
      "description": "Hex prefix",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "uploaded_after",
      "in": "query",
      "required": false,
      "description": "RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "uploaded_before",
      "in": "query",
      "required": false,
      "description": "RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1\u2013500 (50)",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "items to skip; next_offset from the previous page",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Page",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/LogdataPage"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/logdata/{name}/meta": {
   "get": {
    "tags": [
     "Log data"
    ],
    "summary": "Metadata",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "logdata:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "in": "path",
      "required": true,
      "description": "Log file name: exactly 128 hex characters (512 bits)",
      "schema": {
       "type": "string",
       "pattern": "^[0-9a-fA-F]{128}$"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Metadata",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Logdata"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/firmware/parse": {
   "post": {
    "tags": [
     "Firmware"
    ],
    "summary": "Dry run: parse what strings",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "type": "object",
        "required": [
         "firmware"
        ],
        "properties": {
         "firmware": {
          "type": "string",
          "format": "binary"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Parse result",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ParseResult"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "413": {
      "$ref": "#/components/responses/P413"
     }
    }
   }
  },
  "/firmware/{id}": {
   "get": {
    "tags": [
     "Firmware"
    ],
    "summary": "Get firmware",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Firmware",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Firmware"
        }
       }
      },
      "headers": {
       "ETag": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   },
   "patch": {
    "tags": [
     "Firmware"
    ],
    "summary": "Update release settings (tags, general release, status)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     },
     {
      "name": "If-Match",
      "in": "header",
      "required": false,
      "description": "ETag from GET",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
         "tags": {
          "type": "array",
          "items": {
           "type": "string"
          }
         },
         "tag_filter_disabled": {
          "type": "boolean"
         },
         "status": {
          "enum": [
           "active",
           "withdrawn"
          ]
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Updated",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Firmware"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "412": {
      "$ref": "#/components/responses/P412"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/firmware/{id}/binary": {
   "get": {
    "tags": [
     "Firmware"
    ],
    "summary": "Download binary (302)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "302": {
      "description": "Redirect to a 5-minute `/dl/\u2026` download link",
      "headers": {
       "Location": {
        "schema": {
         "type": "string",
         "format": "uri"
        }
       }
      },
      "content": {
       "text/html": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/firmware/{id}/notes": {
   "get": {
    "tags": [
     "Firmware"
    ],
    "summary": "Download release notes (302)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "302": {
      "description": "Redirect to a 5-minute `/dl/\u2026` download link",
      "headers": {
       "Location": {
        "schema": {
         "type": "string",
         "format": "uri"
        }
       }
      },
      "content": {
       "text/html": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/firmware/{id}/tags": {
   "get": {
    "tags": [
     "Firmware",
     "Tags"
    ],
    "summary": "Get tags",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Tags",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tags": {
           "type": "array",
           "items": {
            "type": "string"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   },
   "put": {
    "tags": [
     "Firmware",
     "Tags"
    ],
    "summary": "Replace tag set",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "tags"
        ],
        "properties": {
         "tags": {
          "type": "array",
          "items": {
           "type": "string"
          }
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Tags",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tags": {
           "type": "array",
           "items": {
            "type": "string"
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/firmware/{id}/tags/{tag}": {
   "put": {
    "tags": [
     "Firmware",
     "Tags"
    ],
    "summary": "Add a tag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Added (idempotent)"
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   },
   "delete": {
    "tags": [
     "Firmware",
     "Tags"
    ],
    "summary": "Remove a tag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Firmware id (UUID)",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Removed (idempotent)"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/devices/{hwid}/tags": {
   "get": {
    "tags": [
     "Devices",
     "Tags"
    ],
    "summary": "Get tags",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "devices:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Tags",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tags": {
           "type": "array",
           "items": {
            "type": "string"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   },
   "put": {
    "tags": [
     "Devices",
     "Tags"
    ],
    "summary": "Replace tag set",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "tags"
        ],
        "properties": {
         "tags": {
          "type": "array",
          "items": {
           "type": "string"
          }
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Tags",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tags": {
           "type": "array",
           "items": {
            "type": "string"
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/devices/{hwid}/tags/{tag}": {
   "put": {
    "tags": [
     "Devices",
     "Tags"
    ],
    "summary": "Add a tag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Added (idempotent)"
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   },
   "delete": {
    "tags": [
     "Devices",
     "Tags"
    ],
    "summary": "Remove a tag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Removed (idempotent)"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/devices": {
   "get": {
    "tags": [
     "Devices"
    ],
    "summary": "List devices",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "devices:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tag",
      "in": "query",
      "required": false,
      "description": "Repeatable",
      "schema": {
       "type": "array",
       "items": {
        "type": "string"
       }
      }
     },
     {
      "name": "tag_mode",
      "in": "query",
      "required": false,
      "description": "any|all",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "hwid prefix (case-sensitive)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "description": "active|withdrawn",
      "schema": {
       "enum": [
        "active",
        "withdrawn"
       ]
      }
     },
     {
      "name": "has_keys",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1\u20131000 (100)",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "items to skip; next_offset from the previous page",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Page",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Device"
           }
          },
          "next_offset": {
           "type": [
            "integer",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/devices/import": {
   "post": {
    "tags": [
     "Devices"
    ],
    "summary": "Bulk import (all-or-nothing)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "devices:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "mode",
      "in": "query",
      "required": false,
      "description": "create (default) | upsert",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "dry_run",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "force",
      "in": "query",
      "required": false,
      "description": "allow key changes",
      "schema": {
       "type": "boolean"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "text/csv": {
       "schema": {
        "type": "string",
        "description": "hwid,identity_pubkey,session_pubkey,tags(;-separated),notes"
       }
      },
      "application/json": {
       "schema": {
        "type": "array",
        "items": {
         "$ref": "#/components/schemas/DeviceInput"
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "created": {
           "type": "integer"
          },
          "updated": {
           "type": "integer"
          },
          "dry_run": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "413": {
      "$ref": "#/components/responses/P413"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/devices/{hwid}": {
   "get": {
    "tags": [
     "Devices"
    ],
    "summary": "Get device",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "devices:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Device",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Device"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   },
   "put": {
    "tags": [
     "Devices"
    ],
    "summary": "Create or update device",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "devices:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     },
     {
      "name": "force",
      "in": "query",
      "required": false,
      "description": "allow changing an existing key",
      "schema": {
       "type": "boolean"
      }
     }
    ],
    "requestBody": {
     "required": false,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DeviceInput"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Created",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Device"
        }
       }
      }
     },
     "200": {
      "description": "Updated",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Device"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   },
   "patch": {
    "tags": [
     "Devices"
    ],
    "summary": "Partial update (null clears)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "devices:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hwid",
      "in": "path",
      "required": true,
      "description": "Device HW id: 1\u201364 printable ASCII characters without spaces, case-sensitive; percent-encode reserved characters",
      "schema": {
       "type": "string",
       "pattern": "^[\\x21-\\x7E]{1,64}$",
       "minLength": 1,
       "maxLength": 64
      }
     },
     {
      "name": "force",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "boolean"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DeviceInput"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Updated",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Device"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/tags": {
   "get": {
    "tags": [
     "Tags"
    ],
    "summary": "List tags with counts",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Tags",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/TagInfo"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/tags/{tag}/devices": {
   "get": {
    "tags": [
     "Tags"
    ],
    "summary": "Devices with a tag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "devices:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "description": "active|withdrawn",
      "schema": {
       "enum": [
        "active",
        "withdrawn"
       ]
      }
     },
     {
      "name": "has_keys",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1\u20131000 (100)",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "items to skip; next_offset from the previous page",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Page",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Device"
           }
          },
          "next_offset": {
           "type": [
            "integer",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/tags/{tag}/firmware": {
   "get": {
    "tags": [
     "Tags"
    ],
    "summary": "Firmware with a tag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "fw:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Page",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Firmware"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/tags/{tag}": {
   "patch": {
    "tags": [
     "Tags"
    ],
    "summary": "Rename tag",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "name"
        ],
        "properties": {
         "name": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Renamed",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "name": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   },
   "delete": {
    "tags": [
     "Tags"
    ],
    "summary": "Delete tag everywhere",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "tags:write",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tag",
      "in": "path",
      "required": true,
      "description": "Tag name",
      "schema": {
       "type": "string",
       "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Deleted"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "503": {
      "$ref": "#/components/responses/P503"
     }
    }
   }
  },
  "/tokens": {
   "get": {
    "tags": [
     "Tokens"
    ],
    "summary": "List API tokens",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "any member",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Tokens",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/APIToken"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   },
   "post": {
    "tags": [
     "Tokens"
    ],
    "summary": "Create an API token (console session only)",
    "security": [
     {
      "session": []
     }
    ],
    "x-required-scope": "any member; scopes \u2264 role",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "X-CSRF-Token",
      "in": "header",
      "required": true,
      "description": "CSRF token",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "name"
        ],
        "properties": {
         "name": {
          "type": "string",
          "maxLength": 100
         },
         "bundle": {
          "enum": [
           "read-only",
           "uploader",
           "full"
          ]
         },
         "scopes": {
          "type": "array",
          "items": {
           "$ref": "#/components/schemas/Scope"
          }
         },
         "ttl_seconds": {
          "type": "integer",
          "minimum": 60,
          "maximum": 31536000,
          "default": 7776000
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Token (shown once)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/NewToken"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/tokens/{jti}": {
   "delete": {
    "tags": [
     "Tokens"
    ],
    "summary": "Revoke an API token",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "creator or members:manage",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "jti",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Revoked (idempotent)"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/members": {
   "get": {
    "tags": [
     "Members"
    ],
    "summary": "List members",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "members:manage",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Members",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Membership"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   },
   "post": {
    "tags": [
     "Members"
    ],
    "summary": "Invite a member",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "members:manage",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "email"
        ],
        "properties": {
         "email": {
          "type": "string",
          "format": "email"
         },
         "role": {
          "$ref": "#/components/schemas/Role"
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Invited",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/InviteResult"
        }
       }
      }
     },
     "200": {
      "description": "Existing membership updated",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/InviteResult"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/members/{email}": {
   "patch": {
    "tags": [
     "Members"
    ],
    "summary": "Change role / disable",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "members:manage",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "email",
      "in": "path",
      "required": true,
      "description": "Member email",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "role": {
          "$ref": "#/components/schemas/Role"
         },
         "disabled": {
          "type": "boolean"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Updated",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Membership"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     }
    }
   },
   "delete": {
    "tags": [
     "Members"
    ],
    "summary": "Remove a member",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "members:manage",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "email",
      "in": "path",
      "required": true,
      "description": "Member email",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Removed"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     }
    }
   }
  },
  "/stats/summary": {
   "get": {
    "tags": [
     "Stats"
    ],
    "summary": "Daily usage + totals",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "stats:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Summary",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/StatsSummary"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/stats/events": {
   "get": {
    "tags": [
     "Stats"
    ],
    "summary": "Access log (filtered view: truncated IPs)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "stats:read",
    "parameters": [
     {
      "name": "customer",
      "in": "query",
      "required": false,
      "description": "Admins only: act on this customer (default: the token's customer)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "route",
      "in": "query",
      "required": false,
      "description": "Route pattern",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1\u20131000 (100)",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "items to skip; next_offset from the previous page",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Events",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/EventPage"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     }
    }
   }
  },
  "/admin/customers": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "List customers with counts",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "responses": {
     "200": {
      "description": "Customers",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Customer"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   },
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "Create customer (optionally invite owner)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "domain": {
          "type": "string"
         },
         "name": {
          "type": "string"
         },
         "status": {
          "enum": [
           "active",
           "suspended"
          ]
         },
         "cors_origins": {
          "type": "array",
          "items": {
           "type": "string"
          }
         },
         "owner_email": {
          "type": "string",
          "format": "email"
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Created",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "customer": {
           "$ref": "#/components/schemas/Customer"
          },
          "warning": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/customers/{domain}": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Customer + members",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "domain",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Customer",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "customer": {
           "$ref": "#/components/schemas/Customer"
          },
          "members": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Membership"
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   },
   "patch": {
    "tags": [
     "Admin"
    ],
    "summary": "Update customer",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "domain",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "domain": {
          "type": "string"
         },
         "name": {
          "type": "string"
         },
         "status": {
          "enum": [
           "active",
           "suspended"
          ]
         },
         "cors_origins": {
          "type": "array",
          "items": {
           "type": "string"
          }
         },
         "owner_email": {
          "type": "string",
          "format": "email"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Updated",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "customer": {
           "$ref": "#/components/schemas/Customer"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   },
   "delete": {
    "tags": [
     "Admin"
    ],
    "summary": "Delete customer and all data",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "domain",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "confirm",
      "in": "query",
      "required": true,
      "description": "must equal the domain",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Deleted"
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/users": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "All memberships",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "responses": {
     "200": {
      "description": "Users",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Membership"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/users/{email}": {
   "patch": {
    "tags": [
     "Admin"
    ],
    "summary": "Disable/enable a person everywhere",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "email",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "disabled"
        ],
        "properties": {
         "disabled": {
          "type": "boolean"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Updated",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/stats/summary": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Cross-customer statistics",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Summary",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/stats/events": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Full access log",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD or RFC 3339",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "route",
      "in": "query",
      "required": false,
      "description": "Route pattern",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1\u20131000 (100)",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "items to skip; next_offset from the previous page",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "domain",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ip",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Events",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/EventPage"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/audit": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Audit log",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "domain",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Audit",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/AuditEntry"
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/security/events": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Security events",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "severity",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "unacked",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Events",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/SecurityEvent"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/security/events/{id}/ack": {
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "Acknowledge event",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Acknowledged"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/ip-blocks": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "List IP blocks",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "all",
      "in": "query",
      "required": false,
      "description": "include expired",
      "schema": {
       "type": "boolean"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Blocks",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/IPBlock"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   },
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "Block an IP/CIDR",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "cidr"
        ],
        "properties": {
         "cidr": {
          "type": "string"
         },
         "reason": {
          "type": "string"
         },
         "ttl_seconds": {
          "type": "integer"
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Blocked",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   },
   "delete": {
    "tags": [
     "Admin"
    ],
    "summary": "Unblock",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "cidr",
      "in": "query",
      "required": true,
      "description": "",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Removed"
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/settings/maintenance": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Maintenance mode",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "responses": {
     "200": {
      "description": "State",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "enabled": {
           "type": "boolean"
          },
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   },
   "put": {
    "tags": [
     "Admin"
    ],
    "summary": "Set maintenance mode",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "enabled": {
          "type": "boolean"
         },
         "message": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "State",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "enabled": {
           "type": "boolean"
          },
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/jobs": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Background jobs",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Jobs",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/backups": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Backups, verifications, restores",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Backups",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "backend": {
           "type": "string"
          },
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Backup"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   },
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "Start a backup",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "requestBody": {
     "required": false,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "archive_name": {
          "type": "string"
         },
         "tarsnap_key_b64": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "202": {
      "description": "Queued",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "id": {
           "type": "string"
          },
          "kind": {
           "type": "string"
          },
          "status": {
           "type": "string"
          }
         }
        }
       }
      },
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/backups/verify": {
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "Verify a backup",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "requestBody": {
     "required": false,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "archive_name": {
          "type": "string"
         },
         "tarsnap_key_b64": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "202": {
      "description": "Queued",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "id": {
           "type": "string"
          },
          "kind": {
           "type": "string"
          },
          "status": {
           "type": "string"
          }
         }
        }
       }
      },
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/backups/verify-report": {
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "Record an external verification",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "archive_name": {
          "type": "string"
         },
         "ok": {
          "type": "boolean"
         },
         "detail": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Recorded",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Backup"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/backups/{id}": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Backup status + log",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Backup",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Backup"
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/P404"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  },
  "/admin/restores": {
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "Restore from an archive (destructive)",
    "security": [
     {
      "bearer": []
     },
     {
      "session": []
     }
    ],
    "x-required-scope": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "archive_name",
         "confirm"
        ],
        "properties": {
         "archive_name": {
          "type": "string"
         },
         "confirm": {
          "type": "string",
          "description": "restore <archive_name>"
         },
         "tarsnap_key_b64": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "202": {
      "description": "Queued",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "id": {
           "type": "string"
          },
          "kind": {
           "type": "string"
          },
          "status": {
           "type": "string"
          }
         }
        }
       }
      },
      "headers": {
       "Location": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/P400"
     },
     "409": {
      "$ref": "#/components/responses/P409"
     },
     "401": {
      "$ref": "#/components/responses/P401"
     },
     "403": {
      "$ref": "#/components/responses/P403"
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "bearer": {
    "type": "http",
    "scheme": "bearer",
    "bearerFormat": "JWT (EdDSA)",
    "description": "API token created in the console"
   },
   "session": {
    "type": "apiKey",
    "in": "cookie",
    "name": "__Host-ucl_at",
    "description": "Console session cookie (plus X-CSRF-Token on writes)"
   },
   "metricsToken": {
    "type": "http",
    "scheme": "bearer",
    "description": "METRICS_TOKEN configured by the operator"
   }
  },
  "schemas": {
   "Problem": {
    "type": "object",
    "description": "RFC 9457 problem details",
    "properties": {
     "type": {
      "type": "string"
     },
     "title": {
      "type": "string"
     },
     "status": {
      "type": "integer"
     },
     "detail": {
      "type": "string"
     },
     "instance": {
      "type": "string"
     },
     "request_id": {
      "type": "string"
     }
    },
    "additionalProperties": true
   },
   "Scope": {
    "enum": [
     "fw:read",
     "fw:write",
     "logdata:read",
     "logdata:write",
     "devices:read",
     "devices:write",
     "tags:read",
     "tags:write",
     "stats:read",
     "members:manage",
     "admin"
    ]
   },
   "Role": {
    "enum": [
     "viewer",
     "editor",
     "owner"
    ]
   },
   "Check": {
    "type": "object",
    "properties": {
     "ok": {
      "type": "boolean"
     },
     "latency_ms": {
      "type": "integer"
     },
     "detail": {
      "type": "string"
     }
    }
   },
   "Ready": {
    "type": "object",
    "properties": {
     "ready": {
      "type": "boolean"
     },
     "checks": {
      "type": "object",
      "additionalProperties": {
       "$ref": "#/components/schemas/Check"
      }
     }
    }
   },
   "Status": {
    "type": "object",
    "properties": {
     "status": {
      "enum": [
       "ok",
       "degraded",
       "down"
      ]
     },
     "version": {
      "type": "string"
     },
     "git_sha": {
      "type": "string"
     },
     "started_at": {
      "type": "string",
      "format": "date-time"
     },
     "uptime_seconds": {
      "type": "integer"
     },
     "active_connections": {
      "type": "integer"
     },
     "requests_total": {
      "type": "integer"
     },
     "requests_in_flight": {
      "type": "integer"
     },
     "db_pool": {
      "type": "object"
     },
     "checks": {
      "type": "object"
     },
     "time": {
      "type": "string",
      "format": "date-time"
     }
    }
   },
   "HealthDay": {
    "type": "object",
    "properties": {
     "day": {
      "type": "string",
      "format": "date"
     },
     "component": {
      "type": "string"
     },
     "samples": {
      "type": "integer"
     },
     "ok_samples": {
      "type": "integer"
     },
     "uptime_pct": {
      "type": "number"
     },
     "p50_ms": {
      "type": [
       "integer",
       "null"
      ]
     },
     "p95_ms": {
      "type": [
       "integer",
       "null"
      ]
     },
     "incidents": {
      "type": "integer"
     }
    }
   },
   "HealthHistory": {
    "type": "object",
    "properties": {
     "days": {
      "type": "integer"
     },
     "uptime_pct": {
      "type": "object",
      "additionalProperties": {
       "type": "number"
      }
     },
     "daily": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/HealthDay"
      }
     }
    }
   },
   "CompatUpdateItem": {
    "type": "object",
    "required": [
     "firmware-url",
     "release-notes-url",
     "version"
    ],
    "properties": {
     "firmware-url": {
      "type": "string",
      "format": "uri"
     },
     "release-notes-url": {
      "type": "string",
      "format": "uri"
     },
     "version": {
      "type": "string",
      "example": "example-hw/2.0.0/demo/1.4.1-10-g30d0049"
     },
     "id": {
      "type": "string"
     },
     "fw-version": {
      "type": "string"
     },
     "fw-type": {
      "enum": [
       "AFI",
       "EFI",
       "MFI"
      ]
     },
     "build-date": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "size": {
      "type": "integer"
     },
     "sha256": {
      "type": "string"
     },
     "general-release": {
      "type": "boolean"
     },
     "expires": {
      "type": "string",
      "format": "date-time"
     }
    }
   },
   "Me": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string"
     },
     "customer": {
      "type": "string"
     },
     "role": {
      "type": "string"
     },
     "admin": {
      "enum": [
       "",
       "viewer",
       "full"
      ]
     },
     "scopes": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "memberships": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "domain": {
         "type": "string"
        },
        "role": {
         "type": "string"
        }
       }
      }
     },
     "csrf_token": {
      "type": "string"
     }
    }
   },
   "FirmwareUpload": {
    "type": "object",
    "required": [
     "firmware",
     "notes"
    ],
    "properties": {
     "firmware": {
      "type": "string",
      "format": "binary",
      "description": "Binary with an @(#) what string (\u226416 MiB)"
     },
     "notes": {
      "type": "string",
      "format": "binary",
      "description": "UTF-8 release notes (\u22641 MiB); .md = Markdown"
     },
     "fw_name": {
      "type": "string"
     },
     "hw_name": {
      "type": "string"
     },
     "hw_version": {
      "type": "string"
     },
     "fw_type": {
      "enum": [
       "AFI",
       "EFI",
       "MFI"
      ]
     },
     "fw_version": {
      "type": "string"
     },
     "build_date": {
      "type": "string"
     },
     "what_index": {
      "type": "integer"
     },
     "general_release": {
      "type": "boolean"
     }
    }
   },
   "Firmware": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "fw_name": {
      "type": "string"
     },
     "hw_name": {
      "type": "string"
     },
     "hw_version": {
      "type": "string"
     },
     "fw_version": {
      "type": "string"
     },
     "version": {
      "type": "string"
     },
     "fw_type": {
      "type": "string"
     },
     "build_date": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "what_string": {
      "type": "string"
     },
     "what_format": {
      "type": "string"
     },
     "fields_from_request": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "size_bytes": {
      "type": "integer"
     },
     "sha256": {
      "type": "string"
     },
     "notes_size": {
      "type": "integer"
     },
     "notes_sha256": {
      "type": "string"
     },
     "notes_filename": {
      "type": [
       "string",
       "null"
      ]
     },
     "tag_filter_disabled": {
      "type": "boolean"
     },
     "status": {
      "enum": [
       "active",
       "withdrawn"
      ]
     },
     "uploaded_at": {
      "type": "string",
      "format": "date-time"
     },
     "uploaded_by": {
      "type": "string"
     },
     "download_count": {
      "type": "integer"
     },
     "notes_download_count": {
      "type": "integer"
     },
     "last_accessed_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "updated_at": {
      "type": "string",
      "format": "date-time"
     },
     "tags": {
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    }
   },
   "ParseResult": {
    "type": "object",
    "properties": {
     "size_bytes": {
      "type": "integer"
     },
     "sha256": {
      "type": "string"
     },
     "what_strings": {
      "type": "array",
      "items": {
       "type": "object"
      }
     }
    }
   },
   "Logdata": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string"
     },
     "size_bytes": {
      "type": "integer"
     },
     "sha256": {
      "type": "string"
     },
     "content_type": {
      "type": "string"
     },
     "uploaded_at": {
      "type": "string",
      "format": "date-time"
     },
     "uploaded_by": {
      "type": "string"
     },
     "download_count": {
      "type": "integer"
     },
     "last_accessed_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     }
    }
   },
   "LogdataPage": {
    "type": "object",
    "properties": {
     "items": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Logdata"
      }
     },
     "next_offset": {
      "type": [
       "integer",
       "null"
      ]
     }
    }
   },
   "Device": {
    "type": "object",
    "properties": {
     "hwid": {
      "type": "string",
      "description": "1\u201364 printable ASCII characters, case-sensitive"
     },
     "identity_pubkey": {
      "type": [
       "string",
       "null"
      ],
      "pattern": "^[0-9a-f]{64}$",
      "description": "Ed25519 public key, 64 lower-case hex digits"
     },
     "session_pubkey": {
      "type": [
       "string",
       "null"
      ],
      "pattern": "^[0-9a-f]{64}$",
      "description": "Ed25519 public key, 64 lower-case hex digits"
     },
     "tags": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "notes": {
      "type": "string"
     },
     "status": {
      "enum": [
       "active",
       "withdrawn"
      ]
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "updated_at": {
      "type": "string",
      "format": "date-time"
     },
     "last_seen_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     }
    }
   },
   "DeviceInput": {
    "type": "object",
    "properties": {
     "hwid": {
      "type": "string",
      "pattern": "^[\\x21-\\x7E]{1,64}$",
      "minLength": 1,
      "maxLength": 64,
      "description": "import only"
     },
     "identity_pubkey": {
      "type": [
       "string",
       "null"
      ],
      "pattern": "^[0-9a-fA-F]{64}$",
      "description": "Ed25519 public key: 64 hex digits (32 bytes); null clears it"
     },
     "session_pubkey": {
      "type": [
       "string",
       "null"
      ],
      "pattern": "^[0-9a-fA-F]{64}$",
      "description": "Ed25519 public key: 64 hex digits (32 bytes); null clears it"
     },
     "notes": {
      "type": [
       "string",
       "null"
      ]
     },
     "tags": {
      "type": [
       "array",
       "null"
      ],
      "items": {
       "type": "string"
      }
     },
     "status": {
      "enum": [
       "active",
       "withdrawn"
      ],
      "description": "PATCH only; a withdrawn device accepts only {\"status\":\"active\"}"
     }
    }
   },
   "TagInfo": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string"
     },
     "device_count": {
      "type": "integer"
     },
     "firmware_count": {
      "type": "integer"
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     }
    }
   },
   "APIToken": {
    "type": "object",
    "properties": {
     "jti": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "scopes": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "created_by": {
      "type": [
       "string",
       "null"
      ]
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "expires_at": {
      "type": "string",
      "format": "date-time"
     },
     "last_used_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "use_count": {
      "type": "integer"
     },
     "revoked_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     }
    }
   },
   "NewToken": {
    "type": "object",
    "properties": {
     "jti": {
      "type": "string"
     },
     "token": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "scopes": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "expires_at": {
      "type": "string",
      "format": "date-time"
     },
     "customer": {
      "type": "string"
     },
     "note": {
      "type": "string"
     }
    }
   },
   "Membership": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string"
     },
     "domain": {
      "type": "string"
     },
     "role": {
      "type": "string"
     },
     "disabled": {
      "type": "boolean"
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "last_login_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "user_disabled": {
      "type": "boolean"
     }
    }
   },
   "InviteResult": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string"
     },
     "role": {
      "type": "string"
     },
     "domain": {
      "type": "string"
     },
     "created": {
      "type": "boolean"
     },
     "warning": {
      "type": "string"
     }
    }
   },
   "StatsSummary": {
    "type": "object",
    "properties": {
     "from": {
      "type": "string",
      "format": "date-time"
     },
     "to": {
      "type": "string",
      "format": "date-time"
     },
     "days": {
      "type": "array",
      "items": {
       "type": "object"
      }
     },
     "totals": {
      "type": "object"
     }
    }
   },
   "Event": {
    "type": "object",
    "properties": {
     "ts": {
      "type": "string",
      "format": "date-time"
     },
     "domain": {
      "type": "string"
     },
     "actor": {
      "type": "string"
     },
     "method": {
      "type": "string"
     },
     "route": {
      "type": "string"
     },
     "path": {
      "type": "string"
     },
     "status": {
      "type": "integer"
     },
     "ip": {
      "type": "string"
     },
     "user_agent": {
      "type": "string"
     },
     "bytes_in": {
      "type": "integer"
     },
     "bytes_out": {
      "type": "integer"
     },
     "duration_ms": {
      "type": "integer"
     },
     "object_type": {
      "type": "string"
     },
     "object_id": {
      "type": "string"
     },
     "url_issued": {
      "type": "string"
     },
     "request_id": {
      "type": "string"
     }
    }
   },
   "EventPage": {
    "type": "object",
    "properties": {
     "items": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Event"
      }
     },
     "next_offset": {
      "type": [
       "integer",
       "null"
      ]
     }
    }
   },
   "Customer": {
    "type": "object",
    "properties": {
     "domain": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "status": {
      "type": "string"
     },
     "cors_origins": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "is_sandbox": {
      "type": "boolean"
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "updated_at": {
      "type": "string",
      "format": "date-time"
     },
     "counts": {
      "type": "object"
     }
    }
   },
   "AuditEntry": {
    "type": "object",
    "properties": {
     "ts": {
      "type": "string",
      "format": "date-time"
     },
     "domain": {
      "type": "string"
     },
     "actor": {
      "type": "string"
     },
     "action": {
      "type": "string"
     },
     "target_type": {
      "type": "string"
     },
     "target_id": {
      "type": "string"
     },
     "before": {},
     "after": {}
    }
   },
   "SecurityEvent": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer"
     },
     "ts": {
      "type": "string",
      "format": "date-time"
     },
     "kind": {
      "type": "string"
     },
     "severity": {
      "enum": [
       "info",
       "warn",
       "critical"
      ]
     },
     "ip": {
      "type": "string"
     },
     "domain": {
      "type": "string"
     },
     "detail": {
      "type": "object"
     },
     "notified_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "acked_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "acked_by": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   },
   "IPBlock": {
    "type": "object",
    "properties": {
     "cidr": {
      "type": "string"
     },
     "reason": {
      "type": "string"
     },
     "created_by": {
      "type": "string"
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "expires_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     }
    }
   },
   "Backup": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "kind": {
      "enum": [
       "backup",
       "restore",
       "verify"
      ]
     },
     "status": {
      "enum": [
       "queued",
       "running",
       "succeeded",
       "failed"
      ]
     },
     "archive_name": {
      "type": [
       "string",
       "null"
      ]
     },
     "object_count": {
      "type": [
       "integer",
       "null"
      ]
     },
     "total_bytes": {
      "type": [
       "integer",
       "null"
      ]
     },
     "initiated_by": {
      "type": "string"
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "started_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "finished_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "log": {
      "type": "string"
     },
     "error": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   }
  },
  "responses": {
   "P400": {
    "description": "Invalid request",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T400": {
    "description": "Invalid request (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "400 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P401": {
    "description": "Missing, invalid, expired or old-format credentials",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T401": {
    "description": "Missing, invalid, expired or old-format credentials (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "401 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P403": {
    "description": "Missing scope, CSRF token or admin rights; blocked IP",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T403": {
    "description": "Missing scope, CSRF token or admin rights; blocked IP (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "403 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P404": {
    "description": "Not found (including customers you cannot access)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T404": {
    "description": "Not found (including customers you cannot access) (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "404 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P409": {
    "description": "Conflict (different content under the same identity, key change, last owner, duplicate)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T409": {
    "description": "Conflict (different content under the same identity, key change, last owner, duplicate) (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "409 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P410": {
    "description": "Download link expired or invalid",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T410": {
    "description": "Download link expired or invalid (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "410 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P412": {
    "description": "Stale If-Match",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T412": {
    "description": "Stale If-Match (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "412 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P413": {
    "description": "Payload too large",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T413": {
    "description": "Payload too large (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "413 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P422": {
    "description": "Firmware what-string problem",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T422": {
    "description": "Firmware what-string problem (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "422 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P429": {
    "description": "Rate limited (see Retry-After)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     },
     "Retry-After": {
      "schema": {
       "type": "integer"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T429": {
    "description": "Rate limited (see Retry-After) (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     },
     "Retry-After": {
      "schema": {
       "type": "integer"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "429 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "P503": {
    "description": "Maintenance mode (writes) \u2014 see Retry-After",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     },
     "Retry-After": {
      "schema": {
       "type": "integer"
      }
     }
    },
    "content": {
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   },
   "T503": {
    "description": "Maintenance mode (writes) \u2014 see Retry-After (text/plain by default, application/problem+json with Accept: application/json)",
    "headers": {
     "X-Request-Id": {
      "schema": {
       "type": "string"
      }
     },
     "Retry-After": {
      "schema": {
       "type": "integer"
      }
     }
    },
    "content": {
     "text/plain": {
      "schema": {
       "type": "string",
       "example": "503 ...: detail"
      }
     },
     "application/problem+json": {
      "schema": {
       "$ref": "#/components/schemas/Problem"
      }
     }
    }
   }
  }
 },
 "security": [
  {
   "bearer": []
  },
  {
   "session": []
  }
 ]
}