{
  "openrpc": "1.3.2",
  "info": {
    "title": "Titan2 App API",
    "version": "1.0.0",
    "description": "JSON-RPC 2.0 over one WebSocket, for web and mobile clients.\n\nThe whole session is one connection: open it, authenticate it, then call and listen on it.\nUntil `auth.v1.authenticate` succeeds every other call is refused, and the connection is\nclosed once its deadline passes.\n\nAccess tokens come from the REST surface, which is documented separately."
  },
  "methods": [
    {
      "name": "auth.v1.authenticate",
      "summary": "Authenticate the connection with an access token.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "token",
          "required": true,
          "schema": {
            "type": "string",
            "description": "OAuth2/OIDC access token that identifies and authorizes the caller."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "principal": {
              "type": "object",
              "required": [
                "kind"
              ],
              "anyOf": [
                {
                  "properties": {
                    "kind": {
                      "const": "user"
                    },
                    "userId": true
                  },
                  "required": [
                    "userId"
                  ]
                },
                {
                  "properties": {
                    "kind": {
                      "const": "admin"
                    },
                    "adminId": true
                  },
                  "required": [
                    "adminId"
                  ]
                },
                {
                  "properties": {
                    "kind": {
                      "const": "orgApiKey"
                    },
                    "apiKeyId": true,
                    "organizationId": true
                  },
                  "required": [
                    "apiKeyId",
                    "organizationId"
                  ]
                }
              ],
              "description": "The authenticated principal: identity and resolved authorization."
            }
          },
          "required": [
            "principal"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/auth"
        }
      ]
    },
    {
      "name": "user.v1.authMethod.list",
      "summary": "The ways this account can sign in: its password, and each linked provider.",
      "paramStructure": "by-name",
      "params": [],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              },
              "kind": {
                "enum": [
                  "Password",
                  "Sso"
                ],
                "description": "What the method is: Password or Sso."
              },
              "providerName": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Display name of the identity provider; null for a password."
              },
              "createdAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the method was added (UTC)."
              },
              "lastUsedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it last signed the account in (UTC); null if never."
              },
              "secondFactorEnabled": {
                "type": "boolean",
                "description": "Whether a second factor is required alongside this method."
              }
            },
            "required": [
              "id",
              "kind",
              "providerName",
              "createdAt",
              "lastUsedAt",
              "secondFactorEnabled"
            ]
          }
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.authMethod.pairSso",
      "summary": "Begin linking an identity provider to the caller's account.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "providerId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "redirectUri",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Which frontend route the provider returns to; one of the configured callbacks. Defaults to the first."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "redirectUrl": {
              "type": "string",
              "description": "Send the browser here to complete the link at the provider."
            }
          },
          "required": [
            "redirectUrl"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.authMethod.unlink",
      "summary": "Remove one of the account's sign-in methods.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "methodId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.get",
      "summary": "The signed-in user's own account and memberships.",
      "paramStructure": "by-name",
      "params": [],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "profile": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                },
                "displayName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Full name, or the primary email address when the account has no name."
                },
                "emails": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "address": {
                        "type": "string",
                        "description": "The email address."
                      },
                      "isPrimary": {
                        "type": "boolean",
                        "description": "True for the login identity. Secondary addresses are for notification and recovery only."
                      },
                      "isVerified": {
                        "type": "boolean",
                        "description": "Whether the address has been confirmed."
                      }
                    },
                    "required": [
                      "address",
                      "isPrimary",
                      "isVerified"
                    ]
                  },
                  "description": "Every email address on the account; exactly one is primary."
                },
                "country": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Country the user selected; null when unset."
                },
                "language": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "UI language tag the user selected, e.g. \"en\"."
                },
                "newsletter": {
                  "type": "boolean",
                  "description": "Whether the user opted into the newsletter."
                },
                "defaultOrganizationId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                },
                "isManaged": {
                  "type": "boolean",
                  "description": "True when an external directory owns this account's details."
                },
                "createdAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "When the account was created (UTC)."
                }
              },
              "required": [
                "id",
                "displayName",
                "emails",
                "country",
                "language",
                "newsletter",
                "defaultOrganizationId",
                "isManaged",
                "createdAt"
              ],
              "description": "The signed-in account."
            },
            "memberships": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "orgId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "orgName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of the organization."
                  },
                  "roleId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "roleName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name of that role."
                  },
                  "permissions": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Organization permissions that role carries, by name. Per-object access comes on each object's own read."
                  }
                },
                "required": [
                  "orgId",
                  "orgName",
                  "roleId",
                  "roleName",
                  "permissions"
                ]
              },
              "description": "The organizations the account belongs to, and its role in each."
            },
            "authMethods": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "kind": {
                    "enum": [
                      "Password",
                      "Sso"
                    ],
                    "description": "What the method is: Password or Sso."
                  },
                  "providerName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of the identity provider; null for a password."
                  },
                  "createdAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the method was added (UTC)."
                  },
                  "lastUsedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When it last signed the account in (UTC); null if never."
                  },
                  "secondFactorEnabled": {
                    "type": "boolean",
                    "description": "Whether a second factor is required alongside this method."
                  }
                },
                "required": [
                  "id",
                  "kind",
                  "providerName",
                  "createdAt",
                  "lastUsedAt",
                  "secondFactorEnabled"
                ]
              },
              "description": "The ways this account can sign in."
            }
          },
          "required": [
            "profile",
            "memberships",
            "authMethods"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ]
    },
    {
      "name": "user.v1.notification.delete",
      "summary": "Dismiss one notification.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "notificationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.notification.list",
      "summary": "The caller's notifications.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        },
        {
          "name": "includeSeen",
          "required": false,
          "schema": {
            "type": "boolean",
            "default": true,
            "description": "Include the ones already seen; omit for a badge count."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "title": {
                    "type": "string",
                    "description": "Short headline."
                  },
                  "message": {
                    "type": "string",
                    "description": "Body text in Markdown. May embed device references as [[device:<eid>:<path>]]."
                  },
                  "isSeen": {
                    "type": "boolean",
                    "description": "Whether the account has marked it seen."
                  },
                  "seenAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the account marked it seen (UTC); null while unseen."
                  },
                  "receivedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When it arrived (UTC)."
                  },
                  "expiresAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When it stops being shown (UTC); null when it never expires."
                  }
                },
                "required": [
                  "id",
                  "title",
                  "message",
                  "isSeen",
                  "seenAt",
                  "receivedAt",
                  "expiresAt"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.notification.markSeen",
      "summary": "Mark one notification as read.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "notificationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.password.change",
      "summary": "Change the caller's password, ending the account's other sessions.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "currentPassword",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The password the account signs in with today."
          }
        },
        {
          "name": "newPassword",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The password to replace it with."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ]
    },
    {
      "name": "user.v1.session.revokeAll",
      "summary": "End every session of the account, this one included.",
      "paramStructure": "by-name",
      "params": [],
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.totp.disable",
      "summary": "Turn off the second factor.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "currentPassword",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The account's current password."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.totp.enable",
      "summary": "Turn on the second factor for a client-held secret.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "secret",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Base32 TOTP secret the client generated. The server never mints one — a client that picks a weak secret has weakened only its own account."
          }
        },
        {
          "name": "code",
          "required": true,
          "schema": {
            "type": "string",
            "description": "A code currently live for that secret, proving the client holds it."
          }
        },
        {
          "name": "currentPassword",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The account's current password."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "recoveryCodes": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Ten single-use codes, shown exactly once. They cannot be read back — regenerating is the only way to see a set again, and it invalidates the previous one."
            }
          },
          "required": [
            "recoveryCodes"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.totp.recoveryCodes.regenerate",
      "summary": "Replace the recovery codes with a fresh set, invalidating the old one.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "currentPassword",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The account's current password."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "recoveryCodes": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Ten single-use codes, shown exactly once. They cannot be read back — regenerating is the only way to see a set again, and it invalidates the previous one."
            }
          },
          "required": [
            "recoveryCodes"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "user.v1.update",
      "summary": "Change the caller's own profile and preferences.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "displayName",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Name to show for the account; omit to leave unchanged, send empty to clear it and fall back to the email address."
          }
        },
        {
          "name": "country",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Country the user is in; omit to leave unchanged, send empty to clear it."
          }
        },
        {
          "name": "language",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Language the app should use, e.g. \"en\"; omit to leave unchanged."
          }
        },
        {
          "name": "defaultOrganizationId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "displayName": {
              "type": [
                "string",
                "null"
              ],
              "description": "Full name, or the primary email address when the account has no name."
            },
            "emails": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "description": "The email address."
                  },
                  "isPrimary": {
                    "type": "boolean",
                    "description": "True for the login identity. Secondary addresses are for notification and recovery only."
                  },
                  "isVerified": {
                    "type": "boolean",
                    "description": "Whether the address has been confirmed."
                  }
                },
                "required": [
                  "address",
                  "isPrimary",
                  "isVerified"
                ]
              },
              "description": "Every email address on the account; exactly one is primary."
            },
            "country": {
              "type": [
                "string",
                "null"
              ],
              "description": "Country the user selected; null when unset."
            },
            "language": {
              "type": [
                "string",
                "null"
              ],
              "description": "UI language tag the user selected, e.g. \"en\"."
            },
            "newsletter": {
              "type": "boolean",
              "description": "Whether the user opted into the newsletter."
            },
            "defaultOrganizationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "isManaged": {
              "type": "boolean",
              "description": "True when an external directory owns this account's details."
            },
            "createdAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When the account was created (UTC)."
            }
          },
          "required": [
            "id",
            "displayName",
            "emails",
            "country",
            "language",
            "newsletter",
            "defaultOrganizationId",
            "isManaged",
            "createdAt"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/user"
        }
      ]
    },
    {
      "name": "organization.v1.apiKey.create",
      "summary": "Issue an API key acting as one of the organization's roles.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "name",
          "required": true,
          "schema": {
            "type": "string",
            "description": "A name to recognise the key by later."
          }
        },
        {
          "name": "roleId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "expiresAt",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "default": null,
            "description": "When the key stops working; omit for one that does not expire."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "key": {
              "type": "object",
              "properties": {
                "orgId": {
                  "type": "string",
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                },
                "id": {
                  "type": "string",
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Display name of the key."
                },
                "roleId": {
                  "type": "string",
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                },
                "roleName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Name of that role."
                },
                "createdAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "When the key was issued (UTC)."
                },
                "expiresAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "When the key stops working (UTC), or null if it never does."
                },
                "isRevoked": {
                  "type": "boolean",
                  "description": "Whether the key has been revoked and no longer authenticates."
                },
                "revokedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "When it was revoked (UTC), or null if it was not."
                }
              },
              "required": [
                "orgId",
                "id",
                "name",
                "roleId",
                "roleName",
                "createdAt",
                "expiresAt",
                "isRevoked",
                "revokedAt"
              ],
              "description": "The key as it will be listed from now on."
            },
            "secret": {
              "type": "string",
              "description": "The secret to send as the X-Api-Key header. Returned here and nowhere else — it cannot be read back, so store it now or issue a new key."
            }
          },
          "required": [
            "key",
            "secret"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again.",
        "note": "The secret comes back once and cannot be read again — store it now."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.apiKey.list",
      "summary": "The organization's API keys. Never their secrets.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "orgId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of the key."
                  },
                  "roleId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "roleName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name of that role."
                  },
                  "createdAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the key was issued (UTC)."
                  },
                  "expiresAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the key stops working (UTC), or null if it never does."
                  },
                  "isRevoked": {
                    "type": "boolean",
                    "description": "Whether the key has been revoked and no longer authenticates."
                  },
                  "revokedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When it was revoked (UTC), or null if it was not."
                  }
                },
                "required": [
                  "orgId",
                  "id",
                  "name",
                  "roleId",
                  "roleName",
                  "createdAt",
                  "expiresAt",
                  "isRevoked",
                  "revokedAt"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.apiKey.revoke",
      "summary": "Stop an API key from working.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "keyId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.create",
      "summary": "Create an organization, with the caller as its administrator.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "name",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Name for the new organization."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name of the organization."
            },
            "timezone": {
              "type": [
                "string",
                "null"
              ],
              "description": "IANA timezone the organization operates in, e.g. \"Europe/Prague\"."
            },
            "createdAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When the organization was created (UTC)."
            },
            "credits": {
              "type": [
                "string",
                "integer",
                "null"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Remaining prepaid credit balance."
            },
            "userCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of users who are members of the organization."
            },
            "deviceCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of devices belonging to the organization."
            },
            "suspendedReason": {
              "type": [
                "string",
                "null"
              ],
              "description": "Reason the organization is suspended; null when active."
            }
          },
          "required": [
            "id",
            "name",
            "timezone",
            "createdAt",
            "credits",
            "userCount",
            "deviceCount",
            "suspendedReason"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.delete",
      "summary": "Schedule the organization for deletion, after re-entering the password.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "currentPassword",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The caller's current password, re-entered."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again.",
        "note": "It answers when the organization is scheduled, not when it is gone — deletion happens seven days later and nothing here reverses it."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.get",
      "summary": "Get an organization's details by id.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name of the organization."
            },
            "timezone": {
              "type": [
                "string",
                "null"
              ],
              "description": "IANA timezone the organization operates in, e.g. \"Europe/Prague\"."
            },
            "createdAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When the organization was created (UTC)."
            },
            "credits": {
              "type": [
                "string",
                "integer",
                "null"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Remaining prepaid credit balance."
            },
            "userCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of users who are members of the organization."
            },
            "deviceCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of devices belonging to the organization."
            },
            "suspendedReason": {
              "type": [
                "string",
                "null"
              ],
              "description": "Reason the organization is suspended; null when active."
            }
          },
          "required": [
            "id",
            "name",
            "timezone",
            "createdAt",
            "credits",
            "userCount",
            "deviceCount",
            "suspendedReason"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.invite.accept",
      "summary": "Claim an invitation, joining the organization in the role it grants.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "inviteToken",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The invite_token from the invitation link."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "orgId": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "orgName": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name of the organization."
            },
            "roleId": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "roleName": {
              "type": [
                "string",
                "null"
              ],
              "description": "Name of that role."
            },
            "permissions": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Organization permissions that role carries, by name. Per-object access comes on each object's own read."
            }
          },
          "required": [
            "orgId",
            "orgName",
            "roleId",
            "roleName",
            "permissions"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.invite.create",
      "summary": "Invite an address to join the organization in a given role.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "email",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Address to invite. The account claiming it must hold this address."
          }
        },
        {
          "name": "roleId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "orgId": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "email": {
              "type": "string",
              "description": "Address the invitation was sent to."
            },
            "roleId": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "roleName": {
              "type": [
                "string",
                "null"
              ],
              "description": "Name of that role."
            },
            "sentAt": {
              "type": "string",
              "format": "date-time",
              "description": "When the invitation was sent (UTC)."
            },
            "expiresAt": {
              "type": "string",
              "format": "date-time",
              "description": "When it stops being redeemable (UTC)."
            }
          },
          "required": [
            "orgId",
            "id",
            "email",
            "roleId",
            "roleName",
            "sentAt",
            "expiresAt"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.invite.list",
      "summary": "The invitations nobody has claimed yet, and that have not expired.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "orgId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "email": {
                    "type": "string",
                    "description": "Address the invitation was sent to."
                  },
                  "roleId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "roleName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name of that role."
                  },
                  "sentAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the invitation was sent (UTC)."
                  },
                  "expiresAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it stops being redeemable (UTC)."
                  }
                },
                "required": [
                  "orgId",
                  "id",
                  "email",
                  "roleId",
                  "roleName",
                  "sentAt",
                  "expiresAt"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.invite.revoke",
      "summary": "Withdraw an unclaimed invitation.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "inviteId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.list",
      "summary": "List organizations visible to the caller, optionally filtered by name.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "nameFilter",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Case-insensitive substring to filter organizations by name; omit for all."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of the organization."
                  },
                  "timezone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "IANA timezone the organization operates in, e.g. \"Europe/Prague\"."
                  },
                  "createdAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the organization was created (UTC)."
                  },
                  "credits": {
                    "type": [
                      "string",
                      "integer",
                      "null"
                    ],
                    "pattern": "^-?(?:0|[1-9]\\d*)$",
                    "description": "Remaining prepaid credit balance."
                  },
                  "userCount": {
                    "type": [
                      "string",
                      "integer"
                    ],
                    "pattern": "^-?(?:0|[1-9]\\d*)$",
                    "description": "Number of users who are members of the organization."
                  },
                  "deviceCount": {
                    "type": [
                      "string",
                      "integer"
                    ],
                    "pattern": "^-?(?:0|[1-9]\\d*)$",
                    "description": "Number of devices belonging to the organization."
                  },
                  "suspendedReason": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Reason the organization is suspended; null when active."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "timezone",
                  "createdAt",
                  "credits",
                  "userCount",
                  "deviceCount",
                  "suspendedReason"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.member.leave",
      "summary": "Leave the organization.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.member.list",
      "summary": "List an organization's members.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "orgId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "userId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Email addresses on the account."
                  },
                  "displayName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name the member goes by, when the account has one."
                  },
                  "roleId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "roleName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name of that role."
                  },
                  "isVerified": {
                    "type": "boolean",
                    "description": "Whether the account has confirmed its email address."
                  },
                  "isBlocked": {
                    "type": "boolean",
                    "description": "Whether the account is blocked from signing in."
                  },
                  "isManaged": {
                    "type": "boolean",
                    "description": "Whether the account is provisioned externally and cannot be edited here."
                  },
                  "authMethods": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "How this person can sign in: \"password\", or \"sso:<provider>\" per linked identity provider. Empty for an account with no usable credential — which is the answer to \"why can't this person log in?\"."
                  },
                  "joinedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the membership was granted (UTC)."
                  },
                  "hiddenFromListings": {
                    "type": "boolean",
                    "description": "Whether the membership is hidden from the member list and the billing count."
                  }
                },
                "required": [
                  "orgId",
                  "userId",
                  "emails",
                  "displayName",
                  "roleId",
                  "roleName",
                  "isVerified",
                  "isBlocked",
                  "isManaged",
                  "authMethods",
                  "joinedAt",
                  "hiddenFromListings"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.member.remove",
      "summary": "Remove a member from the organization.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "userId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.member.setRole",
      "summary": "Move a member to a different role in the organization.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "userId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "roleId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.role.create",
      "summary": "Define a new role in the organization.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "name",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Name for the role."
          }
        },
        {
          "name": "permissions",
          "required": true,
          "schema": {
            "type": "array",
            "items": {
              "enum": [
                "OrganizationManage",
                "CreditManage",
                "BillingView",
                "LogView",
                "DataHistoryView",
                "LocationManage",
                "UsersView",
                "UserManage",
                "RoleView",
                "RoleManage",
                "ApiMqtt",
                "ApiRest",
                "Demo",
                "ReportRead",
                "ReportManage",
                "DashboardManage",
                "AlertManage"
              ]
            },
            "description": "Organization permissions the role carries, by name. Anything omitted is not granted."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "orgId": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name of the role."
            },
            "isLocked": {
              "type": "boolean",
              "description": "Whether the role is one of the built-in roles and cannot be edited or deleted."
            },
            "permissions": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Organization permissions the role carries, by name."
            },
            "memberCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of members holding the role, hidden assignments excluded."
            }
          },
          "required": [
            "orgId",
            "id",
            "name",
            "isLocked",
            "permissions",
            "memberCount"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.role.delete",
      "summary": "Delete a role nobody holds. Its per-object access goes with it.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "roleId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.role.list",
      "summary": "List an organization's roles and the permissions each carries.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "orgId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of the role."
                  },
                  "isLocked": {
                    "type": "boolean",
                    "description": "Whether the role is one of the built-in roles and cannot be edited or deleted."
                  },
                  "permissions": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Organization permissions the role carries, by name."
                  },
                  "memberCount": {
                    "type": [
                      "string",
                      "integer"
                    ],
                    "pattern": "^-?(?:0|[1-9]\\d*)$",
                    "description": "Number of members holding the role, hidden assignments excluded."
                  }
                },
                "required": [
                  "orgId",
                  "id",
                  "name",
                  "isLocked",
                  "permissions",
                  "memberCount"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ]
    },
    {
      "name": "organization.v1.role.update",
      "summary": "Rename a role, or replace the permissions it carries.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "roleId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "name",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "New name."
          }
        },
        {
          "name": "permissions",
          "required": false,
          "schema": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "enum": [
                "OrganizationManage",
                "CreditManage",
                "BillingView",
                "LogView",
                "DataHistoryView",
                "LocationManage",
                "UsersView",
                "UserManage",
                "RoleView",
                "RoleManage",
                "ApiMqtt",
                "ApiRest",
                "Demo",
                "ReportRead",
                "ReportManage",
                "DashboardManage",
                "AlertManage"
              ]
            },
            "default": null,
            "description": "The permissions the role should carry, replacing the current set."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "orgId": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name of the role."
            },
            "isLocked": {
              "type": "boolean",
              "description": "Whether the role is one of the built-in roles and cannot be edited or deleted."
            },
            "permissions": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Organization permissions the role carries, by name."
            },
            "memberCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of members holding the role, hidden assignments excluded."
            }
          },
          "required": [
            "orgId",
            "id",
            "name",
            "isLocked",
            "permissions",
            "memberCount"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "organization.v1.update",
      "summary": "Change an organization's settings.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "name",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Display name."
          }
        },
        {
          "name": "timezone",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "IANA timezone the organization operates in."
          }
        },
        {
          "name": "alarmEmailDefault",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Where alerts go when a rule names no recipient of its own."
          }
        },
        {
          "name": "creditThreshold",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer",
              "null"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": null,
            "description": "Credit balance below which the organization is warned."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name of the organization."
            },
            "timezone": {
              "type": [
                "string",
                "null"
              ],
              "description": "IANA timezone the organization operates in, e.g. \"Europe/Prague\"."
            },
            "createdAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When the organization was created (UTC)."
            },
            "credits": {
              "type": [
                "string",
                "integer",
                "null"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Remaining prepaid credit balance."
            },
            "userCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of users who are members of the organization."
            },
            "deviceCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of devices belonging to the organization."
            },
            "suspendedReason": {
              "type": [
                "string",
                "null"
              ],
              "description": "Reason the organization is suspended; null when active."
            }
          },
          "required": [
            "id",
            "name",
            "timezone",
            "createdAt",
            "credits",
            "userCount",
            "deviceCount",
            "suspendedReason"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/organization"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "location.v1.defaultDashboard.get",
      "summary": "What a Location opens with, per role. A role or dashboard that has since been deleted is left out, which reads as the device grid.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "locationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "roleId": {
                "type": "string",
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              },
              "dashboardId": {
                "type": "string",
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              }
            },
            "required": [
              "roleId",
              "dashboardId"
            ]
          }
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/location"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "location.v1.defaultDashboard.set",
      "summary": "Choose what a Location opens with for one role: a dashboard, or the device grid.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "locationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "roleId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "dashboardId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/location"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "location.v1.list",
      "summary": "List Locations as a flat page, with resolved paths, optionally scoped to an organization.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of the Location."
                  },
                  "parentId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "organizationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "path": {
                    "type": "string",
                    "description": "Full resolved path, e.g. \"Root / Devices / Server Room\"."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "parentId",
                  "organizationId",
                  "path"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/location"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "location.v1.tree",
      "summary": "Return the root Locations with their children nested, for rendering navigation.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "maxDepth",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer",
              "null"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": null,
            "description": "How many levels to return; omit for the whole tree, 1 for roots without children."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Display name of the Location."
              },
              "organizationId": {
                "type": [
                  "string",
                  "null"
                ],
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              },
              "children": {
                "type": "array",
                "items": {
                  "$ref": "#/items"
                },
                "description": "Child Locations, empty at the requested depth limit or for a leaf."
              }
            },
            "required": [
              "id",
              "name",
              "organizationId",
              "children"
            ]
          }
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/location"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "device.v1.io.control",
      "summary": "Switch or power-cycle a device IO. Reaches the real device. It answers once the command is published, not when the device reports the new state — watch subscription.ioEvent for confirmation.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "ioId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "action",
          "required": true,
          "schema": {
            "enum": [
              "Off",
              "On",
              "ShortOff",
              "ShortOn",
              "Toggle"
            ],
            "description": "What to do: Off, On, ShortOff (power-cycle), ShortOn, or Toggle."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/device"
        }
      ]
    },
    {
      "name": "device.v1.io.list",
      "summary": "List a device's IOs (sockets).",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "deviceId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              },
              "deviceId": {
                "type": "string",
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Display name of the IO."
              },
              "socketNumber": {
                "type": [
                  "string",
                  "integer",
                  "null"
                ],
                "pattern": "^-?(?:0|[1-9]\\d*)$",
                "description": "Physical slot number, used in MQTT topics as output/{SocketNumber}/..."
              },
              "kind": {
                "enum": [
                  "Switch",
                  "Input",
                  null
                ],
                "description": "What the IO is: a Switch it can command, or an Input it reads. Null for a socket type the model has no kind for."
              },
              "deviceAvailability": {
                "enum": [
                  "Online",
                  "Unresponsive",
                  "Offline"
                ],
                "description": "Availability of the owning device. A value from a device that is not Online is the last one it sent, not the current one."
              },
              "deviceAvailabilitySince": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the owning device entered that state. Null if it was never judged."
              },
              "properties": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "property": {
                      "enum": [
                        "ActivePower",
                        "Temperature",
                        "Humidity",
                        "Energy",
                        "PulseCount",
                        "SwitchState",
                        "ContactState",
                        "AlarmState",
                        "Availability"
                      ],
                      "description": "What the value is of."
                    },
                    "value": true,
                    "at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When the device reported it."
                    }
                  },
                  "required": [
                    "property",
                    "value",
                    "at"
                  ]
                },
                "description": "Latest value of everything this IO reports. A property the IO has never published is absent rather than null."
              }
            },
            "required": [
              "id",
              "deviceId",
              "name",
              "socketNumber",
              "kind",
              "deviceAvailability",
              "deviceAvailabilitySince",
              "properties"
            ]
          }
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/device"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "device.v1.list",
      "summary": "List devices, optionally scoped to an organization.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "nameFilter",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Case-insensitive substring to filter devices by name."
          }
        },
        {
          "name": "macFilter",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Case-insensitive substring to filter devices by MAC address."
          }
        },
        {
          "name": "availability",
          "required": false,
          "schema": {
            "enum": [
              "Online",
              "Unresponsive",
              "Offline",
              null
            ],
            "default": null,
            "description": "Keep only devices in this state. A device never heard from counts as Offline."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of the device."
                  },
                  "mac": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Device MAC address."
                  },
                  "mqttBase": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Derived identifier used in MQTT topics, e.g. \"PowerBOX4KE24a42c3a6fcf\". A client that connects to the broker itself addresses the device by this."
                  },
                  "organizationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "locationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "driver": {
                    "type": "string",
                    "description": "Key of the driver that speaks to this device: what translates its messages and encodes its commands."
                  },
                  "availability": {
                    "enum": [
                      "Online",
                      "Unresponsive",
                      "Offline"
                    ],
                    "description": "Online, Unresponsive (it sends messages but did not report a commanded IO in time) or Offline (silent past its keepalive window, or never heard from)."
                  },
                  "availabilitySince": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the device entered that state. Null if it was never judged."
                  },
                  "properties": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "property": {
                          "enum": [
                            "ActivePower",
                            "Temperature",
                            "Humidity",
                            "Energy",
                            "PulseCount",
                            "SwitchState",
                            "ContactState",
                            "AlarmState",
                            "Availability"
                          ],
                          "description": "What the value is of."
                        },
                        "value": true,
                        "at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the device reported it."
                        }
                      },
                      "required": [
                        "property",
                        "value",
                        "at"
                      ]
                    },
                    "description": "Latest value of everything the device reports about itself, if anything."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "mac",
                  "mqttBase",
                  "organizationId",
                  "locationId",
                  "driver",
                  "availability",
                  "availabilitySince",
                  "properties"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/device"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "dashboard.v1.create",
      "summary": "Create a dashboard in a Location.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "locationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "name",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Display name."
          }
        },
        {
          "name": "config",
          "required": false,
          "schema": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "version": {
                "enum": [
                  "1"
                ],
                "description": "Document version. Only \"1\" exists."
              },
              "widgets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "type"
                  ],
                  "anyOf": [
                    {
                      "properties": {
                        "type": {
                          "const": "alertList"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "bookmarks"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "$ref": "#/properties/widgets/items/anyOf/0/properties/config/properties/items",
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "deviceList"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "$ref": "#/properties/widgets/items/anyOf/0/properties/config/properties/items",
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "io"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "$ref": "#/properties/widgets/items/anyOf/0/properties/config/properties/items",
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "text"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "contents": {
                              "type": "string"
                            },
                            "imageSize": {
                              "enum": [
                                "sm",
                                "md",
                                "lg"
                              ]
                            },
                            "imageObjectId": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Object key of the image, as dashboard.v1.image.createUpload issued it."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "contents",
                            "imageSize",
                            "imageObjectId",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    }
                  ]
                },
                "description": "The widgets, in the order they are drawn."
              }
            },
            "required": [
              "version",
              "widgets"
            ],
            "additionalProperties": false,
            "default": null,
            "description": "The configuration document: { version: \"1\", widgets: [...] }. Omit to start empty."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            }
          },
          "required": [
            "id"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "dashboard.v1.delete",
      "summary": "Delete a dashboard and everything filed under it.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "dashboard.v1.duplicate",
      "summary": "Copy a dashboard, optionally into another Location.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "locationId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "name",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Name for the copy; omit for \"<original> (copy)\"."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            }
          },
          "required": [
            "id"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "dashboard.v1.get",
      "summary": "Read a dashboard: its name, Location, configuration and version.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": "string",
              "description": "Display name."
            },
            "locationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "organizationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "config": {
              "type": "object",
              "properties": {
                "version": {
                  "enum": [
                    "1"
                  ],
                  "description": "Document version. Only \"1\" exists."
                },
                "widgets": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "anyOf": [
                      {
                        "properties": {
                          "type": {
                            "const": "alertList"
                          },
                          "config": {
                            "type": "object",
                            "properties": {
                              "title": {
                                "type": "string"
                              },
                              "items": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                              },
                              "width": {
                                "enum": [
                                  "full",
                                  "1/2",
                                  "1/3",
                                  "2/3"
                                ],
                                "description": "Share of the page's row the widget takes."
                              }
                            },
                            "required": [
                              "title",
                              "items",
                              "width"
                            ],
                            "additionalProperties": false
                          },
                          "id": {
                            "type": "string",
                            "description": "Unique within the document; the client's own."
                          }
                        },
                        "required": [
                          "config",
                          "id"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "properties": {
                          "type": {
                            "const": "bookmarks"
                          },
                          "config": {
                            "type": "object",
                            "properties": {
                              "title": {
                                "type": "string"
                              },
                              "items": {
                                "$ref": "#/properties/config/properties/widgets/items/anyOf/0/properties/config/properties/items",
                                "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                              },
                              "width": {
                                "enum": [
                                  "full",
                                  "1/2",
                                  "1/3",
                                  "2/3"
                                ],
                                "description": "Share of the page's row the widget takes."
                              }
                            },
                            "required": [
                              "title",
                              "items",
                              "width"
                            ],
                            "additionalProperties": false
                          },
                          "id": {
                            "type": "string",
                            "description": "Unique within the document; the client's own."
                          }
                        },
                        "required": [
                          "config",
                          "id"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "properties": {
                          "type": {
                            "const": "deviceList"
                          },
                          "config": {
                            "type": "object",
                            "properties": {
                              "title": {
                                "type": "string"
                              },
                              "items": {
                                "$ref": "#/properties/config/properties/widgets/items/anyOf/0/properties/config/properties/items",
                                "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                              },
                              "width": {
                                "enum": [
                                  "full",
                                  "1/2",
                                  "1/3",
                                  "2/3"
                                ],
                                "description": "Share of the page's row the widget takes."
                              }
                            },
                            "required": [
                              "title",
                              "items",
                              "width"
                            ],
                            "additionalProperties": false
                          },
                          "id": {
                            "type": "string",
                            "description": "Unique within the document; the client's own."
                          }
                        },
                        "required": [
                          "config",
                          "id"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "properties": {
                          "type": {
                            "const": "io"
                          },
                          "config": {
                            "type": "object",
                            "properties": {
                              "title": {
                                "type": "string"
                              },
                              "items": {
                                "$ref": "#/properties/config/properties/widgets/items/anyOf/0/properties/config/properties/items",
                                "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                              },
                              "width": {
                                "enum": [
                                  "full",
                                  "1/2",
                                  "1/3",
                                  "2/3"
                                ],
                                "description": "Share of the page's row the widget takes."
                              }
                            },
                            "required": [
                              "title",
                              "items",
                              "width"
                            ],
                            "additionalProperties": false
                          },
                          "id": {
                            "type": "string",
                            "description": "Unique within the document; the client's own."
                          }
                        },
                        "required": [
                          "config",
                          "id"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "properties": {
                          "type": {
                            "const": "text"
                          },
                          "config": {
                            "type": "object",
                            "properties": {
                              "contents": {
                                "type": "string"
                              },
                              "imageSize": {
                                "enum": [
                                  "sm",
                                  "md",
                                  "lg"
                                ]
                              },
                              "imageObjectId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Object key of the image, as dashboard.v1.image.createUpload issued it."
                              },
                              "width": {
                                "enum": [
                                  "full",
                                  "1/2",
                                  "1/3",
                                  "2/3"
                                ],
                                "description": "Share of the page's row the widget takes."
                              }
                            },
                            "required": [
                              "contents",
                              "imageSize",
                              "imageObjectId",
                              "width"
                            ],
                            "additionalProperties": false
                          },
                          "id": {
                            "type": "string",
                            "description": "Unique within the document; the client's own."
                          }
                        },
                        "required": [
                          "config",
                          "id"
                        ],
                        "additionalProperties": false
                      }
                    ]
                  },
                  "description": "The widgets, in the order they are drawn."
                }
              },
              "required": [
                "version",
                "widgets"
              ],
              "additionalProperties": false,
              "description": "The configuration document: { version, widgets }."
            },
            "createdAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When the dashboard was created."
            },
            "version": {
              "type": [
                "string",
                "null"
              ],
              "description": "Opaque token to echo back when saving; a save against a stale version is refused. Compare it as text and never interpret it."
            },
            "mayManage": {
              "type": "boolean",
              "description": "Whether the caller may rename, re-arrange, move or delete it."
            }
          },
          "required": [
            "id",
            "name",
            "locationId",
            "organizationId",
            "config",
            "createdAt",
            "version",
            "mayManage"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ]
    },
    {
      "name": "dashboard.v1.image.createUpload",
      "summary": "Issue a URL for uploading one text-widget image straight to storage.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "fileName",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Original file name; only the recognisable part of it is kept."
          }
        },
        {
          "name": "contentType",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Content type of the file, e.g. image/png. It is part of the signature."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "imageObjectId": {
              "type": "string",
              "description": "Object key to write into the text widget's imageObjectId once the upload succeeds."
            },
            "uploadUrl": {
              "type": "string",
              "format": "uri",
              "description": "PUT the file here with exactly the Content-Type that was asked for; any other header is refused by the bucket. No credentials, so do not log it."
            },
            "expiresAt": {
              "type": "string",
              "format": "date-time",
              "description": "After this the URL is refused and a new one has to be asked for."
            }
          },
          "required": [
            "imageObjectId",
            "uploadUrl",
            "expiresAt"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ]
    },
    {
      "name": "dashboard.v1.list",
      "summary": "List dashboards, optionally scoped to an organization or a Location.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "locationId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": "string",
                    "description": "Display name."
                  },
                  "locationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "organizationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "createdAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the dashboard was created."
                  },
                  "version": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Opaque token to echo back when saving; a save against a stale version is refused. Compare it as text and never interpret it."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "locationId",
                  "organizationId",
                  "createdAt",
                  "version"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "dashboard.v1.move",
      "summary": "Move a dashboard into another Location.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "locationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ]
    },
    {
      "name": "dashboard.v1.resolve",
      "summary": "Name, live state and the caller's own rights for everything a dashboard references.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "devices": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "locationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "availability": {
                    "enum": [
                      "Online",
                      "Unresponsive",
                      "Offline"
                    ],
                    "description": "Online, Unresponsive or Offline."
                  },
                  "availabilitySince": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When it entered that state, or null if it was never judged."
                  },
                  "mayControl": {
                    "type": "boolean",
                    "description": "Whether the caller may switch this device's IOs."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "locationId",
                  "availability",
                  "availabilitySince",
                  "mayControl"
                ]
              },
              "description": "Devices named by deviceList widgets."
            },
            "ios": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "kind": {
                    "enum": [
                      "Switch",
                      "Input",
                      null
                    ],
                    "description": "What the IO is, or null for a socket type the model has no kind for."
                  },
                  "deviceId": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "deviceName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name of that device."
                  },
                  "properties": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "property": {
                          "enum": [
                            "ActivePower",
                            "Temperature",
                            "Humidity",
                            "Energy",
                            "PulseCount",
                            "SwitchState",
                            "ContactState",
                            "AlarmState",
                            "Availability"
                          ],
                          "description": "What the value is of."
                        },
                        "value": true,
                        "at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the device reported it."
                        }
                      },
                      "required": [
                        "property",
                        "value",
                        "at"
                      ]
                    },
                    "description": "Latest value of everything this IO reports."
                  },
                  "mayControl": {
                    "type": "boolean",
                    "description": "Whether the caller may switch it."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "kind",
                  "deviceId",
                  "deviceName",
                  "properties",
                  "mayControl"
                ]
              },
              "description": "Device IOs named by io widgets."
            },
            "alerts": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "Whether the rule is evaluated at all."
                  },
                  "state": {
                    "enum": [
                      "Ok",
                      "PendingFiring",
                      "Firing",
                      "PendingRecovery",
                      null
                    ],
                    "description": "Current state, or null if the rule has never been evaluated."
                  },
                  "stateChangedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When it entered that state."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "isActive",
                  "state",
                  "stateChangedAt"
                ]
              },
              "description": "Alert rules named by alertList widgets."
            },
            "bookmarks": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "path": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Full path in the Location tree."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "path"
                ]
              },
              "description": "Locations and dashboards named by bookmarks widgets."
            },
            "unavailable": {
              "type": "array",
              "description": "Ids the dashboard references that the caller cannot reach. Render the item as unavailable.",
              "items": {
                "type": "string",
                "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
              }
            }
          },
          "required": [
            "devices",
            "ios",
            "alerts",
            "bookmarks",
            "unavailable"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ]
    },
    {
      "name": "dashboard.v1.update",
      "summary": "Rename a dashboard, replace its widgets, or both, guarded by the version read.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "version",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The version token read from dashboard.v1.get, echoed back exactly. A save against a stale version is refused. Compare it as text and never interpret it."
          }
        },
        {
          "name": "name",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "New display name; omit to leave it alone."
          }
        },
        {
          "name": "config",
          "required": false,
          "schema": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "version": {
                "enum": [
                  "1"
                ],
                "description": "Document version. Only \"1\" exists."
              },
              "widgets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "type"
                  ],
                  "anyOf": [
                    {
                      "properties": {
                        "type": {
                          "const": "alertList"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "bookmarks"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "$ref": "#/properties/widgets/items/anyOf/0/properties/config/properties/items",
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "deviceList"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "$ref": "#/properties/widgets/items/anyOf/0/properties/config/properties/items",
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "io"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "items": {
                              "$ref": "#/properties/widgets/items/anyOf/0/properties/config/properties/items",
                              "description": "Entity ids. A bookmarks widget takes devices, device IOs, Locations and dashboards."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "title",
                            "items",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "properties": {
                        "type": {
                          "const": "text"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "contents": {
                              "type": "string"
                            },
                            "imageSize": {
                              "enum": [
                                "sm",
                                "md",
                                "lg"
                              ]
                            },
                            "imageObjectId": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Object key of the image, as dashboard.v1.image.createUpload issued it."
                            },
                            "width": {
                              "enum": [
                                "full",
                                "1/2",
                                "1/3",
                                "2/3"
                              ],
                              "description": "Share of the page's row the widget takes."
                            }
                          },
                          "required": [
                            "contents",
                            "imageSize",
                            "imageObjectId",
                            "width"
                          ],
                          "additionalProperties": false
                        },
                        "id": {
                          "type": "string",
                          "description": "Unique within the document; the client's own."
                        }
                      },
                      "required": [
                        "config",
                        "id"
                      ],
                      "additionalProperties": false
                    }
                  ]
                },
                "description": "The widgets, in the order they are drawn."
              }
            },
            "required": [
              "version",
              "widgets"
            ],
            "additionalProperties": false,
            "default": null,
            "description": "Replacement configuration document; omit to leave it alone."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "version": {
              "type": "string",
              "description": "The version to send with the next save."
            }
          },
          "required": [
            "version"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/dashboard"
        }
      ]
    },
    {
      "name": "alert.v1.create",
      "summary": "Create an alert rule in a Location.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "locationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "name",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Display name."
          }
        },
        {
          "name": "triggers",
          "required": true,
          "schema": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "target": {
                  "type": "string",
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                },
                "property": {
                  "enum": [
                    "ActivePower",
                    "Temperature",
                    "Humidity",
                    "Energy",
                    "PulseCount",
                    "SwitchState",
                    "ContactState",
                    "AlarmState",
                    "Availability"
                  ],
                  "description": "What it watches on the target."
                },
                "condition": {
                  "type": "object",
                  "properties": {
                    "operator": {
                      "enum": [
                        "Gt",
                        "Lt",
                        "Gte",
                        "Lte",
                        "Eq",
                        "Neq"
                      ],
                      "description": "How the reported value is compared. Availability and the three states take Eq or Neq only."
                    },
                    "value": {
                      "oneOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "string",
                          "enum": [
                            "Online",
                            "Offline"
                          ]
                        }
                      ]
                    }
                  },
                  "required": [
                    "operator",
                    "value"
                  ],
                  "description": "The condition the watched value is held to."
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "default": null,
                  "description": "Display name; omit for \"Trigger N\"."
                },
                "id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                }
              },
              "required": [
                "target",
                "property",
                "condition"
              ]
            },
            "description": "At least one. All must match at once for the rule to fire."
          }
        },
        {
          "name": "actions",
          "required": true,
          "schema": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "type"
              ],
              "anyOf": [
                {
                  "properties": {
                    "type": {
                      "const": "email"
                    },
                    "addresses": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "At least one address."
                    },
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "addresses",
                    "notifyOn"
                  ],
                  "description": "Emails a list of addresses, CC'd into one message."
                },
                {
                  "properties": {
                    "type": {
                      "const": "roleEmail"
                    },
                    "roleId": true,
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "roleId",
                    "notifyOn"
                  ],
                  "description": "Emails everyone holding a role in the rule's organization, resolved when it sends."
                },
                {
                  "properties": {
                    "type": {
                      "const": "organizationDefaultEmail"
                    },
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "notifyOn"
                  ],
                  "description": "Emails the organization's default alarm address, resolved when it sends."
                },
                {
                  "properties": {
                    "type": {
                      "const": "webhook"
                    },
                    "url": {
                      "type": "string",
                      "description": "An absolute http or https URL."
                    },
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "url",
                    "notifyOn"
                  ],
                  "description": "POSTs the event to a URL."
                }
              ]
            },
            "description": "Who it notifies; may be empty."
          }
        },
        {
          "name": "description",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Optional description."
          }
        },
        {
          "name": "isActive",
          "required": false,
          "schema": {
            "type": "boolean",
            "default": true,
            "description": "Whether it starts switched on."
          }
        },
        {
          "name": "fireAfterSeconds",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Seconds the triggers stay matched before the rule fires."
          }
        },
        {
          "name": "recoverAfterSeconds",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Seconds the triggers stay unmatched before the rule recovers."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name."
            },
            "description": {
              "type": [
                "string",
                "null"
              ],
              "description": "Description."
            },
            "isActive": {
              "type": "boolean",
              "description": "Whether it is switched on."
            },
            "locationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "organizationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "state": {
              "enum": [
                "Ok",
                "PendingFiring",
                "Firing",
                "PendingRecovery",
                "Paused",
                null
              ],
              "description": "The state it is in now."
            },
            "stateChangedAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When it entered its stored state."
            },
            "fireAfterSeconds": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Seconds the triggers stay matched before the rule fires."
            },
            "recoverAfterSeconds": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Seconds the triggers stay unmatched before the rule recovers."
            },
            "createdTime": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When it was created."
            },
            "triggers": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "target": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "targetName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name of the target; null when the caller cannot see it."
                  },
                  "targetAccess": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "view": {
                        "type": "boolean",
                        "description": "The caller's role may see the object."
                      },
                      "control": {
                        "type": "boolean",
                        "description": "The caller's role may operate it: switch IOs, trigger resets."
                      },
                      "manage": {
                        "type": "boolean",
                        "description": "The caller's role may change it: rename, move, reconfigure, delete."
                      }
                    },
                    "required": [
                      "view",
                      "control",
                      "manage"
                    ],
                    "description": "The caller's own access row for the target."
                  },
                  "property": {
                    "enum": [
                      "ActivePower",
                      "Temperature",
                      "Humidity",
                      "Energy",
                      "PulseCount",
                      "SwitchState",
                      "ContactState",
                      "AlarmState",
                      "Availability",
                      null
                    ],
                    "description": "What it watches on the target."
                  },
                  "condition": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "operator": {
                        "enum": [
                          "Gt",
                          "Lt",
                          "Gte",
                          "Lte",
                          "Eq",
                          "Neq"
                        ],
                        "description": "How the reported value is compared. Availability and the three states take Eq or Neq only."
                      },
                      "value": {
                        "oneOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "boolean"
                          },
                          {
                            "type": "string",
                            "enum": [
                              "Online",
                              "Offline"
                            ]
                          }
                        ]
                      }
                    },
                    "required": [
                      "operator",
                      "value"
                    ],
                    "description": "The condition, or null where the stored one cannot be expressed."
                  },
                  "state": {
                    "enum": [
                      "Ok",
                      "Firing",
                      null
                    ],
                    "description": "Whether the condition holds right now."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "target",
                  "targetName",
                  "targetAccess",
                  "property",
                  "condition",
                  "state"
                ]
              },
              "description": "Its triggers, in the order they were created."
            },
            "actions": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "type"
                ],
                "anyOf": [
                  {
                    "properties": {
                      "type": {
                        "const": "email"
                      },
                      "addresses": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "At least one address."
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "addresses",
                      "notifyOn"
                    ],
                    "description": "Emails a list of addresses, CC'd into one message."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "roleEmail"
                      },
                      "roleId": true,
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "roleId",
                      "notifyOn"
                    ],
                    "description": "Emails everyone holding a role in the rule's organization, resolved when it sends."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "organizationDefaultEmail"
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "notifyOn"
                    ],
                    "description": "Emails the organization's default alarm address, resolved when it sends."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "webhook"
                      },
                      "url": {
                        "type": "string",
                        "description": "An absolute http or https URL."
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "url",
                      "notifyOn"
                    ],
                    "description": "POSTs the event to a URL."
                  }
                ]
              },
              "description": "Its actions, in the order they were created. A stored action this API cannot express is left out."
            },
            "version": {
              "type": "string",
              "description": "The version to send with the next alert.v1.update."
            },
            "access": {
              "type": "object",
              "properties": {
                "view": {
                  "type": "boolean",
                  "description": "The caller's role may see the object."
                },
                "control": {
                  "type": "boolean",
                  "description": "The caller's role may operate it: switch IOs, trigger resets."
                },
                "manage": {
                  "type": "boolean",
                  "description": "The caller's role may change it: rename, move, reconfigure, delete."
                }
              },
              "required": [
                "view",
                "control",
                "manage"
              ],
              "description": "The caller's own access row for the rule."
            }
          },
          "required": [
            "id",
            "name",
            "description",
            "isActive",
            "locationId",
            "organizationId",
            "state",
            "stateChangedAt",
            "fireAfterSeconds",
            "recoverAfterSeconds",
            "createdTime",
            "triggers",
            "actions",
            "version",
            "access"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ]
    },
    {
      "name": "alert.v1.delete",
      "summary": "Delete an alert rule with its history and queued notifications.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ]
    },
    {
      "name": "alert.v1.get",
      "summary": "Read an alert rule: its triggers, actions, state and version.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name."
            },
            "description": {
              "type": [
                "string",
                "null"
              ],
              "description": "Description."
            },
            "isActive": {
              "type": "boolean",
              "description": "Whether it is switched on."
            },
            "locationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "organizationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "state": {
              "enum": [
                "Ok",
                "PendingFiring",
                "Firing",
                "PendingRecovery",
                "Paused",
                null
              ],
              "description": "The state it is in now."
            },
            "stateChangedAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When it entered its stored state."
            },
            "fireAfterSeconds": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Seconds the triggers stay matched before the rule fires."
            },
            "recoverAfterSeconds": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Seconds the triggers stay unmatched before the rule recovers."
            },
            "createdTime": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When it was created."
            },
            "triggers": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "target": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "targetName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name of the target; null when the caller cannot see it."
                  },
                  "targetAccess": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "view": {
                        "type": "boolean",
                        "description": "The caller's role may see the object."
                      },
                      "control": {
                        "type": "boolean",
                        "description": "The caller's role may operate it: switch IOs, trigger resets."
                      },
                      "manage": {
                        "type": "boolean",
                        "description": "The caller's role may change it: rename, move, reconfigure, delete."
                      }
                    },
                    "required": [
                      "view",
                      "control",
                      "manage"
                    ],
                    "description": "The caller's own access row for the target."
                  },
                  "property": {
                    "enum": [
                      "ActivePower",
                      "Temperature",
                      "Humidity",
                      "Energy",
                      "PulseCount",
                      "SwitchState",
                      "ContactState",
                      "AlarmState",
                      "Availability",
                      null
                    ],
                    "description": "What it watches on the target."
                  },
                  "condition": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "operator": {
                        "enum": [
                          "Gt",
                          "Lt",
                          "Gte",
                          "Lte",
                          "Eq",
                          "Neq"
                        ],
                        "description": "How the reported value is compared. Availability and the three states take Eq or Neq only."
                      },
                      "value": {
                        "oneOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "boolean"
                          },
                          {
                            "type": "string",
                            "enum": [
                              "Online",
                              "Offline"
                            ]
                          }
                        ]
                      }
                    },
                    "required": [
                      "operator",
                      "value"
                    ],
                    "description": "The condition, or null where the stored one cannot be expressed."
                  },
                  "state": {
                    "enum": [
                      "Ok",
                      "Firing",
                      null
                    ],
                    "description": "Whether the condition holds right now."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "target",
                  "targetName",
                  "targetAccess",
                  "property",
                  "condition",
                  "state"
                ]
              },
              "description": "Its triggers, in the order they were created."
            },
            "actions": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "type"
                ],
                "anyOf": [
                  {
                    "properties": {
                      "type": {
                        "const": "email"
                      },
                      "addresses": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "At least one address."
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "addresses",
                      "notifyOn"
                    ],
                    "description": "Emails a list of addresses, CC'd into one message."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "roleEmail"
                      },
                      "roleId": true,
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "roleId",
                      "notifyOn"
                    ],
                    "description": "Emails everyone holding a role in the rule's organization, resolved when it sends."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "organizationDefaultEmail"
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "notifyOn"
                    ],
                    "description": "Emails the organization's default alarm address, resolved when it sends."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "webhook"
                      },
                      "url": {
                        "type": "string",
                        "description": "An absolute http or https URL."
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "url",
                      "notifyOn"
                    ],
                    "description": "POSTs the event to a URL."
                  }
                ]
              },
              "description": "Its actions, in the order they were created. A stored action this API cannot express is left out."
            },
            "version": {
              "type": "string",
              "description": "The version to send with the next alert.v1.update."
            },
            "access": {
              "type": "object",
              "properties": {
                "view": {
                  "type": "boolean",
                  "description": "The caller's role may see the object."
                },
                "control": {
                  "type": "boolean",
                  "description": "The caller's role may operate it: switch IOs, trigger resets."
                },
                "manage": {
                  "type": "boolean",
                  "description": "The caller's role may change it: rename, move, reconfigure, delete."
                }
              },
              "required": [
                "view",
                "control",
                "manage"
              ],
              "description": "The caller's own access row for the rule."
            }
          },
          "required": [
            "id",
            "name",
            "description",
            "isActive",
            "locationId",
            "organizationId",
            "state",
            "stateChangedAt",
            "fireAfterSeconds",
            "recoverAfterSeconds",
            "createdTime",
            "triggers",
            "actions",
            "version",
            "access"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ]
    },
    {
      "name": "alert.v1.history.list",
      "summary": "List a rule's incidents, newest first: when each fired, when and how it ended.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "firedAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the rule fired."
                  },
                  "endedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the incident ended; null while it is open."
                  },
                  "endedBy": {
                    "enum": [
                      "Recovered",
                      "SwitchedOff",
                      null
                    ],
                    "description": "How it ended: Recovered or SwitchedOff; null while it is open."
                  },
                  "triggers": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "triggerId": {
                          "type": "string",
                          "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                          "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                        },
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Its name at fire time."
                        },
                        "state": {
                          "enum": [
                            "Ok",
                            "Firing",
                            null
                          ],
                          "description": "Its state at fire time."
                        }
                      },
                      "required": [
                        "triggerId",
                        "name",
                        "state"
                      ]
                    },
                    "description": "Each trigger as it was when the rule fired."
                  }
                },
                "required": [
                  "id",
                  "firedAt",
                  "endedAt",
                  "endedBy",
                  "triggers"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ]
    },
    {
      "name": "alert.v1.list",
      "summary": "List alert rules, optionally scoped to an organization or one Location.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "orgId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "locationId",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "page",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Zero-based page index."
          }
        },
        {
          "name": "pageSize",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Page size; a non-positive value uses the server default (50, max 200)."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "Whether it is switched on."
                  },
                  "state": {
                    "enum": [
                      "Ok",
                      "PendingFiring",
                      "Firing",
                      "PendingRecovery",
                      "Paused",
                      null
                    ],
                    "description": "The state it is in now."
                  },
                  "locationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "organizationId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "triggerCount": {
                    "type": [
                      "string",
                      "integer"
                    ],
                    "pattern": "^-?(?:0|[1-9]\\d*)$",
                    "description": "How many triggers it has."
                  },
                  "actionCount": {
                    "type": [
                      "string",
                      "integer"
                    ],
                    "pattern": "^-?(?:0|[1-9]\\d*)$",
                    "description": "How many actions it has."
                  },
                  "createdTime": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When it was created."
                  },
                  "access": {
                    "type": "object",
                    "properties": {
                      "view": {
                        "type": "boolean",
                        "description": "The caller's role may see the object."
                      },
                      "control": {
                        "type": "boolean",
                        "description": "The caller's role may operate it: switch IOs, trigger resets."
                      },
                      "manage": {
                        "type": "boolean",
                        "description": "The caller's role may change it: rename, move, reconfigure, delete."
                      }
                    },
                    "required": [
                      "view",
                      "control",
                      "manage"
                    ],
                    "description": "The caller's own access row for it."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "isActive",
                  "state",
                  "locationId",
                  "organizationId",
                  "triggerCount",
                  "actionCount",
                  "createdTime",
                  "access"
                ]
              },
              "description": "The items on this page."
            },
            "totalCount": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Total number of items matching the request across all pages."
            },
            "pageIndex": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Zero-based index of the returned page."
            },
            "pageSize": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of items per page actually applied."
            }
          },
          "required": [
            "items",
            "totalCount",
            "pageIndex",
            "pageSize"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ]
    },
    {
      "name": "alert.v1.move",
      "summary": "File an alert rule under another Location.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "locationId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    },
    {
      "name": "alert.v1.setActive",
      "summary": "Switch an alert rule on or off.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "isActive",
          "required": true,
          "schema": {
            "type": "boolean",
            "description": "True switches it on, false switches it off."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ]
    },
    {
      "name": "alert.v1.update",
      "summary": "Write the whole rule except its Location and switch, guarded by the version read.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "version",
          "required": true,
          "schema": {
            "type": "string",
            "description": "The version read from alert.v1.get, echoed back exactly. A save against a stale version is refused. Compare it as text and never interpret it."
          }
        },
        {
          "name": "name",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Display name."
          }
        },
        {
          "name": "triggers",
          "required": true,
          "schema": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "target": {
                  "type": "string",
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                },
                "property": {
                  "enum": [
                    "ActivePower",
                    "Temperature",
                    "Humidity",
                    "Energy",
                    "PulseCount",
                    "SwitchState",
                    "ContactState",
                    "AlarmState",
                    "Availability"
                  ],
                  "description": "What it watches on the target."
                },
                "condition": {
                  "type": "object",
                  "properties": {
                    "operator": {
                      "enum": [
                        "Gt",
                        "Lt",
                        "Gte",
                        "Lte",
                        "Eq",
                        "Neq"
                      ],
                      "description": "How the reported value is compared. Availability and the three states take Eq or Neq only."
                    },
                    "value": {
                      "oneOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "string",
                          "enum": [
                            "Online",
                            "Offline"
                          ]
                        }
                      ]
                    }
                  },
                  "required": [
                    "operator",
                    "value"
                  ],
                  "description": "The condition the watched value is held to."
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "default": null,
                  "description": "Display name; omit for \"Trigger N\"."
                },
                "id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                  "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                }
              },
              "required": [
                "target",
                "property",
                "condition"
              ]
            },
            "description": "The whole trigger list. An entry with an id updates that trigger, one without is new, and a stored trigger left out is deleted."
          }
        },
        {
          "name": "actions",
          "required": true,
          "schema": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "type"
              ],
              "anyOf": [
                {
                  "properties": {
                    "type": {
                      "const": "email"
                    },
                    "addresses": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "At least one address."
                    },
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "addresses",
                    "notifyOn"
                  ],
                  "description": "Emails a list of addresses, CC'd into one message."
                },
                {
                  "properties": {
                    "type": {
                      "const": "roleEmail"
                    },
                    "roleId": true,
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "roleId",
                    "notifyOn"
                  ],
                  "description": "Emails everyone holding a role in the rule's organization, resolved when it sends."
                },
                {
                  "properties": {
                    "type": {
                      "const": "organizationDefaultEmail"
                    },
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "notifyOn"
                  ],
                  "description": "Emails the organization's default alarm address, resolved when it sends."
                },
                {
                  "properties": {
                    "type": {
                      "const": "webhook"
                    },
                    "url": {
                      "type": "string",
                      "description": "An absolute http or https URL."
                    },
                    "notifyOn": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "Fired",
                          "Recovered"
                        ]
                      },
                      "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                    },
                    "id": {
                      "default": null
                    }
                  },
                  "required": [
                    "url",
                    "notifyOn"
                  ],
                  "description": "POSTs the event to a URL."
                }
              ]
            },
            "description": "The whole action list, matched by id as the triggers are."
          }
        },
        {
          "name": "description",
          "required": false,
          "schema": {
            "type": [
              "string",
              "null"
            ],
            "default": null,
            "description": "Description; omit to clear it."
          }
        },
        {
          "name": "fireAfterSeconds",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Seconds the triggers stay matched before the rule fires."
          }
        },
        {
          "name": "recoverAfterSeconds",
          "required": false,
          "schema": {
            "type": [
              "string",
              "integer"
            ],
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "default": 0,
            "description": "Seconds the triggers stay unmatched before the rule recovers."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "description": "Display name."
            },
            "description": {
              "type": [
                "string",
                "null"
              ],
              "description": "Description."
            },
            "isActive": {
              "type": "boolean",
              "description": "Whether it is switched on."
            },
            "locationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "organizationId": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            },
            "state": {
              "enum": [
                "Ok",
                "PendingFiring",
                "Firing",
                "PendingRecovery",
                "Paused",
                null
              ],
              "description": "The state it is in now."
            },
            "stateChangedAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When it entered its stored state."
            },
            "fireAfterSeconds": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Seconds the triggers stay matched before the rule fires."
            },
            "recoverAfterSeconds": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Seconds the triggers stay unmatched before the rule recovers."
            },
            "createdTime": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When it was created."
            },
            "triggers": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Display name."
                  },
                  "target": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
                    "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
                  },
                  "targetName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Name of the target; null when the caller cannot see it."
                  },
                  "targetAccess": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "view": {
                        "type": "boolean",
                        "description": "The caller's role may see the object."
                      },
                      "control": {
                        "type": "boolean",
                        "description": "The caller's role may operate it: switch IOs, trigger resets."
                      },
                      "manage": {
                        "type": "boolean",
                        "description": "The caller's role may change it: rename, move, reconfigure, delete."
                      }
                    },
                    "required": [
                      "view",
                      "control",
                      "manage"
                    ],
                    "description": "The caller's own access row for the target."
                  },
                  "property": {
                    "enum": [
                      "ActivePower",
                      "Temperature",
                      "Humidity",
                      "Energy",
                      "PulseCount",
                      "SwitchState",
                      "ContactState",
                      "AlarmState",
                      "Availability",
                      null
                    ],
                    "description": "What it watches on the target."
                  },
                  "condition": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "operator": {
                        "enum": [
                          "Gt",
                          "Lt",
                          "Gte",
                          "Lte",
                          "Eq",
                          "Neq"
                        ],
                        "description": "How the reported value is compared. Availability and the three states take Eq or Neq only."
                      },
                      "value": {
                        "oneOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "boolean"
                          },
                          {
                            "type": "string",
                            "enum": [
                              "Online",
                              "Offline"
                            ]
                          }
                        ]
                      }
                    },
                    "required": [
                      "operator",
                      "value"
                    ],
                    "description": "The condition, or null where the stored one cannot be expressed."
                  },
                  "state": {
                    "enum": [
                      "Ok",
                      "Firing",
                      null
                    ],
                    "description": "Whether the condition holds right now."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "target",
                  "targetName",
                  "targetAccess",
                  "property",
                  "condition",
                  "state"
                ]
              },
              "description": "Its triggers, in the order they were created."
            },
            "actions": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "type"
                ],
                "anyOf": [
                  {
                    "properties": {
                      "type": {
                        "const": "email"
                      },
                      "addresses": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "At least one address."
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "addresses",
                      "notifyOn"
                    ],
                    "description": "Emails a list of addresses, CC'd into one message."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "roleEmail"
                      },
                      "roleId": true,
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "roleId",
                      "notifyOn"
                    ],
                    "description": "Emails everyone holding a role in the rule's organization, resolved when it sends."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "organizationDefaultEmail"
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "notifyOn"
                    ],
                    "description": "Emails the organization's default alarm address, resolved when it sends."
                  },
                  {
                    "properties": {
                      "type": {
                        "const": "webhook"
                      },
                      "url": {
                        "type": "string",
                        "description": "An absolute http or https URL."
                      },
                      "notifyOn": {
                        "type": "array",
                        "items": {
                          "enum": [
                            "Fired",
                            "Recovered"
                          ]
                        },
                        "description": "Which transitions it runs on: Fired, Recovered, or both. At least one."
                      },
                      "id": {
                        "default": null
                      }
                    },
                    "required": [
                      "url",
                      "notifyOn"
                    ],
                    "description": "POSTs the event to a URL."
                  }
                ]
              },
              "description": "Its actions, in the order they were created. A stored action this API cannot express is left out."
            },
            "version": {
              "type": "string",
              "description": "The version to send with the next alert.v1.update."
            },
            "access": {
              "type": "object",
              "properties": {
                "view": {
                  "type": "boolean",
                  "description": "The caller's role may see the object."
                },
                "control": {
                  "type": "boolean",
                  "description": "The caller's role may operate it: switch IOs, trigger resets."
                },
                "manage": {
                  "type": "boolean",
                  "description": "The caller's role may change it: rename, move, reconfigure, delete."
                }
              },
              "required": [
                "view",
                "control",
                "manage"
              ],
              "description": "The caller's own access row for the rule."
            }
          },
          "required": [
            "id",
            "name",
            "description",
            "isActive",
            "locationId",
            "organizationId",
            "state",
            "stateChangedAt",
            "fireAfterSeconds",
            "recoverAfterSeconds",
            "createdTime",
            "triggers",
            "actions",
            "version",
            "access"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/alert"
        }
      ]
    },
    {
      "name": "subscription.v1.alert.subscribe",
      "summary": "Watch alert rules for state changes.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "ids",
          "required": true,
          "schema": {
            "type": "array",
            "description": "Ids of the alert rules to watch. At least one is required.",
            "items": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            }
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "subscriptionId": {
              "type": "string",
              "description": "Opaque id identifying this subscription; pass it to subscription.v1.unsubscribe."
            }
          },
          "required": [
            "subscriptionId"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/subscription"
        }
      ]
    },
    {
      "name": "subscription.v1.device.subscribe",
      "summary": "Watch devices, and optionally everything their IOs report.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "ids",
          "required": true,
          "schema": {
            "type": "array",
            "description": "Ids of the devices to watch. At least one is required.",
            "items": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            }
          }
        },
        {
          "name": "includeIos",
          "required": false,
          "schema": {
            "type": "boolean",
            "default": false,
            "description": "Also deliver subscription.ioEvent for every IO of these devices that the caller can see now; an IO added later is not included. False watches the devices themselves only, which is availability; name the IOs separately to watch some of them."
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "subscriptionId": {
              "type": "string",
              "description": "Opaque id identifying this subscription; pass it to subscription.v1.unsubscribe."
            }
          },
          "required": [
            "subscriptionId"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/subscription"
        }
      ]
    },
    {
      "name": "subscription.v1.io.subscribe",
      "summary": "Watch individual device IOs.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "ids",
          "required": true,
          "schema": {
            "type": "array",
            "description": "Ids of the device IOs to watch. At least one is required.",
            "items": {
              "type": "string",
              "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
              "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
            }
          }
        }
      ],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "subscriptionId": {
              "type": "string",
              "description": "Opaque id identifying this subscription; pass it to subscription.v1.unsubscribe."
            }
          },
          "required": [
            "subscriptionId"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/subscription"
        }
      ]
    },
    {
      "name": "subscription.v1.unsubscribe",
      "summary": "Cancel one subscription, whatever it covers. Cancelling an unknown id succeeds.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "subscriptionId",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Subscription id returned by a prior subscribe call."
          }
        }
      ],
      "tags": [
        {
          "$ref": "#/components/tags/subscription"
        }
      ]
    },
    {
      "name": "subscription.v1.unsubscribeAll",
      "summary": "Cancel every subscription this connection holds.",
      "paramStructure": "by-name",
      "params": [],
      "result": {
        "name": "result",
        "required": true,
        "schema": {
          "type": "object",
          "properties": {
            "removed": {
              "type": [
                "string",
                "integer"
              ],
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "description": "Number of subscriptions that were cancelled."
            }
          },
          "required": [
            "removed"
          ]
        }
      },
      "tags": [
        {
          "$ref": "#/components/tags/subscription"
        }
      ],
      "x-unsupported": {
        "marker": "⛔",
        "badge": "UNSUPPORTED",
        "color": "#dc2626",
        "headline": "⛔ Unsupported — experimental",
        "body": "No one requested this endpoint. It is purely experimental: it may be faulty, and it could change or disappear without notice. A signed-in user can call it only while their experimental access is enabled: the first call opens a one-hour window, after which support has to enable it again."
      },
      "x-badges": [
        {
          "name": "UNSUPPORTED",
          "position": "before",
          "color": "#dc2626"
        }
      ]
    }
  ],
  "servers": [
    {
      "name": "App WebSocket",
      "url": "/api/app/ws",
      "summary": "Upgrade a request to this path; the whole session is one connection."
    }
  ],
  "components": {
    "tags": {
      "auth": {
        "name": "auth",
        "x-displayName": "Authentication",
        "description": "Every connection opens here. Until `auth.v1.authenticate` succeeds any other call is refused, and the connection is closed once its deadline passes. Access tokens come from the REST surface.\n\nCalling it again with a fresh token extends the connection, whose deadline is the token's own expiry. It cannot switch identity — open a new connection for that."
      },
      "user": {
        "name": "user",
        "x-displayName": "Account",
        "description": "The signed-in account itself: who it is, the addresses it can be reached at, and the preferences that decide what the app opens with. These calls always act on the connection's own account — none of them names a user."
      },
      "organization": {
        "name": "organization",
        "x-displayName": "Organizations",
        "description": "Organizations own the devices, Locations and users a caller can reach, and are the unit permissions are granted on. One the caller has no role in is absent from a listing rather than marked inaccessible.\n\nWho belongs to one, and what the roles they hold may do, are separate reads behind separate permissions: a member the caller may not enumerate is not the same as an organization they cannot see."
      },
      "location": {
        "name": "location",
        "x-displayName": "Locations",
        "description": "Locations arrange an organization's devices, dashboards and alert rules into a tree. Each one is returned with its full resolved path, so a client does not have to walk parents to render one."
      },
      "device": {
        "name": "device",
        "x-displayName": "Devices and IOs",
        "description": "NETIO devices and their IOs — the individually switchable, individually metered outlets. Everything here is filtered to what the caller may see.\n\n`device.v1.io.control` is the only call on this surface that reaches physical hardware. Watching a device or an IO change is the `subscription` category."
      },
      "dashboard": {
        "name": "dashboard",
        "x-displayName": "Dashboards",
        "description": "A dashboard is a named page of widgets filed into a Location. It holds nothing of its own: every widget names a device, an IO, an alert rule, a Location or another dashboard.\n\nDrawing one takes two calls. `dashboard.v1.get` answers the configuration, which is ids; `dashboard.v1.resolve` answers what those ids name, their live state and what the caller may do with each. Keeping the page current is the client's own subscribe calls, over the ids it just read."
      },
      "alert": {
        "name": "alert",
        "x-displayName": "Alerts",
        "description": "An alert rule watches devices and IOs and notifies someone when all its triggers match at once. A rule is written whole: `alert.v1.update` takes every trigger and action, matched to the stored ones by id, against the version `alert.v1.get` answered. Switching a rule on or off is `alert.v1.setActive`, and needs no version.\n\nA rule's state is Ok, PendingFiring, Firing, PendingRecovery or Paused. Paused means the engine cannot trust its input, so the rule neither fires nor recovers until it can. Watching the state live is `subscription.v1.alert.subscribe`."
      },
      "subscription": {
        "name": "subscription",
        "x-displayName": "Subscriptions",
        "description": "Live updates. One call per kind of resource — devices, device IOs, alert rules — each taking a list of ids. The client decides what it watches, from ids a read already gave it: nothing here reads a dashboard's configuration on the client's behalf.\n\nUpdates arrive as `subscription.deviceEvent`, `subscription.ioEvent` and `subscription.alertEvent`. A device subscription can ask for its IOs' events too, so a page showing a whole device needs one call rather than one per outlet — and a page showing only which devices are online is not made to receive them."
      }
    },
    "errors": {
      "methodNotFound": {
        "code": -32601,
        "message": "No handler is registered for that method name."
      },
      "invalidParams": {
        "code": -32602,
        "message": "Params failed schema validation; the offending fields are in data.validationErrors."
      },
      "internalError": {
        "code": -32603,
        "message": "The handler threw. Nothing about the cause is disclosed to the caller."
      },
      "notFound": {
        "code": 1001,
        "message": "No such resource, or none visible."
      },
      "unauthenticated": {
        "code": 1002,
        "message": "The connection is not authenticated, or the token was rejected. The connection is then closed."
      },
      "forbidden": {
        "code": 1003,
        "message": "Authenticated, but the caller's role is short a permission."
      },
      "validationError": {
        "code": 1004,
        "message": "Params are valid JSON and match the schema, but were rejected on their meaning."
      },
      "conflict": {
        "code": 1006,
        "message": "The object changed since the caller read it. Re-read it and re-apply the change; nothing is merged automatically."
      },
      "experimentalDisabled": {
        "code": 1005,
        "message": "The method is unsupported and experimental access is not enabled for the caller."
      }
    }
  },
  "x-tag-order": [
    "auth",
    "user",
    "organization",
    "location",
    "device",
    "dashboard",
    "alert",
    "subscription"
  ],
  "x-notifications": [
    {
      "name": "subscription.deviceEvent",
      "summary": "Pushed when a subscribed device reports something about itself.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "subscriptionId",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Subscription id this event belongs to."
          }
        },
        {
          "name": "deviceId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "property",
          "required": true,
          "schema": {
            "enum": [
              "ActivePower",
              "Temperature",
              "Humidity",
              "Energy",
              "PulseCount",
              "SwitchState",
              "ContactState",
              "AlarmState",
              "Availability"
            ],
            "description": "What changed."
          }
        },
        {
          "name": "value",
          "required": true,
          "schema": true
        },
        {
          "name": "at",
          "required": true,
          "schema": {
            "type": "string",
            "format": "date-time",
            "description": "When the device reported it. For Availability, when the device entered the state."
          }
        }
      ],
      "description": "Arrives for as long as the subscription lives, which is as long as the connection does. One subscription id can cover several devices, so read the payload's own deviceId rather than the subscription's to tell them apart."
    },
    {
      "name": "subscription.ioEvent",
      "summary": "Pushed when a subscribed device IO changes state or reports a measurement.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "subscriptionId",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Subscription id this event belongs to."
          }
        },
        {
          "name": "deviceId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "ioId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "property",
          "required": true,
          "schema": {
            "enum": [
              "ActivePower",
              "Temperature",
              "Humidity",
              "Energy",
              "PulseCount",
              "SwitchState",
              "ContactState",
              "AlarmState",
              "Availability"
            ],
            "description": "What changed."
          }
        },
        {
          "name": "value",
          "required": true,
          "schema": true
        },
        {
          "name": "at",
          "required": true,
          "schema": {
            "type": "string",
            "format": "date-time",
            "description": "When the device reported it. For Availability, when the device entered the state."
          }
        }
      ],
      "description": "Also arrives for a subscription on the IO's device that asked to include them. Carries both ids, so a page can route it either way."
    },
    {
      "name": "subscription.alertEvent",
      "summary": "Pushed when a subscribed alert rule enters a new state.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "subscriptionId",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Subscription id this event belongs to."
          }
        },
        {
          "name": "alertId",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-z]{3}_([0-9A-Za-z]{7}|[0-9A-Za-z]{22})$",
            "description": "Typed opaque id: a three-letter kind prefix, an underscore and the payload, e.g. dev_3kTMd8n. Compare ids as strings; never derive anything from the payload."
          }
        },
        {
          "name": "state",
          "required": true,
          "schema": {
            "enum": [
              "Ok",
              "PendingFiring",
              "Firing",
              "PendingRecovery",
              "Paused"
            ],
            "description": "The state the rule is now in. Paused while the engine cannot trust its input."
          }
        },
        {
          "name": "at",
          "required": true,
          "schema": {
            "type": "string",
            "format": "date-time",
            "description": "When it entered that state."
          }
        }
      ],
      "description": "Carries the state the rule is now in, not only fired and recovered, so a widget showing a pending grace period stays accurate. One subscription id can cover several rules, so read the payload's own alertId."
    },
    {
      "name": "connection.closing",
      "summary": "Sent immediately before the server closes the connection.",
      "paramStructure": "by-name",
      "params": [
        {
          "name": "reason",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Why the server is closing the connection: \"auth_timeout\", \"token_expired\", \"session_revoked\", \"unauthenticated_access\", or \"message_too_large\"."
          }
        }
      ],
      "description": "The last frame on the socket. It carries the reason, which is the only way to tell an expired token from a server shutdown."
    }
  ]
}