{
  "openapi": "3.1.0",
  "info": {
    "title": "Buzzer API",
    "version": "1.0.0",
    "description": "Public BuzzerAPI /v1 contract. Access rules can be created before subscribing; they open the door only after a BuzzerAPI subscription, a provisioned virtual number, and completed building setup. Webhook deliveries are described under webhooks. This reference covers the public API only."
  },
  "servers": [
    {
      "url": "https://api.buzzerapi.com",
      "description": "BuzzerAPI endpoint. Check /v1/health for current availability."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "operationId": "get_v1_health",
        "summary": "Check service health",
        "description": "Health is public and not rate limited; success does not establish account readiness. openapi_url and docs_url point at this contract and the AI agent guide.",
        "security": [],
        "x-required-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "operationId": "get_v1_openapi_json",
        "summary": "Fetch the OpenAPI contract",
        "description": "Public, not rate limited, and sent with Access-Control-Allow-Origin: *. Redirects to the website copy of this contract (https://www.buzzerapi.com/openapi.json in production). Follow the redirect.",
        "security": [],
        "x-required-scopes": [],
        "parameters": [],
        "responses": {
          "302": {
            "description": "Found. Follow Location to the OpenAPI 3.1 JSON document.",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "description": "",
                  "format": "uri"
                },
                "description": "Absolute URL of openapi.json on the website."
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/plans": {
      "get": {
        "operationId": "get_v1_plans",
        "summary": "Read live public prices",
        "description": "Only BuzzerAPI weekly and yearly are listed. Each building uses one subscription unit at the selected price. Public cache max-age=60, shared cache max-age=300.",
        "security": [],
        "x-required-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plans"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/otp": {
      "post": {
        "operationId": "post_v1_auth_otp",
        "summary": "Request email sign-in code",
        "description": "Sign-in codes are single-use, expire, and are rate- and attempt-limited. On 429, wait the Retry-After seconds. Delivery is not proof that the account already exists.",
        "security": [],
        "x-required-scopes": [],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtpChallenge"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_EMAIL, LINKED_ACCOUNT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: OTP_RATE_LIMIT, AUTH_RATE_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/verify": {
      "post": {
        "operationId": "post_v1_auth_verify",
        "summary": "Verify email and start a website session",
        "description": "Website sign-in only: purpose must be web, otherwise 400 WEBSITE_SIGN_IN_REQUIRED is returned before the code is consumed. Creates the account if needed. Returns a 12-hour website session key that the website keeps server-side; it is not a browser-storage recommendation. AI agents use keys created on the account page instead. Never disclose apiKey.",
        "security": [],
        "x-required-scopes": [],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebSessionCredential"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_EMAIL, LINKED_ACCOUNT, WEBSITE_SIGN_IN_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: INVALID_OTP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: AUTH_RATE_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/key": {
      "delete": {
        "operationId": "delete_v1_auth_key",
        "summary": "Revoke the current credential",
        "description": "No extra scope required. Any key can revoke itself; subsequent use fails authentication. AI agent keys survive website sign-out.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Revoked"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: AUTH_RATE_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/keys": {
      "post": {
        "operationId": "post_v1_auth_keys",
        "summary": "Create an AI agent key",
        "description": "Website session only; AI agent keys get 403 WEB_SESSION_REQUIRED. Keys can be issued before payment with access, setup, billing, and optional building scopes. keys:write or any other unlisted scope returns 400 INVALID_KEY_OPTIONS. At most 20 active AI agent keys (409 KEY_LIMIT). Live access and building mutations still require the corresponding subscription. AI agent keys are independent of website session expiry.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "keys:write"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentCredential"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_KEY_OPTIONS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, WEB_SESSION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: KEY_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: AUTH_RATE_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_v1_auth_keys",
        "summary": "List every key on the account",
        "description": "Website session only; AI agent keys get 403 WEB_SESSION_REQUIRED. Returns every active key: website sign-ins (type web_session, current true for the calling session) and AI agent keys (type agent). Newest first. Excludes revoked keys, but can include expired ones. No secrets or pagination.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "keys:write"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyList"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, WEB_SESSION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: AUTH_RATE_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/keys/{id}": {
      "delete": {
        "operationId": "delete_v1_auth_keys_id",
        "summary": "Revoke any key on the account",
        "description": "Website session only; AI agent keys get 403 WEB_SESSION_REQUIRED. Revokes any active key on the account, including other website sign-ins and the calling session itself, which is then signed out. A malformed ID returns 400 INVALID_ID; an unknown ID or another account's key returns 404 NOT_FOUND.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "keys:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyRevoked"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, WEB_SESSION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: AUTH_RATE_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/keys/revoke-others": {
      "post": {
        "operationId": "post_v1_auth_keys_revoke-others",
        "summary": "Revoke every other key",
        "description": "Website session only; AI agent keys get 403 WEB_SESSION_REQUIRED. Revokes every active key on the account except the calling website session, including AI agent keys and other website sign-ins. No request body. Returns the number of keys revoked.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "keys:write"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeysRevoked"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, WEB_SESSION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: AUTH_RATE_LIMIT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account": {
      "get": {
        "operationId": "get_v1_account",
        "summary": "Inspect account readiness",
        "description": "Account-level response; building header does not select another account. Subscription active and a recorded buzz do not prove physical entry.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: ACCOUNT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: FETCH_FAILED, INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/phone": {
      "get": {
        "operationId": "get_v1_account_phone",
        "summary": "Read forwarding phone status",
        "description": "Website session only; AI agent keys and linked-building keys get 403 WEB_SESSION_REQUIRED. A phone verified earlier appears here without another SMS.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read",
          "keys:write"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneStatus"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, WEB_SESSION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: ACCOUNT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/phone/verification": {
      "post": {
        "operationId": "post_v1_account_phone_verification",
        "summary": "Send forwarding phone code",
        "description": "Website session only (403 WEB_SESSION_REQUIRED otherwise). Requires an active subscription and an owned provisioned virtual number. Explicit request only. Verification codes are single-use, expire, and are rate- and attempt-limited, and changing an existing phone is also limited. On 429, wait the Retry-After seconds.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read",
          "keys:write"
        ],
        "x-active-subscription-required": true,
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhoneVerificationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneCodeSent"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_PHONE_NUMBER.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, WEB_SESSION_REQUIRED, SUBSCRIPTION_REQUIRED, NUMBER_NOT_PROVISIONED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: ACCOUNT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: ALREADY_VERIFIED, PHONE_IN_USE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: PHONE_CODE_RATE_LIMIT, PHONE_CHANGE_LIMIT, RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: PHONE_CODE_SEND_FAILED, INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/phone/confirmation": {
      "post": {
        "operationId": "post_v1_account_phone_confirmation",
        "summary": "Confirm forwarding phone code",
        "description": "Website session only (403 WEB_SESSION_REQUIRED otherwise). Requires an active subscription and owned provisioned virtual number. Codes expire and are attempt-limited; after PHONE_CODE_EXPIRED or PHONE_CODE_ATTEMPTS, request a new code.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read",
          "keys:write"
        ],
        "x-active-subscription-required": true,
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhoneConfirmationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneStatus"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_PHONE_CODE, PHONE_CODE_EXPIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, WEB_SESSION_REQUIRED, SUBSCRIPTION_REQUIRED, NUMBER_NOT_PROVISIONED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: ACCOUNT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: PHONE_IN_USE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: PHONE_CODE_ATTEMPTS, PHONE_CHANGE_LIMIT, RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/plans": {
      "get": {
        "operationId": "get_v1_billing_plans",
        "summary": "Read authenticated price catalog",
        "description": "Same catalog as public plans; no active subscription required.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "billing:write"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plans"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/checkout": {
      "get": {
        "operationId": "get_v1_billing_checkout",
        "summary": "Recover latest checkout",
        "description": "Read after a timeout. complete means hosted checkout completed; recheck account.subscription.status and setup. preparing means retry original plan and request ID. Once the subscription a completed checkout created is canceled, this reports none and a new checkout can start.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "billing:write"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkout"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: CHECKOUT_UNAVAILABLE, INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post_v1_billing_checkout",
        "summary": "Start or recover hosted checkout",
        "description": "Parent account only. Any existing subscription on the account, including a past_due one, returns SUBSCRIPTION_EXISTS; manage it in the portal. A request ID whose checkout ended failed replays that result; use a new Idempotency-Key to try again. A new request ID for the same plan returns the existing open checkout with its original request_id. One pending checkout: same plan reuses it. Requesting another plan while the existing session is still open (unpaid) expires that session and starts the new plan; a checkout that is being prepared or was already paid returns CHECKOUT_EXISTS. A completed checkout keeps blocking new ones until its subscription is canceled; then start again with a new Idempotency-Key. Same request ID with another plan conflicts. Hosted checkout returns to the account page with checkout=success after payment or checkout=cancel when the customer backs out. CHECKOUT_RECONCILIATION_REQUIRED means an earlier checkout needs support to resolve; contact support instead of purchasing again. No card details accepted by this API.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "billing:write"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "",
              "pattern": "^[a-zA-Z0-9_-]{16,100}$"
            },
            "description": "Stable identifier for this action: 16 to 100 letters, digits, hyphens, or underscores. Reuse the identical body and key after a timeout. Keys never expire."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkout"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkout"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, IDEMPOTENCY_KEY_REQUIRED, INVALID_PLAN.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PARENT_BILLING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: ACCOUNT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: IDEMPOTENCY_CONFLICT, SUBSCRIPTION_EXISTS, CHECKOUT_EXISTS, CHECKOUT_PENDING, CHECKOUT_RECONCILIATION_REQUIRED, PLAN_UNAVAILABLE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: CHECKOUT_UNAVAILABLE, INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/checkout/{id}/expire": {
      "post": {
        "operationId": "post_v1_billing_checkout_id_expire",
        "summary": "Expire unpaid checkout",
        "description": "Open sessions can be expired; already-expired sessions succeed. Completed checkout returns 409 SUBSCRIPTION_EXISTS. This does not cancel a subscription.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "billing:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Stripe checkout session ID."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutExpired"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: SUBSCRIPTION_EXISTS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: CHECKOUT_UNAVAILABLE, INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/portal": {
      "post": {
        "operationId": "post_v1_billing_portal",
        "summary": "Open hosted billing management",
        "description": "Parent account with an existing billing customer. No request body.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "billing:write"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Portal"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PARENT_BILLING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: CUSTOMER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/buildings/{buildingId}/settings": {
      "get": {
        "operationId": "get_v1_buildings_buildingId_settings",
        "summary": "Read one building’s tone and greeting",
        "description": "Read without an active subscription. Invited members can inspect their number but cannot change its settings; editable is false for them. Unprovisioned buildings return virtual_number/unlock_tone/version null and default greeting values. The path explicitly selects the building; no header is needed.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read"
        ],
        "parameters": [
          {
            "name": "buildingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Explicit building ID from GET /v1/buildings. Child keys can only use their own building. An optional X-Buzzer-Building-Id header must agree with the path."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingSettings"
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "description": "Quoted opaque 64-hex snapshot token."
                },
                "description": "Present for provisioned numbers. Supply as If-Match on PATCH. Also exposed without quotes in response.version."
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_BUILDING, INVALID_BUILDING_CONTEXT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patch_v1_buildings_buildingId_settings",
        "summary": "Update one building’s tone and greeting",
        "description": "Requires ownership and a provisioned number. Invited members get 403 NUMBER_OWNER_REQUIRED; check editable from GET first. Primary-building writes need no active subscription; linked-building writes require an active BuzzerAPI subscription. Supply the ETag from GET in If-Match. Strong and weak quoted tokens are accepted. Tone and greeting are saved together in one transaction. Omitted fields stay unchanged; unknown fields, nulls and empty patch objects are rejected. Greeting strings preserve whitespace and must be shorter than 120 JavaScript UTF-16 code units (astral characters count twice). A shared legacy greeting is copied so siblings remain unchanged. One competing save wins; others return 409 SETTINGS_VERSION_CONFLICT. After a timeout or conflict, read back and review before deciding to retry; no automatic mutation retry.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "setup:write"
        ],
        "parameters": [
          {
            "name": "buildingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Explicit building ID from GET /v1/buildings. Child keys can only use their own building. An optional X-Buzzer-Building-Id header must agree with the path."
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Quoted ETag from this building’s GET.",
              "pattern": "^(?:W/)?\"[a-f0-9]{64}\"$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuildingSettingsPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingSettingsUpdated"
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "description": "Quoted opaque 64-hex snapshot token."
                },
                "description": "Present for provisioned numbers. Supply as If-Match on PATCH. Also exposed without quotes in response.version."
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_BUILDING, INVALID_BUILDING_CONTEXT, INVALID_TONE, INVALID_SETTINGS, INVALID_GREETING.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, MULTI_BUILDING_REQUIRED, NUMBER_OWNER_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND, NUMBER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: SETTINGS_VERSION_CONFLICT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "Precondition required. Codes: SETTINGS_VERSION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/buildings/{buildingId}/setup": {
      "get": {
        "operationId": "get_v1_buildings_buildingId_setup",
        "summary": "Inspect one building’s setup",
        "description": "No subscription required for inspection. previous_buzz_recorded requires a successful access-rule unlock; forwarded calls and owner self-calls do not count. It is not proof of physical door release. The path explicitly selects the building; no header is needed.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read"
        ],
        "parameters": [
          {
            "name": "buildingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Explicit building ID from GET /v1/buildings. Child keys can only use their own building. An optional X-Buzzer-Building-Id header must agree with the path."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingSetup"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_BUILDING, INVALID_BUILDING_CONTEXT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/buildings": {
      "get": {
        "operationId": "get_v1_buildings",
        "summary": "List accessible buildings",
        "description": "No pagination. Ordered by creation time then ID. Parent sees primary and children; child sees only itself.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Buildings"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY, AUTHENTICATION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post_v1_buildings",
        "summary": "Execute quoted building addition",
        "description": "Parent account only; do not send building header. Supply the matching unexpired quote and stable request ID. Stale inventory/billing requires a fresh preview before execution. Replay returns stored operation. HTTP 202 is not completion. running: poll the operation; reconciliation_required: contact support with its ID and do not create another request. Only one building change runs at a time per account (409 BUILDING_BUSY). An addition that fully rolled back (no number purchased, building removed, billing restored) returns 409 BUILDING_ADD_FAILED, is recorded as failed, and lets another building change start; replaying it returns the same error.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read",
          "buildings:write"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "",
              "pattern": "^[a-zA-Z0-9_-]{16,100}$"
            },
            "description": "Stable identifier for this action: 16 to 100 letters, digits, hyphens, or underscores. Reuse the identical body and key after a timeout. Keys never expire."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingOperation"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingOperation"
                }
              }
            }
          },
          "202": {
            "description": "Pending or uncertain: inspect status and next_action.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingOperation"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, IDEMPOTENCY_KEY_REQUIRED, INVALID_QUOTE, INVALID_BUILDING_CONTEXT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment failed. Codes: PAYMENT_FAILED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PARENT_BUILDING_KEY_REQUIRED, MULTI_BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: INVALID_QUOTE, IDEMPOTENCY_CONFLICT, QUOTE_EXPIRED, QUOTE_STALE, BUILDING_BUSY, BUILDING_BILLING_MISMATCH, BUILDING_ADD_FAILED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/buildings/preview": {
      "post": {
        "operationId": "post_v1_buildings_preview",
        "summary": "Preview addition or removal",
        "description": "Parent account only; do not send building header. Requires an active BuzzerAPI subscription with a matching billed quantity, maximum 20 buildings including primary. Each additional building adds one unit at the same subscription price. Preview purchases nothing, creates a 15-minute quote and invoice snapshot. US and Canadian addresses are supported; a Canadian building receives a Canadian number. Previews are still issued while another operation awaits reconciliation, but cannot be executed until it is resolved. Removal cannot target primary; review release/deletion effects.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read",
          "buildings:write"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuildingPreview"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingOperation"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_BUILDING_INPUT, INVALID_BUILDING_CONTEXT, INVALID_PHONE_NUMBER, PHONE_VERIFICATION_REQUIRED, FORWARDING_PHONE_NOT_VERIFIED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PARENT_BUILDING_KEY_REQUIRED, MULTI_BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: BUILDING_LIMIT, BUILDING_BILLING_MISMATCH.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/buildings/{id}": {
      "delete": {
        "operationId": "delete_v1_buildings_id",
        "summary": "Execute quoted building removal",
        "description": "Parent account only; do not send building header. Supply the matching unexpired quote and stable request ID. Stale inventory/billing requires a fresh preview before execution. Replay returns stored operation. HTTP 202 is not completion. running: poll the operation; reconciliation_required: contact support with its ID and do not create another request. Only one building change runs at a time per account (409 BUILDING_BUSY). An addition that fully rolled back (no number purchased, building removed, billing restored) returns 409 BUILDING_ADD_FAILED, is recorded as failed, and lets another building change start; replaying it returns the same error. The JSON DELETE body is required. Permanently releases the number, deletes child rules/activity, revokes child keys, and reduces subscription quantity.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read",
          "buildings:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "",
              "pattern": "^[a-zA-Z0-9_-]{16,100}$"
            },
            "description": "Stable identifier for this action: 16 to 100 letters, digits, hyphens, or underscores. Reuse the identical body and key after a timeout. Keys never expire."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingOperation"
                }
              }
            }
          },
          "202": {
            "description": "Pending or uncertain: inspect status and next_action.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingOperation"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, IDEMPOTENCY_KEY_REQUIRED, INVALID_ID, INVALID_QUOTE, INVALID_BUILDING_CONTEXT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PARENT_BUILDING_KEY_REQUIRED, MULTI_BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: NOT_FOUND, BUILDING_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: INVALID_QUOTE, IDEMPOTENCY_CONFLICT, QUOTE_EXPIRED, QUOTE_STALE, BUILDING_BUSY, BUILDING_BILLING_MISMATCH.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/buildings/operations/{id}": {
      "get": {
        "operationId": "get_v1_buildings_operations_id",
        "summary": "Read building operation receipt",
        "description": "Parent-owned operation. Recovery remains available without an active subscription. A running operation that stops making progress is reported as reconciliation_required. Quotes/receipts are not erased when the quote expires.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "account:read",
          "buildings:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuildingOperation"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PARENT_BUILDING_KEY_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/unlock": {
      "post": {
        "operationId": "post_v1_unlock",
        "summary": "Create an access grant",
        "description": "No subscription or virtual number is needed: rules can be created before subscribing or connecting a building, and they start opening the door once a virtual number is connected. BuzzerAPI includes timer, passcode, and routine for every building; if the account's current plan doesn't include a rule type, creating it returns 403 PLAN_UPGRADE_REQUIRED. A timer with a future starts_at has status scheduled until then. A timer or passcode with remaining_uses lets in that many buzzes, then becomes exhausted; omit it (or send null on a passcode) for unlimited buzzes; a passcode no longer defaults to one use. A timer's window is set by exactly one of expires_in_minutes or ends_at; a passcode can take either one for an expiry, or neither to never expire. type is required and never inferred. A repeated Idempotency-Key with the same body returns 200 with the current grant and Idempotency-Replayed: true (including revoked state and current remaining_uses), never reopens it; the same key with a different body returns 409 IDEMPOTENCY_CONFLICT. Keys never expire and are scoped to the selected building.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:write"
        ],
        "parameters": [
          {
            "name": "X-Buzzer-Building-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Required when a parent account has linked buildings, even for its primary building. Omit only for a single-building account. Child keys cannot select siblings."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "",
              "pattern": "^[a-zA-Z0-9_-]{16,100}$"
            },
            "description": "Stable identifier for this action: 16 to 100 letters, digits, hyphens, or underscores. Reuse the identical body and key after a timeout. Keys never expire."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnlockCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Unlock"
                }
              }
            },
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "description": ""
                },
                "description": "On new 201: relative /v1/unlock/{id}."
              },
              "Idempotency-Replayed": {
                "schema": {
                  "const": "true"
                },
                "description": "Present on replay."
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Unlock"
                }
              }
            },
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "description": ""
                },
                "description": "On new 201: relative /v1/unlock/{id}."
              },
              "Idempotency-Replayed": {
                "schema": {
                  "const": "true"
                },
                "description": "Present on replay."
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, IDEMPOTENCY_KEY_REQUIRED, INVALID_BUILDING, INVALID_TYPE, INVALID_UNLOCK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PLAN_UPGRADE_REQUIRED, MULTI_BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: BUILDING_REQUIRED, IDEMPOTENCY_CONFLICT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_v1_unlock",
        "summary": "List access grants",
        "description": "No active subscription required. Excludes API-revoked grants. Ordered by descending ID. enabled filters by the on/off switch; status filters by what the rule does right now (status=active matches a timer within its window, a nonexpired/nonexhausted enabled passcode, or an enabled routine, not necessarily inside its schedule).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:read"
        ],
        "parameters": [
          {
            "name": "X-Buzzer-Building-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Required when a parent account has linked buildings, even for its primary building. Omit only for a single-building account. Child keys cannot select siblings."
          },
          {
            "name": "enabled",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": ""
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "scheduled",
                "inactive",
                "expired",
                "exhausted"
              ]
            },
            "description": ""
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "timer",
                "passcode",
                "routine"
              ]
            },
            "description": ""
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "description": "",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Use pagination.cursor; this endpoint uses a grant ID cursor."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnlockPage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_BUILDING, INVALID_FILTER, INVALID_TYPE, INVALID_LIMIT, INVALID_CURSOR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/unlock/{id}": {
      "get": {
        "operationId": "get_v1_unlock_id",
        "summary": "Read one access grant",
        "description": "Includes revoked grants; ownership is scoped to selected building.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:read"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          },
          {
            "name": "X-Buzzer-Building-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Required when a parent account has linked buildings, even for its primary building. Omit only for a single-building account. Child keys cannot select siblings."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Unlock"
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "description": "Quoted decimal version, e.g. \"3\", or its proxy-generated weak form W/\"3\"."
                },
                "description": "Supply this exact quoted value as If-Match when updating."
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_BUILDING, INVALID_ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND, NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patch_v1_unlock_id",
        "summary": "Update an access grant",
        "description": "Requires If-Match from GET. Strong quoted versions and proxy-generated weak ETags are accepted. Parallel updates using the same version permit one write; the others return 409 VERSION_CONFLICT. Missing/malformed version: 428 VERSION_REQUIRED. Reread, review changes, and decide whether to retry. Revoked grants cannot be reopened. remaining_uses (1 to 100) sets a new count; null removes the use limit on timers and passcodes. Turning a timer on (enabled: true) needs expires_in_minutes or ends_at, plus an optional starts_at. On a passcode, expires_in_minutes or ends_at sets a new expiry and ends_at: null removes it. No subscription or virtual number is needed on the primary building; if the account's current plan doesn't include the rule type, PLAN_UPGRADE_REQUIRED is returned except for the exact body {\"enabled\":false}. Linked-building PATCH still requires an active BuzzerAPI subscription even for deactivation. DELETE remains the downgrade cleanup path.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          },
          {
            "name": "X-Buzzer-Building-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Required when a parent account has linked buildings, even for its primary building. Omit only for a single-building account. Child keys cannot select siblings."
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Quoted version from the ETag. A weak W/\"3\" form, which proxies may add when compressing, is accepted too.",
              "pattern": "^(?:W/)?\"[0-9]+\"$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnlockUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Unlock"
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "description": "Quoted decimal version, e.g. \"3\", or its proxy-generated weak form W/\"3\"."
                },
                "description": "Supply this exact quoted value as If-Match when updating."
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_BUILDING, INVALID_ID, INVALID_UNLOCK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE, PLAN_UPGRADE_REQUIRED, MULTI_BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND, NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: BUILDING_REQUIRED, VERSION_CONFLICT, GRANT_REVOKED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "Precondition required. Codes: VERSION_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_v1_unlock_id",
        "summary": "Revoke access grant",
        "description": "No active subscription required. Soft revocation is repeatable; never erases create idempotency receipt. Missing grant is 404. Other grants may still allow access.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          },
          {
            "name": "X-Buzzer-Building-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Required when a parent account has linked buildings, even for its primary building. Omit only for a single-building account. Child keys cannot select siblings."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnlockRevoked"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_BUILDING, INVALID_ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND, NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/logs": {
      "get": {
        "operationId": "get_v1_logs",
        "summary": "Read persisted access activity",
        "description": "No active subscription required. Descending created_at then ID. since/until inclusive. Follow every cursor with unchanged filters; overlap timestamp checkpoints and deduplicate by ID to recover use events. Passcodes are withheld from logs; use an access:read key to retrieve a grant when needed. Calls forwarded to the resident appear with type call. No server streaming endpoint.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "logs:read"
        ],
        "parameters": [
          {
            "name": "X-Buzzer-Building-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Required when a parent account has linked buildings, even for its primary building. Omit only for a single-building account. Child keys cannot select siblings."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "description": "",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "ISO 8601 timestamp.",
              "format": "date-time"
            },
            "description": ""
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "ISO 8601 timestamp.",
              "format": "date-time"
            },
            "description": ""
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "unlock",
                "call"
              ]
            },
            "description": "unlock: access-rule attempts only. call: forwarded calls only. Omit for both."
          },
          {
            "name": "unlock_id",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Only entries for this access rule."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "",
              "minLength": 1,
              "maxLength": 100
            },
            "description": "Case-insensitive search of each entry's name, such as an access rule label. Matched literally; 1 to 100 characters after trimming."
          },
          {
            "name": "succeeded",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": ""
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "description": ""
            },
            "description": "Opaque base64url cursor; do not construct or decode as part of client logic."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogPage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_BUILDING, INVALID_ID, INVALID_LIMIT, INVALID_DATE, INVALID_TYPE, INVALID_QUERY, INVALID_SUCCEEDED, INVALID_CURSOR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: BUILDING_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: BUILDING_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: FETCH_FAILED, INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "post": {
        "operationId": "post_v1_webhooks",
        "summary": "Create a webhook endpoint",
        "description": "Account-level: do not send X-Buzzer-Building-Id; events carry building_id. At most 5 endpoints per account (409 WEBHOOK_LIMIT). secret is returned only by this call; store it to verify BuzzerAPI-Signature. events defaults to every event type. Endpoints can also be managed on the account page. Repeating the call with the same Idempotency-Key and body returns 200 with the original endpoint, including secret, and Idempotency-Replayed: true; a different body with that key returns 409 IDEMPOTENCY_CONFLICT.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:write"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "description": "",
              "pattern": "^[a-zA-Z0-9_-]{16,100}$"
            },
            "description": "Optional. When supplied it works like access creation: the same key and body replay the original endpoint with Idempotency-Replayed: true, and a different body returns 409 IDEMPOTENCY_CONFLICT."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            },
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "const": "true"
                },
                "description": "Present on replay."
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            },
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "const": "true"
                },
                "description": "Present on replay."
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_JSON, INVALID_WEBHOOK_URL, INVALID_WEBHOOK_EVENTS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicts with current state; inspect it before retrying. Codes: WEBHOOK_LIMIT, IDEMPOTENCY_CONFLICT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_v1_webhooks",
        "summary": "List webhook endpoints",
        "description": "Every endpoint on the account. secret is never returned here.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:read"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "operationId": "delete_v1_webhooks_id",
        "summary": "Delete a webhook endpoint",
        "description": "Stops deliveries and cancels pending retries for this endpoint. Repeating the call is harmless.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/test": {
      "post": {
        "operationId": "post_v1_webhooks_id_test",
        "summary": "Send a test event",
        "description": "Queues a webhook.test event for this endpoint with the normal signature, timeout, and retry rules. 202 means queued, not delivered.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "access:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Opaque resource ID, normally 24 hexadecimal characters.",
              "pattern": "^[a-fA-F0-9]{24}$"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted: the test delivery is queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestQueued"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request; correct the input. Codes: INVALID_ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked key. Codes: AUTH_REQUIRED, INVALID_KEY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not permitted for this key, account, or plan. Codes: INSUFFICIENT_SCOPE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found for this key or building. Codes: NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; wait for Retry-After. Codes: RATE_LIMIT_EXCEEDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "5XX": {
            "description": "Server error; retryable is true, but check a mutation's state before repeating it. Codes: INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Structured API error; see error handling and the error code catalog. Hosting/proxy failures and unknown paths can return non-JSON bodies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "headers": {
      "Retry-After": {
        "schema": {
          "type": "integer",
          "description": "",
          "minimum": 1
        },
        "description": "Number of seconds to wait before retrying. Absent on PHONE_CODE_ATTEMPTS; request a new code instead."
      },
      "RateLimit-Limit": {
        "schema": {
          "type": "integer",
          "description": ""
        },
        "description": "Requests allowed in the current window."
      },
      "RateLimit-Remaining": {
        "schema": {
          "type": "integer",
          "description": ""
        },
        "description": "Requests left in the current window."
      },
      "RateLimit-Reset": {
        "schema": {
          "type": "integer",
          "description": ""
        },
        "description": "Seconds until the window resets."
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "AI agent key created on the account page, or the website session. Required scopes are listed on each operation as x-required-scopes."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "permission_error",
                  "authentication_error",
                  "invalid_request_error",
                  "not_found_error",
                  "rate_limit_error",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string",
                "description": ""
              },
              "code": {
                "type": "string",
                "enum": [
                  "INVALID_SETTINGS",
                  "INVALID_GREETING",
                  "SETTINGS_VERSION_REQUIRED",
                  "SETTINGS_VERSION_CONFLICT",
                  "ACCOUNT_NOT_FOUND",
                  "ALREADY_VERIFIED",
                  "AUTH_RATE_LIMIT",
                  "AUTH_REQUIRED",
                  "AUTHENTICATION_REQUIRED",
                  "BUILDING_ADD_FAILED",
                  "BUILDING_BILLING_MISMATCH",
                  "BUILDING_BUSY",
                  "BUILDING_LIMIT",
                  "BUILDING_NOT_FOUND",
                  "BUILDING_REQUIRED",
                  "CHECKOUT_EXISTS",
                  "CHECKOUT_PENDING",
                  "CHECKOUT_RECONCILIATION_REQUIRED",
                  "CHECKOUT_UNAVAILABLE",
                  "CUSTOMER_NOT_FOUND",
                  "FETCH_FAILED",
                  "FORWARDING_PHONE_NOT_VERIFIED",
                  "GRANT_REVOKED",
                  "HTTPS_REQUIRED",
                  "IDEMPOTENCY_CONFLICT",
                  "IDEMPOTENCY_KEY_REQUIRED",
                  "INSUFFICIENT_SCOPE",
                  "INTERNAL_ERROR",
                  "INVALID_FILTER",
                  "INVALID_BUILDING",
                  "INVALID_BUILDING_CONTEXT",
                  "INVALID_BUILDING_INPUT",
                  "INVALID_CURSOR",
                  "INVALID_DATE",
                  "INVALID_EMAIL",
                  "INVALID_ID",
                  "INVALID_JSON",
                  "INVALID_KEY",
                  "INVALID_KEY_OPTIONS",
                  "INVALID_LIMIT",
                  "INVALID_OTP",
                  "INVALID_PHONE_CODE",
                  "INVALID_PHONE_NUMBER",
                  "INVALID_PLAN",
                  "INVALID_QUOTE",
                  "INVALID_SUCCEEDED",
                  "INVALID_TONE",
                  "INVALID_TYPE",
                  "INVALID_UNLOCK",
                  "INVALID_WEBHOOK_EVENTS",
                  "INVALID_WEBHOOK_URL",
                  "KEY_LIMIT",
                  "LINKED_ACCOUNT",
                  "MULTI_BUILDING_REQUIRED",
                  "NOT_FOUND",
                  "NUMBER_NOT_FOUND",
                  "NUMBER_OWNER_REQUIRED",
                  "NUMBER_NOT_PROVISIONED",
                  "OTP_RATE_LIMIT",
                  "PARENT_BILLING_REQUIRED",
                  "PARENT_BUILDING_KEY_REQUIRED",
                  "PAYLOAD_TOO_LARGE",
                  "PAYMENT_FAILED",
                  "PHONE_CHANGE_LIMIT",
                  "PHONE_CODE_ATTEMPTS",
                  "PHONE_CODE_EXPIRED",
                  "PHONE_CODE_RATE_LIMIT",
                  "PHONE_CODE_SEND_FAILED",
                  "PHONE_IN_USE",
                  "PHONE_VERIFICATION_REQUIRED",
                  "PLAN_UNAVAILABLE",
                  "PLAN_UPGRADE_REQUIRED",
                  "QUOTE_EXPIRED",
                  "QUOTE_STALE",
                  "RATE_LIMIT_EXCEEDED",
                  "SETUP_REQUIRED",
                  "SUBSCRIPTION_EXISTS",
                  "SUBSCRIPTION_REQUIRED",
                  "VERSION_CONFLICT",
                  "VERSION_REQUIRED",
                  "WEBHOOK_LIMIT",
                  "WEB_SESSION_REQUIRED",
                  "WEBSITE_SIGN_IN_REQUIRED"
                ],
                "description": "Stable UPPER_SNAKE_CASE code. Branch on this, not on message. New codes can be added; handle an unknown code by its HTTP status and retryable."
              },
              "retryable": {
                "type": "boolean",
                "description": "True for 429 and 5xx; does not authorize blindly repeating mutations."
              },
              "next_action": {
                "type": "string",
                "description": ""
              }
            },
            "required": [
              "type",
              "message",
              "code",
              "retryable",
              "next_action"
            ]
          },
          "requestId": {
            "type": "string",
            "description": "Also returned as X-Request-ID."
          }
        },
        "required": [
          "error",
          "requestId"
        ]
      },
      "Health": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "version": {
            "type": "string",
            "description": "Backend package version."
          },
          "uptime": {
            "type": "number",
            "description": "Process uptime in seconds."
          },
          "openapi_url": {
            "type": "string",
            "description": "Where to fetch this OpenAPI contract, such as https://www.buzzerapi.com/openapi.json.",
            "format": "uri"
          },
          "docs_url": {
            "type": "string",
            "description": "AI agent onboarding guide, such as https://www.buzzerapi.com/agents.md.",
            "format": "uri"
          }
        },
        "required": [
          "status",
          "version",
          "uptime"
        ]
      },
      "Plans": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "enum": [
                    "api_weekly",
                    "api_yearly"
                  ]
                },
                "available": {
                  "type": "boolean",
                  "description": ""
                },
                "amount": {
                  "anyOf": [
                    {
                      "type": "integer",
                      "description": "Minor currency units; do not hardcode prices."
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "currency": {
                  "type": "string",
                  "description": ""
                },
                "interval": {
                  "type": "string",
                  "description": ""
                },
                "interval_count": {
                  "type": "integer",
                  "description": ""
                },
                "access": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "timer",
                      "passcode",
                      "routine"
                    ]
                  }
                }
              },
              "required": [
                "id",
                "available",
                "amount",
                "currency",
                "access"
              ]
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "OtpRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "Trimmed and lowercased.",
            "format": "email",
            "maxLength": 254
          }
        },
        "required": [
          "email"
        ]
      },
      "OtpChallenge": {
        "type": "object",
        "properties": {
          "challenge": {
            "type": "string",
            "description": "Single-use challenge. It expires; request a new one if verification fails."
          },
          "message": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "challenge",
          "message"
        ]
      },
      "VerifyRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "",
            "format": "email"
          },
          "challenge": {
            "type": "string",
            "description": ""
          },
          "otp": {
            "type": "string",
            "description": "Six-digit email sign-in code, not a visitor code.",
            "pattern": "^[0-9]{6}$"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "web"
            ],
            "description": "Required. Email sign-in is only for the website; any other value returns 400 WEBSITE_SIGN_IN_REQUIRED."
          }
        },
        "required": [
          "email",
          "challenge",
          "otp",
          "purpose"
        ]
      },
      "WebSessionCredential": {
        "type": "object",
        "properties": {
          "apiKey": {
            "type": "string",
            "description": "12-hour website session key, returned once. Holds every scope, including keys:write. The website keeps it server-side."
          },
          "keyPrefix": {
            "type": "string",
            "description": ""
          },
          "name": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "apiKey",
          "keyPrefix",
          "name"
        ]
      },
      "KeyRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nonblank; trimmed before storage.",
            "default": "My AI agent",
            "maxLength": 120
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "account:read",
                "access:read",
                "access:write",
                "logs:read",
                "setup:write",
                "billing:write",
                "buildings:write"
              ]
            },
            "minItems": 1,
            "default": [
              "account:read",
              "access:read",
              "access:write",
              "logs:read"
            ],
            "description": "AI agent keys cannot hold keys:write; requesting it returns 400 INVALID_KEY_OPTIONS."
          },
          "expires_in_days": {
            "anyOf": [
              {
                "type": "integer",
                "description": "Optional lifetime. Defaults to no expiry.",
                "minimum": 1,
                "maximum": 90
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": false
      },
      "AgentCredential": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "api_key": {
            "type": "string",
            "description": "Returned once; store in secret settings."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "account:read",
                "access:read",
                "access:write",
                "logs:read",
                "setup:write",
                "billing:write",
                "keys:write",
                "buildings:write"
              ]
            }
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 timestamp.",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "message": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "id",
          "api_key",
          "scopes",
          "expires_at",
          "message"
        ]
      },
      "KeyList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Opaque resource ID, normally 24 hexadecimal characters.",
                  "pattern": "^[a-fA-F0-9]{24}$"
                },
                "name": {
                  "type": "string",
                  "description": ""
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "web_session",
                    "agent"
                  ],
                  "description": "web_session: a website sign-in. agent: an AI agent key created on the account page."
                },
                "scopes": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "account:read",
                      "access:read",
                      "access:write",
                      "logs:read",
                      "setup:write",
                      "billing:write",
                      "keys:write",
                      "buildings:write"
                    ]
                  }
                },
                "key_prefix": {
                  "type": "string",
                  "description": "First 12 characters of the key, for recognition only."
                },
                "created_at": {
                  "type": "string",
                  "description": "ISO 8601 timestamp.",
                  "format": "date-time"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "description": "ISO 8601 timestamp.",
                      "format": "date-time"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "last_used_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "description": "ISO 8601 timestamp.",
                      "format": "date-time"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "current": {
                  "type": "boolean",
                  "description": "True only for the website session making this request."
                }
              },
              "required": [
                "id",
                "name",
                "type",
                "scopes",
                "key_prefix",
                "created_at",
                "expires_at",
                "last_used_at",
                "current"
              ]
            },
            "description": "Every active key on the account, newest first."
          }
        },
        "required": [
          "data"
        ]
      },
      "Revoked": {
        "type": "object",
        "properties": {
          "revoked": {
            "const": true
          }
        },
        "required": [
          "revoked"
        ]
      },
      "KeyRevoked": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "revoked": {
            "const": true
          }
        },
        "required": [
          "id",
          "revoked"
        ]
      },
      "KeysRevoked": {
        "type": "object",
        "properties": {
          "revoked": {
            "type": "integer",
            "description": "Number of keys revoked.",
            "minimum": 0
          }
        },
        "required": [
          "revoked"
        ]
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "email": {
            "type": "string",
            "description": ""
          },
          "virtual_number": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "subscription": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "description": "BUZZER_API for a BuzzerAPI subscription, NONE without one. Treat any other value as not a BuzzerAPI subscription."
              },
              "status": {
                "type": "string",
                "enum": [
                  "none",
                  "active",
                  "past_due"
                ]
              }
            },
            "required": [
              "type",
              "status"
            ]
          },
          "usage": {
            "type": "object",
            "properties": {
              "total_unlocks": {
                "type": "integer",
                "description": "Recorded activity count, including failed attempts; not a physical-entry count."
              },
              "active_routines": {
                "type": "integer",
                "description": "Stored activated rules; not necessarily currently effective."
              },
              "shared_users": {
                "type": "integer",
                "description": "Number of users associated with the number."
              }
            },
            "required": [
              "total_unlocks",
              "active_routines",
              "shared_users"
            ]
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          },
          "buildings": {
            "type": "object",
            "properties": {
              "count": {
                "type": "integer",
                "description": ""
              },
              "selection_required": {
                "type": "boolean",
                "description": ""
              },
              "list_command": {
                "type": "string",
                "description": "REST request that lists buildings, such as GET /v1/buildings."
              }
            },
            "required": [
              "count",
              "selection_required",
              "list_command"
            ]
          },
          "capabilities": {
            "type": "object",
            "properties": {
              "multi_building": {
                "type": "boolean",
                "description": ""
              },
              "access_types": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "timer",
                    "passcode",
                    "routine"
                  ]
                },
                "description": "Access rule types this account can create."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "account:read",
                    "access:read",
                    "access:write",
                    "logs:read",
                    "setup:write",
                    "billing:write",
                    "keys:write",
                    "buildings:write"
                  ]
                }
              }
            },
            "required": [
              "multi_building",
              "access_types",
              "scopes"
            ]
          },
          "readiness": {
            "type": "object",
            "properties": {
              "can_create_access": {
                "type": "boolean",
                "description": "True for any key with access:write. Rules can be created before subscribing or connecting a building; they start opening the door once a virtual number is connected. Creation still validates input and the selected building."
              },
              "building_connection": {
                "type": "string",
                "enum": [
                  "not_provisioned",
                  "previous_buzz_recorded",
                  "unverified"
                ],
                "description": "previous_buzz_recorded requires a successful access-rule unlock; calls forwarded to the resident do not count."
              },
              "physical_entry_verified": {
                "const": false
              }
            },
            "required": [
              "can_create_access",
              "building_connection",
              "physical_entry_verified"
            ]
          },
          "next_actions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "description": "REST request to make next, such as GET /v1/buildings/{buildingId}/setup."
                },
                "reason": {
                  "type": "string",
                  "description": ""
                }
              },
              "required": [
                "command",
                "reason"
              ]
            }
          }
        },
        "required": [
          "id",
          "email",
          "virtual_number",
          "subscription",
          "usage",
          "created_at",
          "buildings",
          "capabilities",
          "readiness",
          "next_actions"
        ]
      },
      "PhoneStatus": {
        "type": "object",
        "properties": {
          "phone_number": {
            "anyOf": [
              {
                "type": "string",
                "description": "The owner's verified forwarding phone, or null."
              },
              {
                "type": "null"
              }
            ]
          },
          "verified": {
            "type": "boolean",
            "description": ""
          }
        },
        "required": [
          "phone_number",
          "verified"
        ]
      },
      "PhoneVerificationRequest": {
        "type": "object",
        "properties": {
          "phone_number": {
            "type": "string",
            "description": "US or Canadian resident phone in +1 E.164 format.",
            "pattern": "^\\+1[2-9][0-9]{9}$"
          }
        },
        "required": [
          "phone_number"
        ],
        "additionalProperties": false
      },
      "PhoneCodeSent": {
        "type": "object",
        "properties": {
          "sent": {
            "const": true
          },
          "phone_number": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "sent",
          "phone_number"
        ]
      },
      "PhoneConfirmationRequest": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Code received by SMS. Never log or store this code.",
            "pattern": "^[0-9]{4,10}$"
          }
        },
        "required": [
          "code"
        ],
        "additionalProperties": false
      },
      "CheckoutRequest": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "api_weekly",
              "api_yearly"
            ]
          }
        },
        "required": [
          "plan"
        ],
        "additionalProperties": false
      },
      "Checkout": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "status": {
                "const": "none"
              },
              "payment_required": {
                "const": false
              },
              "next_action": {
                "type": "string",
                "description": ""
              }
            },
            "required": [
              "status",
              "payment_required",
              "next_action"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "anyOf": [
                  {
                    "type": "string",
                    "description": "Stripe checkout session ID."
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "request_id": {
                "type": "string",
                "description": ""
              },
              "plan": {
                "type": "string",
                "enum": [
                  "api_weekly",
                  "api_yearly"
                ]
              },
              "url": {
                "anyOf": [
                  {
                    "type": "string",
                    "description": "",
                    "format": "uri"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "preparing",
                  "open",
                  "complete",
                  "expired",
                  "failed"
                ]
              },
              "payment_required": {
                "type": "boolean",
                "description": ""
              },
              "next_action": {
                "type": "string",
                "description": ""
              },
              "message": {
                "type": "string",
                "description": ""
              }
            },
            "required": [
              "id",
              "request_id",
              "plan",
              "url",
              "status",
              "payment_required",
              "next_action",
              "message"
            ]
          }
        ]
      },
      "CheckoutExpired": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": ""
          },
          "status": {
            "const": "expired"
          },
          "payment_required": {
            "const": false
          }
        },
        "required": [
          "id",
          "status",
          "payment_required"
        ]
      },
      "Portal": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Hosted Stripe billing-management URL.",
            "format": "uri"
          }
        },
        "required": [
          "url"
        ]
      },
      "BuildingGreeting": {
        "type": "object",
        "properties": {
          "custom_greeting": {
            "type": "string",
            "description": "Custom greeting. Empty uses the standard instructions. Stored exactly without trimming.",
            "maxLength": 119
          },
          "prompt_for_passcode": {
            "type": "boolean",
            "description": "Preserves the existing call-flow option; it does not create or enable access rules."
          },
          "access_granted_phrase": {
            "type": "string",
            "description": "Phrase used on release. Empty makes this phrase silent.",
            "maxLength": 119
          },
          "access_denied_phrase": {
            "type": "string",
            "description": "Phrase used on denied access. Empty makes this phrase silent.",
            "maxLength": 119
          }
        },
        "required": [
          "custom_greeting",
          "prompt_for_passcode",
          "access_granted_phrase",
          "access_denied_phrase"
        ],
        "additionalProperties": false
      },
      "BuildingGreetingPatch": {
        "type": "object",
        "properties": {
          "custom_greeting": {
            "type": "string",
            "description": "Custom greeting. Empty uses the standard instructions. Stored exactly without trimming.",
            "maxLength": 119
          },
          "prompt_for_passcode": {
            "type": "boolean",
            "description": "Preserves the existing call-flow option; it does not create or enable access rules."
          },
          "access_granted_phrase": {
            "type": "string",
            "description": "Phrase used on release. Empty makes this phrase silent.",
            "maxLength": 119
          },
          "access_denied_phrase": {
            "type": "string",
            "description": "Phrase used on denied access. Empty makes this phrase silent.",
            "maxLength": 119
          }
        },
        "additionalProperties": false,
        "minProperties": 1
      },
      "BuildingSettings": {
        "type": "object",
        "properties": {
          "building_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "virtual_number": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "unlock_tone": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "greeting": {
            "$ref": "#/components/schemas/BuildingGreeting"
          },
          "version": {
            "anyOf": [
              {
                "type": "string",
                "description": "Opaque settings snapshot token. Use the quoted ETag in If-Match; do not construct a token.",
                "pattern": "^[a-f0-9]{64}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "editable": {
            "type": "boolean",
            "description": "True when the caller owns the number and can PATCH these settings. False for invited members and unprovisioned buildings. Not part of version."
          }
        },
        "required": [
          "building_id",
          "virtual_number",
          "unlock_tone",
          "greeting",
          "version",
          "editable"
        ]
      },
      "BuildingSettingsUpdated": {
        "type": "object",
        "properties": {
          "building_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "virtual_number": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "unlock_tone": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "greeting": {
            "$ref": "#/components/schemas/BuildingGreeting"
          },
          "version": {
            "anyOf": [
              {
                "type": "string",
                "description": "Opaque settings snapshot token. Use the quoted ETag in If-Match; do not construct a token.",
                "pattern": "^[a-f0-9]{64}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "editable": {
            "type": "boolean",
            "description": "True when the caller owns the number and can PATCH these settings. False for invited members and unprovisioned buildings. Not part of version."
          },
          "physical_test_required": {
            "type": "boolean",
            "description": "True when unlock_tone was supplied. Test from the entrance yourself."
          }
        },
        "required": [
          "building_id",
          "virtual_number",
          "unlock_tone",
          "greeting",
          "version",
          "editable",
          "physical_test_required"
        ]
      },
      "BuildingSettingsPatch": {
        "type": "object",
        "properties": {
          "unlock_tone": {
            "type": "string",
            "description": "Exact building release keypress; test at the entrance.",
            "pattern": "^[0-9#*]{1,3}(?![\\s\\S])"
          },
          "greeting": {
            "$ref": "#/components/schemas/BuildingGreetingPatch"
          }
        },
        "additionalProperties": false,
        "minProperties": 1
      },
      "BuildingSetup": {
        "type": "object",
        "properties": {
          "building_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "virtual_number": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "unlock_tone": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "last_successful_buzz_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "Latest successful access-rule unlock; calls forwarded to the resident are excluded.",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "awaiting_subscription_or_provisioning",
              "previous_buzz_recorded",
              "building_setup_required"
            ]
          },
          "instructions": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "building_id",
          "virtual_number",
          "unlock_tone",
          "last_successful_buzz_at",
          "status",
          "instructions"
        ]
      },
      "Address": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "description": ""
          },
          "city": {
            "type": "string",
            "description": ""
          },
          "state": {
            "type": "string",
            "description": ""
          },
          "zip": {
            "type": "string",
            "description": ""
          },
          "country": {
            "type": "string",
            "description": ""
          }
        }
      },
      "Buildings": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Opaque resource ID, normally 24 hexadecimal characters.",
                  "pattern": "^[a-fA-F0-9]{24}$"
                },
                "label": {
                  "type": "string",
                  "description": ""
                },
                "address": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/Address"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "virtual_number": {
                  "anyOf": [
                    {
                      "type": "string",
                      "description": ""
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "is_primary": {
                  "type": "boolean",
                  "description": ""
                },
                "provisioned": {
                  "type": "boolean",
                  "description": ""
                }
              },
              "required": [
                "id",
                "label",
                "address",
                "virtual_number",
                "is_primary",
                "provisioned"
              ]
            }
          },
          "selection_required": {
            "type": "boolean",
            "description": ""
          },
          "next_action": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "data",
          "selection_required",
          "next_action"
        ]
      },
      "BuildingAddPreview": {
        "type": "object",
        "properties": {
          "action": {
            "const": "add"
          },
          "label": {
            "type": "string",
            "description": "Nonblank; trimmed.",
            "maxLength": 120
          },
          "address": {
            "type": "object",
            "properties": {
              "street": {
                "type": "string",
                "description": "",
                "maxLength": 200
              },
              "city": {
                "type": "string",
                "description": "Nonblank; trimmed.",
                "maxLength": 120
              },
              "state": {
                "type": "string",
                "description": "Two-letter US state or Canadian province (AB, BC, MB, NB, NL, NS, NT, NU, ON, PE, QC, SK, YT). Normalized uppercase.",
                "pattern": "^[A-Za-z]{2}$"
              },
              "zip": {
                "type": "string",
                "description": "US ZIP (12345 or 12345-6789) or Canadian postal code (A1A 1A1; normalized to that form).",
                "pattern": "^([0-9]{5}(-[0-9]{4})?|[A-Za-z][0-9][A-Za-z][ -]?[0-9][A-Za-z][0-9])$"
              },
              "country": {
                "type": "string",
                "enum": [
                  "US",
                  "CA"
                ],
                "description": "Defaults to CA for a Canadian postal code, otherwise US."
              }
            },
            "required": [
              "city",
              "state",
              "zip"
            ],
            "additionalProperties": false
          },
          "unlock_tone": {
            "type": "string",
            "description": "Exact building release keypress; test at the entrance.",
            "pattern": "^[0-9#*]{1,3}$"
          },
          "phone_number": {
            "type": "string",
            "description": "Resident forwarding number. Defaults to parent phone if omitted; a valid number is still required.",
            "pattern": "^\\+[1-9][0-9]{6,14}$"
          }
        },
        "required": [
          "action",
          "label",
          "address",
          "unlock_tone"
        ],
        "additionalProperties": false
      },
      "BuildingRemovePreview": {
        "type": "object",
        "properties": {
          "action": {
            "const": "remove"
          },
          "building_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          }
        },
        "required": [
          "action",
          "building_id"
        ],
        "additionalProperties": false
      },
      "BuildingPreview": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/BuildingAddPreview"
          },
          {
            "$ref": "#/components/schemas/BuildingRemovePreview"
          }
        ]
      },
      "QuoteRequest": {
        "type": "object",
        "properties": {
          "quote_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          }
        },
        "required": [
          "quote_id"
        ],
        "additionalProperties": false
      },
      "BuildingOperation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "action": {
            "type": "string",
            "enum": [
              "add",
              "remove"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "quoted",
              "expired",
              "running",
              "succeeded",
              "failed",
              "reconciliation_required"
            ]
          },
          "input": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": ""
              },
              "address": {
                "$ref": "#/components/schemas/Address"
              },
              "unlock_tone": {
                "type": "string",
                "description": ""
              },
              "phone_number": {
                "type": "string",
                "description": ""
              },
              "building_id": {
                "type": "string",
                "description": "Opaque resource ID, normally 24 hexadecimal characters.",
                "pattern": "^[a-fA-F0-9]{24}$"
              },
              "virtual_number": {
                "anyOf": [
                  {
                    "type": "string",
                    "description": ""
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "effects": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": ""
                }
              }
            },
            "description": "Add: normalized label/address/unlock_tone/phone_number. Remove: building_id/label/virtual_number/effects. Inspect the exact snapshot before execution."
          },
          "billing": {
            "type": "object",
            "properties": {
              "subscription_id": {
                "type": "string",
                "description": ""
              },
              "price_id": {
                "type": "string",
                "description": ""
              },
              "current_quantity": {
                "type": "integer",
                "description": ""
              },
              "new_quantity": {
                "type": "integer",
                "description": ""
              },
              "currency": {
                "type": "string",
                "description": ""
              },
              "next_invoice_amount_due": {
                "type": "integer",
                "description": "Entire next renewal invoice estimate in minor currency units. Read amount_due_now for the immediate building charge."
              },
              "per_building_amount": {
                "anyOf": [
                  {
                    "type": "integer",
                    "description": "Can be null for tiered pricing. Do not multiply this to reconstruct the invoice."
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "interval": {
                "type": "string",
                "description": ""
              },
              "proration_date": {
                "type": "integer",
                "description": "Quote timestamp in Unix seconds. Building quantity changes do not prorate."
              },
              "amount_due_now": {
                "type": "integer",
                "description": "Quoted immediate charge in minor currency units. Adding a building bills its full current weekly or annual term; adding during a trial ends it and bills all buildings. Zero for removal."
              },
              "charge_timing": {
                "type": "string",
                "enum": [
                  "immediate",
                  "none"
                ]
              },
              "ends_trial": {
                "type": "boolean",
                "description": "Whether adding this building ends the current trial."
              },
              "note": {
                "type": "string",
                "description": ""
              }
            },
            "required": [
              "subscription_id",
              "price_id",
              "current_quantity",
              "new_quantity",
              "currency",
              "next_invoice_amount_due",
              "per_building_amount",
              "proration_date",
              "amount_due_now",
              "charge_timing",
              "ends_trial",
              "note"
            ]
          },
          "expires_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          },
          "building_id": {
            "anyOf": [
              {
                "type": "string",
                "description": "Opaque resource ID, normally 24 hexadecimal characters.",
                "pattern": "^[a-fA-F0-9]{24}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "request_id": {
            "anyOf": [
              {
                "type": "string",
                "description": ""
              },
              {
                "type": "null"
              }
            ]
          },
          "result": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "building_id": {
                    "type": "string",
                    "description": "Opaque resource ID, normally 24 hexadecimal characters.",
                    "pattern": "^[a-fA-F0-9]{24}$"
                  },
                  "label": {
                    "type": "string",
                    "description": ""
                  },
                  "virtual_number": {
                    "type": "string",
                    "description": ""
                  },
                  "physical_test_required": {
                    "const": true
                  },
                  "deleted": {
                    "const": true
                  },
                  "released_number": {
                    "anyOf": [
                      {
                        "type": "string",
                        "description": ""
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "charge": {
                    "type": "object",
                    "properties": {
                      "invoice_id": {
                        "type": "string",
                        "description": ""
                      },
                      "amount": {
                        "type": "integer",
                        "description": "Amount collected in minor currency units."
                      },
                      "currency": {
                        "type": "string",
                        "description": ""
                      }
                    },
                    "required": [
                      "invoice_id",
                      "amount",
                      "currency"
                    ]
                  }
                },
                "required": [
                  "building_id"
                ],
                "description": "Add result: building_id, label, virtual_number, physical_test_required, charge (invoice_id, amount, currency). Remove result: building_id, deleted, released_number. Null until succeeded."
              },
              {
                "type": "null"
              }
            ]
          },
          "next_action": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "id",
          "action",
          "status",
          "input",
          "billing",
          "expires_at",
          "building_id",
          "request_id",
          "result",
          "next_action"
        ]
      },
      "TimerCreate": {
        "type": "object",
        "properties": {
          "type": {
            "const": "timer"
          },
          "label": {
            "type": "string",
            "description": "Required. 1 to 120 characters, such as who the access is for.",
            "minLength": 1,
            "maxLength": 120
          },
          "enabled": {
            "type": "boolean",
            "description": "Required. Whether the rule is on when it's created. true: it works right away (a timer with starts_at starts at that time). false: it's saved but stays off until you turn it on with PATCH."
          },
          "expires_in_minutes": {
            "type": "integer",
            "description": "Window length in minutes, 1 to 1,440 (1 day). Send this or ends_at, not both. Starts immediately unless starts_at is supplied.",
            "minimum": 1,
            "maximum": 1440
          },
          "ends_at": {
            "type": "string",
            "description": "ISO timestamp with Z or numeric timezone offset for when the window closes: in the future, after starts_at, and 1 minute to 1 day after the start (starts_at, or now). Send this or expires_in_minutes, not both. Only with enabled: true.",
            "format": "date-time"
          },
          "starts_at": {
            "type": "string",
            "description": "Optional ISO timestamp with Z or numeric timezone offset, now or later and within 1 year; a time in the past is rejected (up to 1 minute late counts as now). Only with enabled: true. Until this time the timer is enabled with status scheduled.",
            "format": "date-time"
          },
          "remaining_uses": {
            "type": "integer",
            "description": "Optional. Number of buzzes this timer lets in (1 to 100). Omit for unlimited buzzes during the window. Each release uses one; at 0 the timer becomes exhausted.",
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "type",
          "label",
          "enabled"
        ],
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "expires_in_minutes"
            ]
          },
          {
            "required": [
              "ends_at"
            ]
          }
        ],
        "dependentSchemas": {
          "starts_at": {
            "required": [
              "enabled"
            ],
            "properties": {
              "enabled": {
                "const": true
              }
            }
          },
          "ends_at": {
            "required": [
              "enabled"
            ],
            "properties": {
              "enabled": {
                "const": true
              }
            }
          }
        }
      },
      "PasscodeCreate": {
        "type": "object",
        "properties": {
          "type": {
            "const": "passcode"
          },
          "label": {
            "type": "string",
            "description": "Required. 1 to 120 characters, such as who the access is for.",
            "minLength": 1,
            "maxLength": 120
          },
          "enabled": {
            "type": "boolean",
            "description": "Required. Whether the rule is on when it's created. true: it works right away (a timer with starts_at starts at that time). false: it's saved but stays off until you turn it on with PATCH."
          },
          "access_code": {
            "type": "string",
            "description": "Omit to generate exactly four digits. Custom codes retain app compatibility: 1–4 digits except 1 alone. Preserve leading zeroes. Six-digit visitor codes are rejected.",
            "pattern": "^(?!1$)[0-9]{1,4}$"
          },
          "remaining_uses": {
            "anyOf": [
              {
                "type": "integer",
                "description": "",
                "minimum": 1,
                "maximum": 100
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional. Number of times this passcode can open the door (1 to 100). Omit it, or send null, for unlimited uses. Each release uses one; at 0 the passcode becomes exhausted."
          },
          "enter_code_with_voice": {
            "type": "boolean",
            "description": "When true, callers can speak the code aloud instead of typing it.",
            "default": false
          },
          "expires_in_minutes": {
            "type": "integer",
            "description": "Optional minutes from now until the passcode expires, 1 to 525,600 (1 year). Send this or ends_at, not both. With neither, the passcode never expires.",
            "minimum": 1,
            "maximum": 525600
          },
          "ends_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional expiry: a future ISO timestamp with Z or numeric timezone offset, no more than 1 year ahead. Send this or expires_in_minutes, not both. Omit both, or send null, for a passcode that never expires."
          }
        },
        "required": [
          "type",
          "label",
          "enabled"
        ],
        "additionalProperties": false,
        "not": {
          "required": [
            "expires_in_minutes",
            "ends_at"
          ]
        }
      },
      "RoutineCreate": {
        "type": "object",
        "properties": {
          "type": {
            "const": "routine"
          },
          "label": {
            "type": "string",
            "description": "Required. 1 to 120 characters, such as who the access is for.",
            "minLength": 1,
            "maxLength": 120
          },
          "enabled": {
            "type": "boolean",
            "description": "Required. Whether the rule is on when it's created. true: it works right away (a timer with starts_at starts at that time). false: it's saved but stays off until you turn it on with PATCH."
          },
          "days": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "Day name, case-insensitive: sunday, monday, tuesday, wednesday, thursday, friday, saturday.",
              "pattern": "^([sS][uU][nN][dD][aA][yY]|[mM][oO][nN][dD][aA][yY]|[tT][uU][eE][sS][dD][aA][yY]|[wW][eE][dD][nN][eE][sS][dD][aA][yY]|[tT][hH][uU][rR][sS][dD][aA][yY]|[fF][rR][iI][dD][aA][yY]|[sS][aA][tT][uU][rR][dD][aA][yY])(?![\\s\\S])",
              "maxLength": 9
            },
            "description": "Any combination of days, each listed once, case-insensitive. For example [\"monday\",\"wednesday\",\"friday\"] for Monday, Wednesday and Friday.",
            "minItems": 1,
            "maxItems": 7,
            "uniqueItems": true,
            "allOf": [
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[sS][uU][nN][dD][aA][yY]$",
                  "maxLength": 6
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[mM][oO][nN][dD][aA][yY]$",
                  "maxLength": 6
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[tT][uU][eE][sS][dD][aA][yY]$",
                  "maxLength": 7
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[wW][eE][dD][nN][eE][sS][dD][aA][yY]$",
                  "maxLength": 9
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[tT][hH][uU][rR][sS][dD][aA][yY]$",
                  "maxLength": 8
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[fF][rR][iI][dD][aA][yY]$",
                  "maxLength": 6
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[sS][aA][tT][uU][rR][dD][aA][yY]$",
                  "maxLength": 8
                },
                "minContains": 0,
                "maxContains": 1
              }
            ]
          },
          "start_hour_and_minutes": {
            "type": "string",
            "description": "24-hour HH:MM. end_hour_and_minutes must be later than start_hour_and_minutes on the same day; no overnight window.",
            "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
          },
          "end_hour_and_minutes": {
            "type": "string",
            "description": "24-hour HH:MM. end_hour_and_minutes must be later than start_hour_and_minutes on the same day; no overnight window.",
            "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
          },
          "timezone": {
            "type": "string",
            "description": "Valid IANA timezone, such as America/Los_Angeles."
          },
          "access_code": {
            "type": "string",
            "description": "Optional visitor code for the schedule: during its window a caller must enter this code instead of being let in on every buzz. Same 1–4 digit app-compatible validation as a passcode; not generated when omitted. No use limit or expiry.",
            "pattern": "^(?!1$)[0-9]{1,4}$"
          },
          "enter_code_with_voice": {
            "type": "boolean",
            "description": "When true, callers can speak the code aloud instead of typing it. Requires access_code.",
            "default": false
          }
        },
        "required": [
          "type",
          "label",
          "enabled",
          "days",
          "start_hour_and_minutes",
          "end_hour_and_minutes",
          "timezone"
        ],
        "additionalProperties": false,
        "dependentRequired": {
          "enter_code_with_voice": [
            "access_code"
          ]
        }
      },
      "UnlockCreate": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/TimerCreate"
          },
          {
            "$ref": "#/components/schemas/PasscodeCreate"
          },
          {
            "$ref": "#/components/schemas/RoutineCreate"
          }
        ],
        "description": "type is required and never inferred, so a missing access_code can't turn a passcode into a timer that lets anyone in. Unknown fields are rejected with 400 INVALID_UNLOCK listing the allowed fields."
      },
      "TimerUpdate": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "description": "Optional replacement label, 1 to 120 characters. It cannot be blanked.",
            "minLength": 1,
            "maxLength": 120
          },
          "enabled": {
            "type": "boolean",
            "description": "false turns the timer off and clears its window. true turns it on and requires expires_in_minutes or ends_at in the same request (plus starts_at to start later); if its uses ran out, also send remaining_uses (a count, or null for unlimited)."
          },
          "expires_in_minutes": {
            "type": "integer",
            "description": "Window length in minutes, 1 to 1,440 (1 day). Only with enabled: true; send this or ends_at, not both. The new window begins immediately, or at starts_at.",
            "minimum": 1,
            "maximum": 1440
          },
          "ends_at": {
            "type": "string",
            "description": "ISO timestamp with Z or numeric timezone offset for when the new window closes, 1 minute to 1 day after it starts. Only with enabled: true; send this or expires_in_minutes, not both.",
            "format": "date-time"
          },
          "starts_at": {
            "type": "string",
            "description": "Optional ISO timestamp with Z or numeric timezone offset, now or later and within 1 year; a time in the past is rejected. Only with enabled: true and expires_in_minutes or ends_at: the new window starts then instead of now.",
            "format": "date-time"
          },
          "remaining_uses": {
            "anyOf": [
              {
                "type": "integer",
                "description": "",
                "minimum": 1,
                "maximum": 100
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional. A number (1 to 100) sets how many buzzes are left; null makes the timer unlimited again. An exhausted timer stops opening the door; send enabled: true and expires_in_minutes or ends_at as well to reuse it."
          }
        },
        "additionalProperties": false,
        "not": {
          "required": [
            "expires_in_minutes",
            "ends_at"
          ]
        },
        "dependentSchemas": {
          "expires_in_minutes": {
            "required": [
              "enabled"
            ],
            "properties": {
              "enabled": {
                "const": true
              }
            }
          },
          "ends_at": {
            "required": [
              "enabled"
            ],
            "properties": {
              "enabled": {
                "const": true
              }
            }
          },
          "starts_at": {
            "required": [
              "enabled"
            ],
            "properties": {
              "enabled": {
                "const": true
              }
            }
          }
        },
        "if": {
          "required": [
            "enabled"
          ],
          "properties": {
            "enabled": {
              "const": true
            }
          }
        },
        "then": {
          "anyOf": [
            {
              "required": [
                "expires_in_minutes"
              ]
            },
            {
              "required": [
                "ends_at"
              ]
            }
          ]
        },
        "minProperties": 1
      },
      "PasscodeUpdate": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "description": "Optional replacement label, 1 to 120 characters. It cannot be blanked.",
            "minLength": 1,
            "maxLength": 120
          },
          "enabled": {
            "type": "boolean",
            "description": "True turns the passcode back on. If its uses ran out, also send remaining_uses (a count, or null for unlimited) or the request is rejected."
          },
          "access_code": {
            "type": "string",
            "description": "Optional replacement code; omission leaves the current code unchanged. Same 1–4 digit app-compatible validation as creation.",
            "pattern": "^(?!1$)[0-9]{1,4}$"
          },
          "remaining_uses": {
            "anyOf": [
              {
                "type": "integer",
                "description": "",
                "minimum": 1,
                "maximum": 100
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional. Sets how many uses are left (1 to 100); null removes the use limit. A passcode whose uses ran out is exhausted; send enabled: true as well to reuse it."
          },
          "enter_code_with_voice": {
            "type": "boolean",
            "description": "true lets callers speak the code aloud instead of typing it; false turns it off. Voice applies to the whole call: while any active code on the building allows voice, callers can speak any active code aloud."
          },
          "expires_in_minutes": {
            "type": "integer",
            "description": "Optional new expiry in minutes from now, 1 to 525,600 (1 year). Send this or ends_at, not both.",
            "minimum": 1,
            "maximum": 525600
          },
          "ends_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional replacement expiry: a future ISO timestamp with Z or numeric timezone offset, no more than 1 year ahead, or null to remove the expiry. Send this or expires_in_minutes, not both."
          }
        },
        "additionalProperties": false,
        "not": {
          "required": [
            "expires_in_minutes",
            "ends_at"
          ]
        },
        "minProperties": 1
      },
      "RoutineUpdate": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "description": "Optional replacement label, 1 to 120 characters. It cannot be blanked.",
            "minLength": 1,
            "maxLength": 120
          },
          "enabled": {
            "type": "boolean",
            "description": ""
          },
          "days": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "Day name, case-insensitive: sunday, monday, tuesday, wednesday, thursday, friday, saturday.",
              "pattern": "^([sS][uU][nN][dD][aA][yY]|[mM][oO][nN][dD][aA][yY]|[tT][uU][eE][sS][dD][aA][yY]|[wW][eE][dD][nN][eE][sS][dD][aA][yY]|[tT][hH][uU][rR][sS][dD][aA][yY]|[fF][rR][iI][dD][aA][yY]|[sS][aA][tT][uU][rR][dD][aA][yY])(?![\\s\\S])",
              "maxLength": 9
            },
            "description": "Any combination of days, each listed once, case-insensitive. For example [\"monday\",\"wednesday\",\"friday\"] for Monday, Wednesday and Friday.",
            "minItems": 1,
            "maxItems": 7,
            "uniqueItems": true,
            "allOf": [
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[sS][uU][nN][dD][aA][yY]$",
                  "maxLength": 6
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[mM][oO][nN][dD][aA][yY]$",
                  "maxLength": 6
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[tT][uU][eE][sS][dD][aA][yY]$",
                  "maxLength": 7
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[wW][eE][dD][nN][eE][sS][dD][aA][yY]$",
                  "maxLength": 9
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[tT][hH][uU][rR][sS][dD][aA][yY]$",
                  "maxLength": 8
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[fF][rR][iI][dD][aA][yY]$",
                  "maxLength": 6
                },
                "minContains": 0,
                "maxContains": 1
              },
              {
                "contains": {
                  "type": "string",
                  "pattern": "^[sS][aA][tT][uU][rR][dD][aA][yY]$",
                  "maxLength": 8
                },
                "minContains": 0,
                "maxContains": 1
              }
            ]
          },
          "start_hour_and_minutes": {
            "type": "string",
            "description": "24-hour HH:MM. end_hour_and_minutes must be later than start_hour_and_minutes on the same day; no overnight window.",
            "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
          },
          "end_hour_and_minutes": {
            "type": "string",
            "description": "24-hour HH:MM. end_hour_and_minutes must be later than start_hour_and_minutes on the same day; no overnight window.",
            "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone."
          },
          "access_code": {
            "anyOf": [
              {
                "type": "string",
                "description": "",
                "pattern": "^(?!1$)[0-9]{1,4}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Adds or replaces the schedule code; null removes it so every buzz in the window is let in again. Removing the code also turns voice off, so a code added later starts with voice off until enter_code_with_voice is set to true again."
          },
          "enter_code_with_voice": {
            "type": "boolean",
            "description": "true lets callers speak the code aloud instead of typing it; false turns it off. Applies only while the schedule has an access_code. Removing the code with access_code: null also turns voice off, so a code added later starts with voice off until this is set to true again. Voice applies to the whole call: while any active code on the building allows voice, callers can speak any active code aloud."
          }
        },
        "additionalProperties": false,
        "dependentRequired": {
          "start_hour_and_minutes": [
            "end_hour_and_minutes"
          ],
          "end_hour_and_minutes": [
            "start_hour_and_minutes"
          ]
        },
        "minProperties": 1
      },
      "UnlockUpdate": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/TimerUpdate"
          },
          {
            "$ref": "#/components/schemas/PasscodeUpdate"
          },
          {
            "$ref": "#/components/schemas/RoutineUpdate"
          }
        ],
        "description": "Nonempty body; fields must match existing grant type. Type cannot change. Include start_hour_and_minutes and end_hour_and_minutes together if changing either."
      },
      "Unlock": {
        "type": "object",
        "properties": {
          "building_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "type": {
            "type": "string",
            "enum": [
              "timer",
              "passcode",
              "routine"
            ]
          },
          "label": {
            "type": "string",
            "description": ""
          },
          "enabled": {
            "type": "boolean",
            "description": "The on/off switch the caller set. status says what the rule does right now. A turned-off timer has no window."
          },
          "version": {
            "type": "integer",
            "description": ""
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "scheduled",
              "inactive",
              "expired",
              "exhausted",
              "revoked"
            ],
            "description": "active: enabled and working now (for routines, not necessarily inside the schedule). scheduled: an enabled timer whose starts_at is in the future. inactive: turned off. exhausted: a passcode, or a timer with a use limit, has remaining_uses 0."
          },
          "request_id": {
            "type": "string",
            "description": "Original create idempotency key, absent on older app-created rules."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          },
          "expires_in_minutes": {
            "type": "integer",
            "description": "Timers: the window length in minutes. A window set with ends_at reports its length rounded up to whole minutes."
          },
          "starts_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          },
          "ends_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 timestamp.",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "Timer window end, or passcode expiry. null for a passcode that never expires."
          },
          "access_code": {
            "type": "string",
            "description": "Sensitive visitor code, present for passcodes and for routines that require a code."
          },
          "remaining_uses": {
            "anyOf": [
              {
                "type": "integer",
                "description": ""
              },
              {
                "type": "null"
              }
            ],
            "description": "Uses left. Each buzz that opens the door takes one; at 0 status is exhausted. null (or absent on older records) for an unlimited timer or passcode. A replayed create returns the current value."
          },
          "enter_code_with_voice": {
            "type": "boolean",
            "description": "Present for passcodes and for routines that require a code."
          },
          "days": {
            "type": "array",
            "items": {
              "type": "string",
              "description": ""
            },
            "description": "The schedule days in lowercase, Sunday first (the weekend pair is returned as [\"saturday\",\"sunday\"])."
          },
          "start_hour_and_minutes": {
            "type": "string",
            "description": "Routines: 24-hour HH:MM the window opens each scheduled day."
          },
          "end_hour_and_minutes": {
            "type": "string",
            "description": "Routines: 24-hour HH:MM the window closes."
          },
          "timezone": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "building_id",
          "id",
          "type",
          "label",
          "enabled",
          "version",
          "status",
          "created_at"
        ]
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "cursor": {
            "anyOf": [
              {
                "type": "string",
                "description": "Pass unchanged into the next request with the same filters and building."
              },
              {
                "type": "null"
              }
            ]
          },
          "has_more": {
            "type": "boolean",
            "description": ""
          }
        },
        "required": [
          "cursor",
          "has_more"
        ]
      },
      "UnlockPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Unlock"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "UnlockRevoked": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "deleted": {
            "const": true
          },
          "status": {
            "const": "revoked"
          }
        },
        "required": [
          "id",
          "deleted",
          "status"
        ]
      },
      "Log": {
        "type": "object",
        "properties": {
          "building_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "unlock_id": {
            "type": "string",
            "description": "Access rule that matched. Absent on calls, failed passcode attempts, and older records.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "type": {
            "type": "string",
            "enum": [
              "unlock",
              "call"
            ],
            "description": "unlock: an access-rule attempt. call: a call forwarded to the resident (or the owner calling their own number)."
          },
          "unlock_type": {
            "type": "string",
            "description": "timer, passcode, routine, or unknown(N) for unrecognized values. Absent on calls. On a failed passcode attempt, the name and unlock_type come from the first active rule."
          },
          "name": {
            "type": "string",
            "description": ""
          },
          "succeeded": {
            "type": "boolean",
            "description": ""
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          }
        },
        "required": [
          "building_id",
          "id",
          "type",
          "name",
          "succeeded",
          "created_at"
        ]
      },
      "LogPage": {
        "type": "object",
        "properties": {
          "building_id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Log"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "building_id",
          "data",
          "pagination"
        ]
      },
      "Deleted": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "deleted": {
            "const": true
          }
        },
        "required": [
          "id",
          "deleted"
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "A publicly reachable https:// URL, at most 2048 characters; otherwise 400 INVALID_WEBHOOK_URL.",
            "format": "uri",
            "maxLength": 2048,
            "pattern": "^https://"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "access.granted",
                "access.call_forwarded",
                "access.denied",
                "unlock.no_uses_remaining",
                "webhook.test"
              ]
            },
            "minItems": 1,
            "description": "Event types to send. Omit to receive every event type."
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque resource ID, normally 24 hexadecimal characters.",
            "pattern": "^[a-fA-F0-9]{24}$"
          },
          "url": {
            "type": "string",
            "description": "",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "access.granted",
                "access.call_forwarded",
                "access.denied",
                "unlock.no_uses_remaining",
                "webhook.test"
              ]
            }
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "description": "Signing secret (whsec_ followed by base64url). Returned only by POST /v1/webhooks (the original 201 and any idempotent 200 replay); store it securely. List responses never include it.",
            "pattern": "^whsec_[A-Za-z0-9_-]+$"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "created_at"
        ]
      },
      "WebhookEndpointList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            },
            "description": "Every endpoint on the account (at most 5). secret is never included."
          }
        },
        "required": [
          "data"
        ]
      },
      "WebhookTestQueued": {
        "type": "object",
        "properties": {
          "delivery_id": {
            "type": "string",
            "description": "ID of the queued webhook.test delivery."
          }
        },
        "required": [
          "delivery_id"
        ]
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique event ID; deduplicate on it because a retried delivery repeats the same ID.",
            "pattern": "^evt_"
          },
          "type": {
            "type": "string",
            "enum": [
              "access.granted",
              "access.call_forwarded",
              "access.denied",
              "unlock.no_uses_remaining",
              "webhook.test"
            ]
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp.",
            "format": "date-time"
          },
          "api_version": {
            "const": "v1"
          },
          "data": {
            "type": "object",
            "properties": {
              "building_id": {
                "type": "string",
                "description": "Opaque resource ID, normally 24 hexadecimal characters.",
                "pattern": "^[a-fA-F0-9]{24}$"
              },
              "building_label": {
                "type": "string",
                "description": "The building label, as in GET /v1/buildings."
              },
              "unlock_id": {
                "type": "string",
                "description": "Opaque resource ID, normally 24 hexadecimal characters.",
                "pattern": "^[a-fA-F0-9]{24}$"
              },
              "unlock_type": {
                "type": "string",
                "enum": [
                  "timer",
                  "passcode",
                  "routine"
                ]
              },
              "label": {
                "type": "string",
                "description": ""
              },
              "remaining_uses": {
                "anyOf": [
                  {
                    "type": "integer",
                    "description": "Uses left after this use; null for rules without a use limit."
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "occurred_at": {
                "type": "string",
                "description": "ISO 8601 time the event happened. Delivery order is not guaranteed, so order events by this field.",
                "format": "date-time"
              }
            },
            "description": "access.granted: building_id, building_label, unlock_id, unlock_type, label, remaining_uses, occurred_at. access.call_forwarded and access.denied: building_id, building_label, occurred_at. unlock.no_uses_remaining: building_id, building_label, unlock_id, unlock_type, label, occurred_at. webhook.test: empty object."
          }
        },
        "required": [
          "id",
          "type",
          "created_at",
          "api_version",
          "data"
        ]
      }
    }
  },
  "webhooks": {
    "buzzerapi-event": {
      "post": {
        "operationId": "webhook_event",
        "summary": "Event delivered to your webhook endpoint",
        "description": "BuzzerAPI POSTs each event as JSON with User-Agent: BuzzerAPI-Webhooks/1. Verify BuzzerAPI-Signature against the raw body before parsing: compute hex HMAC-SHA256 of \"<t>.<raw body>\" with the whole endpoint secret (including the whsec_ prefix), compare it to v1 in constant time, and reject timestamps more than 5 minutes old. Respond 2xx within 5 seconds; redirects are not followed. Any other outcome is retried at +1 minute, +5 minutes, +30 minutes, and +2 hours (5 attempts in total), then marked failed. Deduplicate on id. Delivery order is not guaranteed; order events by data.occurred_at.",
        "parameters": [
          {
            "name": "BuzzerAPI-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "",
              "pattern": "^t=[0-9]+,v1=[0-9a-f]{64}$"
            },
            "description": "t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the whole endpoint secret>."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Delivered. Anything else is retried."
          }
        }
      }
    }
  },
  "externalDocs": {
    "url": "https://www.buzzerapi.com/api-reference",
    "description": "Human-readable reference, error catalog, and retry rules."
  }
}
