> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/cortex-cloud-api/broker-vm-tenant-side/brokers.md).

# Brokers

Manage the inventory of registered Broker VMs — list, edit, register new ones, remove, reboot, shutdown, upgrade. Endpoints in this tag operate on the broker as a whole, not on individual applets.

## List registered Broker VMs

> Return all brokers registered with the tenant, optionally filtered\
> by one or more \`device\_id\` and/or \`device\_name\` values supplied in\
> the request body.\
> \
> The response is a JSON array of broker records, each carrying the\
> broker identity (device\_id, name, FQDN, version), connectivity and\
> configuration status, resource usage (CPU, memory, disk), network\
> configuration (interfaces, subnet, proxy, NTP), policy\
> (auto-upgrade window, SSH access, SSL/CA certificates), and the\
> list of currently configured applets with their per-applet status\
> and metrics.\
> \
> \*\*No pagination today\*\* — the full list is returned in a single\
> response. Filters are applied server-side: \`device\_id\` by exact\
> match, and \`device\_name\` by shell-style wildcard (\`fnmatch\`,\
> case-insensitive when a \`\*\`/\`?\` wildcard is present) falling back\
> to exact match for values without wildcards.\
> \
> \*\*Filtered no-match returns \`null\`\*\* — when a filter is supplied\
> but no broker matches, the \`200\` body is JSON \`null\` (not \`\[]\`).\
> An unfiltered request always returns a JSON array.\
> \
> \*\*Required permission:\*\* \`broker\_action\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Public API (tenant-side)","version":"1.0.0"},"tags":[{"name":"brokers","description":"Manage the inventory of registered Broker VMs — list, edit, register\nnew ones, remove, reboot, shutdown, upgrade. Endpoints in this tag\noperate on the broker as a whole, not on individual applets.\n"}],"servers":[{"url":"https://api-{fqdn}","description":"Cortex tenant base URL","variables":{"fqdn":{"default":"cortex.paloaltonetworks.com","description":"Fully qualified domain name of the Cortex tenant."}}}],"security":[{"XDRAuth":[],"XDRAuthToken":[]}],"components":{"securitySchemes":{"XDRAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"The tenant API key value, sent as the literal `Authorization`\nheader value (no `Bearer ` prefix).\n"}},"schemas":{"GetBrokersRequestParams":{"type":"object","description":"Optional filters for [`getBrokers`](#operation/getBrokers). Omit\nthe body entirely to return every broker.\n","additionalProperties":false,"properties":{"id":{"type":"array","description":"Exact-match filter on `device_id`.","items":{"type":"string","minLength":1}},"name":{"type":"array","description":"Filter on `device_name`. A value containing shell-style\nwildcards (`*`, `?`) is matched with `fnmatch`\n(case-insensitive); a value without wildcards is matched\nexactly (case-sensitive). Multiple values are OR-combined.\n","items":{"type":"string","minLength":1}}}},"BrokerDeviceInfo":{"type":"object","description":"Full inventory record for a single registered broker.","required":["device_id","device_name","status","version","external_interface","all_interfaces","configuration_status","fqdn","ntp_servers","internal_network_subnet","monitoring","apps"],"properties":{"device_id":{"type":"string","description":"Unique identifier of the broker within the tenant."},"device_name":{"type":"string","description":"Operator-supplied display name."},"status":{"type":"string","description":"Connectivity / lifecycle status of the broker (e.g.,\n`CONNECTED`, `DISCONNECTED`, transitory states such as\n`IMPORT_CONFIG`).\n"},"version":{"type":"string","description":"Broker VM platform version (e.g., `10.2.0`)."},"external_interface":{"type":"string","description":"IP address of the broker's externally-facing interface."},"all_interfaces":{"type":"array","description":"IP addresses of every configured interface.","items":{"type":"string"}},"cluster_name":{"type":"string","nullable":true,"description":"Cluster the broker belongs to, or `null` if standalone."},"configuration_status":{"type":"string","description":"Whether the broker's persisted configuration matches its\napplied configuration (e.g., `Configured`, `Misconfigured`).\n"},"cpu_usage":{"type":"number","format":"float","nullable":true,"description":"Recent CPU usage as a percentage (0–100), or `null` if unavailable."},"memory_usage":{"type":"number","format":"float","nullable":true,"description":"Recent memory usage as a percentage (0–100), or `null` if unavailable."},"disk_usage":{"type":"number","format":"float","nullable":true,"description":"Recent disk usage as a percentage (0–100), or `null` if unavailable."},"last_seen":{"type":"string","nullable":true,"description":"ISO 8601 UTC timestamp of the broker's last sync."},"upgrade_time":{"type":"string","nullable":true,"description":"ISO 8601 UTC timestamp of the broker's last upgrade."},"fqdn":{"type":"string","description":"Broker's fully qualified domain name."},"proxy_server":{"$ref":"#/components/schemas/ProxyServer"},"web_ui_listening_port":{"type":"string","nullable":true,"description":"Port the broker web UI listens on, or `null`."},"ntp_servers":{"type":"array","description":"Configured NTP servers.","items":{"type":"string"}},"internal_network_subnet":{"type":"string","description":"Broker internal subnet CIDR."},"auto_upgrade":{"$ref":"#/components/schemas/AutoUpgrade"},"monitoring":{"type":"boolean","description":"Whether monitoring metric collection is enabled."},"ssh_access":{"$ref":"#/components/schemas/SSHAccess"},"ssl_server_certificates":{"$ref":"#/components/schemas/SSLServerCertificates"},"trusted_ca_certificate":{"$ref":"#/components/schemas/TrustedCACertificate"},"apps":{"type":"array","description":"Currently configured applets and their per-applet status +\nmetrics. Inactive applets are omitted.\n","items":{"$ref":"#/components/schemas/BrokerApp"}}}},"ProxyServer":{"type":"object","nullable":true,"description":"Outbound proxy currently configured on the broker, or `null` when\nno proxy is set (`type` was `none`/`disabled`/empty).\n","required":["type"],"properties":{"type":{"type":"string","description":"Proxy protocol.","enum":["http","socks4","socks5"]},"address":{"type":"string","nullable":true},"port":{"type":"string","nullable":true},"username":{"type":"string","nullable":true}}},"AutoUpgrade":{"type":"object","description":"Auto-upgrade policy as returned by `getBrokers`.","required":["enabled"],"properties":{"enabled":{"type":"boolean"},"days_in_week":{"type":"array","nullable":true,"description":"Day names the window applies, when `enabled` and a specific\nwindow is configured.\n","items":{"type":"string","enum":["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]}},"schedule":{"type":"string","nullable":true,"enum":["any","specific"]},"schedule_from":{"type":"string","nullable":true,"description":"`HH:MM` start of window."},"schedule_to":{"type":"string","nullable":true,"description":"`HH:MM` end of window."},"timezone":{"type":"string","nullable":true}}},"SSHAccess":{"type":"object","description":"SSH access policy as returned by `getBrokers`.","required":["type"],"properties":{"type":{"type":"string","enum":["enabled","disabled"]},"welcome_message":{"type":"string","nullable":true},"ssh_public_keys":{"type":"array","nullable":true,"items":{"type":"string"}}}},"SSLServerCertificates":{"description":"Currently-installed SSL serving certificate, as returned by `getBrokers`. Both `server_certificate` and `private_key` are display-name references; raw PEM material is never returned.\n","type":"object","nullable":true,"required":["server_certificate","private_key"],"properties":{"server_certificate":{"$ref":"#/components/schemas/ServerCertificate"},"private_key":{"type":"string","description":"Display name of the private-key file."}}},"ServerCertificate":{"description":"Display-name reference to an installed SSL server certificate, including its `expires_on` ISO timestamp.\n","type":"object","required":["name","expires_on"],"properties":{"name":{"type":"string"},"expires_on":{"type":"string","description":"ISO 8601 UTC timestamp of certificate expiration."}}},"TrustedCACertificate":{"description":"Custom trusted CA certificate currently installed on the broker, as returned by `getBrokers`.\n","type":"object","nullable":true,"required":["name","expires_on"],"properties":{"name":{"type":"string"},"expires_on":{"type":"string","description":"ISO 8601 UTC timestamp of CA certificate expiration."}}},"BrokerApp":{"type":"object","description":"Per-applet entry within a broker's `apps` list.\n`name` is the applet display name (e.g., `WEC`, `CSV`,\n`Network Mapper`); `status` reflects the applet runtime state.\n\n**Note:** additional metric fields are injected dynamically by the\nbackend from each applet's own metrics class. They are not\nenumerated here because the set is open-ended per applet. Treat\nunknown fields as informational.\n","required":["name","status"],"properties":{"name":{"type":"string"},"status":{"type":"string","description":"Applet runtime status. Known values: `Connected`,\n`WARNING`, `ERROR`, `activating`, `deactivating`,\n`updating`.\n"},"errors":{"type":"array","description":"Present when `status` is `WARNING` or `ERROR` and the applet\nsurfaced one or more reason entries.\n","items":{"$ref":"#/components/schemas/AppError"}}},"additionalProperties":true},"AppError":{"description":"Per-applet error or warning entry surfaced under `BrokerApp.errors`.\n","type":"object","required":["classification","timestamp","message"],"properties":{"classification":{"type":"string","enum":["Error","Warning"]},"timestamp":{"type":"string","description":"ISO 8601 UTC timestamp."},"message":{"type":"string"}}},"PapiErrorResponse":{"type":"object","description":"Canonical error envelope returned by every non-2xx response on\nthis surface.\n","required":["description"],"properties":{"description":{"type":"string","description":"Human-readable error message."},"errors":{"type":"array","description":"Per-field validation failures. Present only on\n`400 Bad Request` responses originating from Pydantic schema\nvalidation; otherwise omitted.\n","items":{"$ref":"#/components/schemas/PapiFieldError"}}}},"PapiFieldError":{"description":"One entry in the `errors` array of a `400 Bad Request` response — a Pydantic per-field validation failure.\n","type":"object","required":["field","message"],"properties":{"field":{"type":"string","description":"Dotted path to the offending field within the request body,\nusing ` -> ` as separator for nested keys\n(e.g., `proxy -> type`, `upgrade_window -> days -> 0`).\n"},"message":{"type":"string","description":"Pydantic validation message."}}}},"responses":{"BadRequest":{"description":"Request validation failed. `errors` is present when the failure\noriginates from Pydantic schema validation; otherwise only\n`description` is populated.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Unauthorized":{"description":"Missing or invalid `Authorization` / `x-xdr-auth-id` credentials.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller lacks the `broker_action` permission, or the\ntargeted broker is a cluster member and the operation is rejected\nat that level.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}}}},"paths":{"/public_api/v1/brokers/":{"get":{"tags":["brokers"],"operationId":"getBrokers","summary":"List registered Broker VMs","description":"Return all brokers registered with the tenant, optionally filtered\nby one or more `device_id` and/or `device_name` values supplied in\nthe request body.\n\nThe response is a JSON array of broker records, each carrying the\nbroker identity (device_id, name, FQDN, version), connectivity and\nconfiguration status, resource usage (CPU, memory, disk), network\nconfiguration (interfaces, subnet, proxy, NTP), policy\n(auto-upgrade window, SSH access, SSL/CA certificates), and the\nlist of currently configured applets with their per-applet status\nand metrics.\n\n**No pagination today** — the full list is returned in a single\nresponse. Filters are applied server-side: `device_id` by exact\nmatch, and `device_name` by shell-style wildcard (`fnmatch`,\ncase-insensitive when a `*`/`?` wildcard is present) falling back\nto exact match for values without wildcards.\n\n**Filtered no-match returns `null`** — when a filter is supplied\nbut no broker matches, the `200` body is JSON `null` (not `[]`).\nAn unfiltered request always returns a JSON array.\n\n**Required permission:** `broker_action`.\n","requestBody":{"required":false,"description":"Optional filters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBrokersRequestParams"}}}},"responses":{"200":{"description":"Brokers matching the request. An unfiltered request returns a\nJSON array (possibly empty). A filtered request that matches\nnothing returns JSON `null` — hence the schema is nullable.\n","content":{"application/json":{"schema":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/BrokerDeviceInfo"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Edit a Broker VM

> Apply configuration changes to a single broker. Any field omitted\
> from the request body is left unchanged. The endpoint returns an\
> \`action\_id\` for the asynchronous propagation of the change to the\
> broker; poll\
> \[\`getActionStatus\`]\(#operation/getActionStatus) to observe completion.\
> \
> \*\*Required permission:\*\* \`broker\_action\`.\
> \
> \### Mutually-exclusive concerns\
> \
> \- \`ssh\_keys\` entries must start with one of \`ssh-rsa\`,\
> &#x20; \`ssh-ed25519\`, \`ssh-dss\`, \`ecdsa-sha2-\` — otherwise \`400\`.\
> \- \`webui\_port\` must be an integer in \`\[1, 65535]\`.\
> \- \`internal\_network\` must be a valid CIDR.\
> \- When \`auto\_upgrade=true\` and \`upgrade\_window\` is provided with\
> &#x20; \`start\_time\` and \`end\_time\`, the window must be \*\*at least\
> &#x20; 4 hours long\*\*.\
> \
> \### Notable error mappings\
> \
> \- \`404 Not Found\` — \`device\_id\` is unknown.\
> \- \`409 Conflict\` — broker is currently disconnected.\
> \- \`403 Forbidden\` — broker is a cluster member (edit the cluster\
> &#x20; configuration instead).<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Public API (tenant-side)","version":"1.0.0"},"tags":[{"name":"brokers","description":"Manage the inventory of registered Broker VMs — list, edit, register\nnew ones, remove, reboot, shutdown, upgrade. Endpoints in this tag\noperate on the broker as a whole, not on individual applets.\n"}],"servers":[{"url":"https://api-{fqdn}","description":"Cortex tenant base URL","variables":{"fqdn":{"default":"cortex.paloaltonetworks.com","description":"Fully qualified domain name of the Cortex tenant."}}}],"security":[{"XDRAuth":[],"XDRAuthToken":[]}],"components":{"securitySchemes":{"XDRAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"The tenant API key value, sent as the literal `Authorization`\nheader value (no `Bearer ` prefix).\n"}},"parameters":{"DeviceIdPath":{"name":"device_id","in":"path","required":true,"description":"The broker device identifier as returned by `getBrokers`.","schema":{"type":"string","minLength":1}}},"schemas":{"EditBrokerRequestParams":{"type":"object","description":"Patch for a single broker. Any field omitted from the body is left\nunchanged. Server-side validation rules are described per-field\nbelow.\n","additionalProperties":false,"properties":{"name":{"type":"string","description":"New display name for the broker."},"fqdn":{"type":"string","description":"New fully qualified domain name."},"proxy":{"$ref":"#/components/schemas/ProxyConfig"},"webui_port":{"type":"string","description":"Port the broker's web UI listens on. Must parse as an integer\nin `[1, 65535]`.\n"},"ntp":{"type":"array","description":"List of NTP server hostnames or IPs.","items":{"type":"string","minLength":1}},"internal_network":{"type":"string","description":"Internal network CIDR. Must parse as an IPv4 network.\n"},"auto_upgrade":{"type":"boolean","description":"Master switch for auto-upgrade. When `true`, `upgrade_window`\nshould also be provided.\n"},"upgrade_window":{"$ref":"#/components/schemas/UpgradeWindow"},"allow_monitoring":{"type":"boolean","description":"Whether the broker reports monitoring metrics."},"ssh_enabled":{"type":"boolean","description":"Whether SSH access to the broker is enabled."},"ssh_keys":{"type":"array","description":"Authorized SSH public keys. Each entry must start with one of\n`ssh-rsa`, `ssh-ed25519`, `ssh-dss`, `ecdsa-sha2-`.\n","items":{"type":"string","minLength":1}},"welcome_message":{"type":"string","description":"SSH login banner."},"ssl_crt":{"type":"string","description":"PEM-encoded server certificate (paired with `ssl_key`)."},"ssl_key":{"type":"string","description":"PEM-encoded private key (paired with `ssl_crt`)."},"ssl_crt_file_name":{"type":"string","description":"Display name for the SSL certificate file."},"ssl_key_file_name":{"type":"string","description":"Display name for the SSL key file."},"custom_ca":{"$ref":"#/components/schemas/CustomCACertificate"},"broker_ui_password":{"type":"string","description":"New broker web-UI admin password (write-only; never returned\nby `getBrokers`).\n","format":"password"}}},"ProxyConfig":{"type":"object","additionalProperties":false,"description":"Broker outbound proxy configuration.","properties":{"type":{"type":"string","enum":["none","http","socks4","socks5"],"default":"none","description":"Proxy protocol (lowercase)."},"host":{"type":"string","description":"Proxy host. Empty string disables."},"port":{"type":"string","description":"Proxy port (string form, integer in `[1, 65535]`)."},"user":{"type":"string","description":"Proxy username."},"pass":{"type":"string","format":"password","description":"Proxy password (write-only)."}}},"UpgradeWindow":{"type":"object","additionalProperties":false,"description":"Recurring maintenance window for auto-upgrade. Must be at least\n4 hours long when both `start_time` and `end_time` are provided.\n","properties":{"days":{"type":"array","description":"Days of the week the window applies. Accepts ISO weekday\nintegers (1=Monday … 7=Sunday) or English day names\n(\"Monday\", \"Tuesday\", …).\n","items":{"oneOf":[{"type":"integer","minimum":1,"maximum":7},{"type":"string","enum":["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]}]}},"start_time":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$","description":"`HH:MM` in 24-hour format."},"end_time":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$","description":"`HH:MM` in 24-hour format."},"timezone":{"type":"string","description":"IANA timezone identifier (e.g., `UTC`, `Europe/Berlin`)."},"schedule":{"type":"string","enum":["any","specific"],"description":"`any` = window applies any time of day on `days`; `specific`\n= window bounded by `start_time`/`end_time`.\n"}}},"CustomCACertificate":{"type":"object","additionalProperties":false,"description":"Custom trusted-CA certificate to install on the broker.","properties":{"cert":{"type":"string","description":"PEM-encoded CA certificate chain."},"name":{"type":"string","description":"Display name for the certificate."},"details":{"type":"string","description":"Free-form description."}}},"EditBrokerResponse":{"type":"object","description":"Acknowledgement of an accepted edit.","required":["action_id"],"properties":{"action_id":{"type":"string","description":"Opaque identifier of the asynchronous action; poll\n[`getActionStatus`](#operation/getActionStatus).\n"}}},"PapiErrorResponse":{"type":"object","description":"Canonical error envelope returned by every non-2xx response on\nthis surface.\n","required":["description"],"properties":{"description":{"type":"string","description":"Human-readable error message."},"errors":{"type":"array","description":"Per-field validation failures. Present only on\n`400 Bad Request` responses originating from Pydantic schema\nvalidation; otherwise omitted.\n","items":{"$ref":"#/components/schemas/PapiFieldError"}}}},"PapiFieldError":{"description":"One entry in the `errors` array of a `400 Bad Request` response — a Pydantic per-field validation failure.\n","type":"object","required":["field","message"],"properties":{"field":{"type":"string","description":"Dotted path to the offending field within the request body,\nusing ` -> ` as separator for nested keys\n(e.g., `proxy -> type`, `upgrade_window -> days -> 0`).\n"},"message":{"type":"string","description":"Pydantic validation message."}}}},"responses":{"BadRequest":{"description":"Request validation failed. `errors` is present when the failure\noriginates from Pydantic schema validation; otherwise only\n`description` is populated.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Unauthorized":{"description":"Missing or invalid `Authorization` / `x-xdr-auth-id` credentials.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller lacks the `broker_action` permission, or the\ntargeted broker is a cluster member and the operation is rejected\nat that level.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"NotFound":{"description":"The targeted resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Conflict":{"description":"The action cannot proceed in the current state — most commonly,\nthe broker is disconnected, or an applet is not in the required\nactive/inactive state.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}}}},"paths":{"/public_api/v1/brokers/{device_id}/":{"post":{"tags":["brokers"],"operationId":"editBroker","summary":"Edit a Broker VM","description":"Apply configuration changes to a single broker. Any field omitted\nfrom the request body is left unchanged. The endpoint returns an\n`action_id` for the asynchronous propagation of the change to the\nbroker; poll\n[`getActionStatus`](#operation/getActionStatus) to observe completion.\n\n**Required permission:** `broker_action`.\n\n### Mutually-exclusive concerns\n\n- `ssh_keys` entries must start with one of `ssh-rsa`,\n  `ssh-ed25519`, `ssh-dss`, `ecdsa-sha2-` — otherwise `400`.\n- `webui_port` must be an integer in `[1, 65535]`.\n- `internal_network` must be a valid CIDR.\n- When `auto_upgrade=true` and `upgrade_window` is provided with\n  `start_time` and `end_time`, the window must be **at least\n  4 hours long**.\n\n### Notable error mappings\n\n- `404 Not Found` — `device_id` is unknown.\n- `409 Conflict` — broker is currently disconnected.\n- `403 Forbidden` — broker is a cluster member (edit the cluster\n  configuration instead).\n","parameters":[{"$ref":"#/components/parameters/DeviceIdPath"}],"requestBody":{"required":true,"description":"Patch payload — every field is optional; omitted fields are\nleft unchanged. See `EditBrokerRequestParams` for the field\nset and per-field validation rules.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditBrokerRequestParams"}}}},"responses":{"201":{"description":"Edit accepted; poll `action_id` for propagation status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditBrokerResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Remove a Broker VM from the tenant

> Permanently de-register a broker. The broker is \*\*not\*\* uninstalled\
> from its host; it is simply removed from the tenant's inventory and\
> will be ignored by subsequent syncs.\
> \
> \*\*Required permission:\*\* \`broker\_action\`.\
> \
> \- \`404 Not Found\` — \`device\_id\` is unknown.\
> \- \`403 Forbidden\` — broker is a cluster member; remove it from the\
> &#x20; cluster first.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Public API (tenant-side)","version":"1.0.0"},"tags":[{"name":"brokers","description":"Manage the inventory of registered Broker VMs — list, edit, register\nnew ones, remove, reboot, shutdown, upgrade. Endpoints in this tag\noperate on the broker as a whole, not on individual applets.\n"}],"servers":[{"url":"https://api-{fqdn}","description":"Cortex tenant base URL","variables":{"fqdn":{"default":"cortex.paloaltonetworks.com","description":"Fully qualified domain name of the Cortex tenant."}}}],"security":[{"XDRAuth":[],"XDRAuthToken":[]}],"components":{"securitySchemes":{"XDRAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"The tenant API key value, sent as the literal `Authorization`\nheader value (no `Bearer ` prefix).\n"}},"parameters":{"DeviceIdPath":{"name":"device_id","in":"path","required":true,"description":"The broker device identifier as returned by `getBrokers`.","schema":{"type":"string","minLength":1}}},"responses":{"Unauthorized":{"description":"Missing or invalid `Authorization` / `x-xdr-auth-id` credentials.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller lacks the `broker_action` permission, or the\ntargeted broker is a cluster member and the operation is rejected\nat that level.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"NotFound":{"description":"The targeted resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}}},"schemas":{"PapiErrorResponse":{"type":"object","description":"Canonical error envelope returned by every non-2xx response on\nthis surface.\n","required":["description"],"properties":{"description":{"type":"string","description":"Human-readable error message."},"errors":{"type":"array","description":"Per-field validation failures. Present only on\n`400 Bad Request` responses originating from Pydantic schema\nvalidation; otherwise omitted.\n","items":{"$ref":"#/components/schemas/PapiFieldError"}}}},"PapiFieldError":{"description":"One entry in the `errors` array of a `400 Bad Request` response — a Pydantic per-field validation failure.\n","type":"object","required":["field","message"],"properties":{"field":{"type":"string","description":"Dotted path to the offending field within the request body,\nusing ` -> ` as separator for nested keys\n(e.g., `proxy -> type`, `upgrade_window -> days -> 0`).\n"},"message":{"type":"string","description":"Pydantic validation message."}}}}},"paths":{"/public_api/v1/brokers/{device_id}/delete/":{"post":{"tags":["brokers"],"operationId":"removeBroker","summary":"Remove a Broker VM from the tenant","description":"Permanently de-register a broker. The broker is **not** uninstalled\nfrom its host; it is simply removed from the tenant's inventory and\nwill be ignored by subsequent syncs.\n\n**Required permission:** `broker_action`.\n\n- `404 Not Found` — `device_id` is unknown.\n- `403 Forbidden` — broker is a cluster member; remove it from the\n  cluster first.\n","parameters":[{"$ref":"#/components/parameters/DeviceIdPath"}],"responses":{"200":{"description":"Broker removed.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"Empty object on success."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Generate a Broker VM registration token

> Issue a short-lived registration token to be used by a new Broker\
> VM during its first-time activation. The token is opaque to the\
> caller; pass it verbatim to the appliance's direct API\
> \`/public\_api/v1/register\` endpoint (see\
> \`broker-direct-papi.yaml\`).\
> \
> \*\*Not idempotent\*\* — each call produces a new token.\
> \
> \*\*Required permission:\*\* \`broker\_action\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Public API (tenant-side)","version":"1.0.0"},"tags":[{"name":"brokers","description":"Manage the inventory of registered Broker VMs — list, edit, register\nnew ones, remove, reboot, shutdown, upgrade. Endpoints in this tag\noperate on the broker as a whole, not on individual applets.\n"}],"servers":[{"url":"https://api-{fqdn}","description":"Cortex tenant base URL","variables":{"fqdn":{"default":"cortex.paloaltonetworks.com","description":"Fully qualified domain name of the Cortex tenant."}}}],"security":[{"XDRAuth":[],"XDRAuthToken":[]}],"components":{"securitySchemes":{"XDRAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"The tenant API key value, sent as the literal `Authorization`\nheader value (no `Bearer ` prefix).\n"}},"schemas":{"GenerateTokenResponse":{"description":"Payload returned by `generateRegistrationToken`. The `token` is opaque to the caller; pass it verbatim to the broker's direct API `/public_api/v1/register` endpoint.\n","type":"object","required":["token"],"properties":{"token":{"type":"string","minLength":1,"description":"Opaque registration token. Pass verbatim to the appliance's\ndirect API `/public_api/v1/register` endpoint.\n"}}},"PapiErrorResponse":{"type":"object","description":"Canonical error envelope returned by every non-2xx response on\nthis surface.\n","required":["description"],"properties":{"description":{"type":"string","description":"Human-readable error message."},"errors":{"type":"array","description":"Per-field validation failures. Present only on\n`400 Bad Request` responses originating from Pydantic schema\nvalidation; otherwise omitted.\n","items":{"$ref":"#/components/schemas/PapiFieldError"}}}},"PapiFieldError":{"description":"One entry in the `errors` array of a `400 Bad Request` response — a Pydantic per-field validation failure.\n","type":"object","required":["field","message"],"properties":{"field":{"type":"string","description":"Dotted path to the offending field within the request body,\nusing ` -> ` as separator for nested keys\n(e.g., `proxy -> type`, `upgrade_window -> days -> 0`).\n"},"message":{"type":"string","description":"Pydantic validation message."}}}},"responses":{"Unauthorized":{"description":"Missing or invalid `Authorization` / `x-xdr-auth-id` credentials.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller lacks the `broker_action` permission, or the\ntargeted broker is a cluster member and the operation is rejected\nat that level.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}}}},"paths":{"/public_api/v1/brokers/registration_token/":{"post":{"tags":["brokers"],"operationId":"generateRegistrationToken","summary":"Generate a Broker VM registration token","description":"Issue a short-lived registration token to be used by a new Broker\nVM during its first-time activation. The token is opaque to the\ncaller; pass it verbatim to the appliance's direct API\n`/public_api/v1/register` endpoint (see\n`broker-direct-papi.yaml`).\n\n**Not idempotent** — each call produces a new token.\n\n**Required permission:** `broker_action`.\n","responses":{"200":{"description":"Token issued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateTokenResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Reboot a Broker VM

> Request an asynchronous reboot of the broker's underlying operating\
> system. The endpoint returns immediately once the action is\
> enqueued; observe completion by inspecting the broker's status\
> through \[\`getBrokers\`]\(#operation/getBrokers) — \`status\` will\
> cycle through reconnect states.\
> \
> \*\*Required permission:\*\* \`broker\_action\`.\
> \
> \- \`404 Not Found\` — \`device\_id\` is unknown.\
> \- \`409 Conflict\` — broker is disconnected and cannot receive the action.\
> \
> The returned \`action\_id\` can also be polled via \[\`getActionStatus\`]\(#operation/getActionStatus).<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Public API (tenant-side)","version":"1.0.0"},"tags":[{"name":"brokers","description":"Manage the inventory of registered Broker VMs — list, edit, register\nnew ones, remove, reboot, shutdown, upgrade. Endpoints in this tag\noperate on the broker as a whole, not on individual applets.\n"}],"servers":[{"url":"https://api-{fqdn}","description":"Cortex tenant base URL","variables":{"fqdn":{"default":"cortex.paloaltonetworks.com","description":"Fully qualified domain name of the Cortex tenant."}}}],"security":[{"XDRAuth":[],"XDRAuthToken":[]}],"components":{"securitySchemes":{"XDRAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"The tenant API key value, sent as the literal `Authorization`\nheader value (no `Bearer ` prefix).\n"}},"parameters":{"DeviceIdPath":{"name":"device_id","in":"path","required":true,"description":"The broker device identifier as returned by `getBrokers`.","schema":{"type":"string","minLength":1}}},"schemas":{"LifecycleActionResponse":{"type":"object","description":"Acknowledgement of an accepted lifecycle action (reboot, shutdown, or upgrade).","required":["action_id"],"properties":{"action_id":{"type":"string","description":"Opaque identifier of the asynchronous lifecycle action; poll\n[`getActionStatus`](#operation/getActionStatus).\n"}}},"PapiErrorResponse":{"type":"object","description":"Canonical error envelope returned by every non-2xx response on\nthis surface.\n","required":["description"],"properties":{"description":{"type":"string","description":"Human-readable error message."},"errors":{"type":"array","description":"Per-field validation failures. Present only on\n`400 Bad Request` responses originating from Pydantic schema\nvalidation; otherwise omitted.\n","items":{"$ref":"#/components/schemas/PapiFieldError"}}}},"PapiFieldError":{"description":"One entry in the `errors` array of a `400 Bad Request` response — a Pydantic per-field validation failure.\n","type":"object","required":["field","message"],"properties":{"field":{"type":"string","description":"Dotted path to the offending field within the request body,\nusing ` -> ` as separator for nested keys\n(e.g., `proxy -> type`, `upgrade_window -> days -> 0`).\n"},"message":{"type":"string","description":"Pydantic validation message."}}}},"responses":{"Unauthorized":{"description":"Missing or invalid `Authorization` / `x-xdr-auth-id` credentials.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller lacks the `broker_action` permission, or the\ntargeted broker is a cluster member and the operation is rejected\nat that level.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"NotFound":{"description":"The targeted resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Conflict":{"description":"The action cannot proceed in the current state — most commonly,\nthe broker is disconnected, or an applet is not in the required\nactive/inactive state.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}}}},"paths":{"/public_api/v1/brokers/{device_id}/reboot/":{"post":{"tags":["brokers"],"operationId":"rebootBroker","summary":"Reboot a Broker VM","description":"Request an asynchronous reboot of the broker's underlying operating\nsystem. The endpoint returns immediately once the action is\nenqueued; observe completion by inspecting the broker's status\nthrough [`getBrokers`](#operation/getBrokers) — `status` will\ncycle through reconnect states.\n\n**Required permission:** `broker_action`.\n\n- `404 Not Found` — `device_id` is unknown.\n- `409 Conflict` — broker is disconnected and cannot receive the action.\n\nThe returned `action_id` can also be polled via [`getActionStatus`](#operation/getActionStatus).\n","parameters":[{"$ref":"#/components/parameters/DeviceIdPath"}],"responses":{"200":{"description":"Reboot accepted; poll `action_id` for completion status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LifecycleActionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Shut down a Broker VM

> Request an asynchronous shutdown of the broker. The broker becomes\
> \`DISCONNECTED\` once the OS powers down and will require manual\
> intervention (or hypervisor automation) to come back online.\
> \
> \*\*Required permission:\*\* \`broker\_action\`.\
> \
> \- \`404 Not Found\` — \`device\_id\` is unknown.\
> \- \`409 Conflict\` — broker is already disconnected.\
> \
> The returned \`action\_id\` can also be polled via \[\`getActionStatus\`]\(#operation/getActionStatus).<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Public API (tenant-side)","version":"1.0.0"},"tags":[{"name":"brokers","description":"Manage the inventory of registered Broker VMs — list, edit, register\nnew ones, remove, reboot, shutdown, upgrade. Endpoints in this tag\noperate on the broker as a whole, not on individual applets.\n"}],"servers":[{"url":"https://api-{fqdn}","description":"Cortex tenant base URL","variables":{"fqdn":{"default":"cortex.paloaltonetworks.com","description":"Fully qualified domain name of the Cortex tenant."}}}],"security":[{"XDRAuth":[],"XDRAuthToken":[]}],"components":{"securitySchemes":{"XDRAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"The tenant API key value, sent as the literal `Authorization`\nheader value (no `Bearer ` prefix).\n"}},"parameters":{"DeviceIdPath":{"name":"device_id","in":"path","required":true,"description":"The broker device identifier as returned by `getBrokers`.","schema":{"type":"string","minLength":1}}},"schemas":{"LifecycleActionResponse":{"type":"object","description":"Acknowledgement of an accepted lifecycle action (reboot, shutdown, or upgrade).","required":["action_id"],"properties":{"action_id":{"type":"string","description":"Opaque identifier of the asynchronous lifecycle action; poll\n[`getActionStatus`](#operation/getActionStatus).\n"}}},"PapiErrorResponse":{"type":"object","description":"Canonical error envelope returned by every non-2xx response on\nthis surface.\n","required":["description"],"properties":{"description":{"type":"string","description":"Human-readable error message."},"errors":{"type":"array","description":"Per-field validation failures. Present only on\n`400 Bad Request` responses originating from Pydantic schema\nvalidation; otherwise omitted.\n","items":{"$ref":"#/components/schemas/PapiFieldError"}}}},"PapiFieldError":{"description":"One entry in the `errors` array of a `400 Bad Request` response — a Pydantic per-field validation failure.\n","type":"object","required":["field","message"],"properties":{"field":{"type":"string","description":"Dotted path to the offending field within the request body,\nusing ` -> ` as separator for nested keys\n(e.g., `proxy -> type`, `upgrade_window -> days -> 0`).\n"},"message":{"type":"string","description":"Pydantic validation message."}}}},"responses":{"Unauthorized":{"description":"Missing or invalid `Authorization` / `x-xdr-auth-id` credentials.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller lacks the `broker_action` permission, or the\ntargeted broker is a cluster member and the operation is rejected\nat that level.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"NotFound":{"description":"The targeted resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Conflict":{"description":"The action cannot proceed in the current state — most commonly,\nthe broker is disconnected, or an applet is not in the required\nactive/inactive state.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}}}},"paths":{"/public_api/v1/brokers/{device_id}/shutdown/":{"post":{"tags":["brokers"],"operationId":"shutdownBroker","summary":"Shut down a Broker VM","description":"Request an asynchronous shutdown of the broker. The broker becomes\n`DISCONNECTED` once the OS powers down and will require manual\nintervention (or hypervisor automation) to come back online.\n\n**Required permission:** `broker_action`.\n\n- `404 Not Found` — `device_id` is unknown.\n- `409 Conflict` — broker is already disconnected.\n\nThe returned `action_id` can also be polled via [`getActionStatus`](#operation/getActionStatus).\n","parameters":[{"$ref":"#/components/parameters/DeviceIdPath"}],"responses":{"200":{"description":"Shutdown accepted; poll `action_id` for completion status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LifecycleActionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```

## Upgrade a Broker VM to the latest available version

> Trigger an asynchronous upgrade of the broker to the most recent\
> version available for its OS family. The broker will reboot one or\
> more times during the upgrade; observe progress via\
> \[\`getBrokers\`]\(#operation/getBrokers).\
> \
> \*\*Required permission:\*\* \`broker\_action\`.\
> \
> \- \`404 Not Found\` — \`device\_id\` is unknown.\
> \- \`409 Conflict\` — broker is disconnected.\
> \
> The returned \`action\_id\` can also be polled via \[\`getActionStatus\`]\(#operation/getActionStatus).<br>

```json
{"openapi":"3.0.3","info":{"title":"Cortex Broker Public API (tenant-side)","version":"1.0.0"},"tags":[{"name":"brokers","description":"Manage the inventory of registered Broker VMs — list, edit, register\nnew ones, remove, reboot, shutdown, upgrade. Endpoints in this tag\noperate on the broker as a whole, not on individual applets.\n"}],"servers":[{"url":"https://api-{fqdn}","description":"Cortex tenant base URL","variables":{"fqdn":{"default":"cortex.paloaltonetworks.com","description":"Fully qualified domain name of the Cortex tenant."}}}],"security":[{"XDRAuth":[],"XDRAuthToken":[]}],"components":{"securitySchemes":{"XDRAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"The tenant API key value, sent as the literal `Authorization`\nheader value (no `Bearer ` prefix).\n"}},"parameters":{"DeviceIdPath":{"name":"device_id","in":"path","required":true,"description":"The broker device identifier as returned by `getBrokers`.","schema":{"type":"string","minLength":1}}},"schemas":{"LifecycleActionResponse":{"type":"object","description":"Acknowledgement of an accepted lifecycle action (reboot, shutdown, or upgrade).","required":["action_id"],"properties":{"action_id":{"type":"string","description":"Opaque identifier of the asynchronous lifecycle action; poll\n[`getActionStatus`](#operation/getActionStatus).\n"}}},"PapiErrorResponse":{"type":"object","description":"Canonical error envelope returned by every non-2xx response on\nthis surface.\n","required":["description"],"properties":{"description":{"type":"string","description":"Human-readable error message."},"errors":{"type":"array","description":"Per-field validation failures. Present only on\n`400 Bad Request` responses originating from Pydantic schema\nvalidation; otherwise omitted.\n","items":{"$ref":"#/components/schemas/PapiFieldError"}}}},"PapiFieldError":{"description":"One entry in the `errors` array of a `400 Bad Request` response — a Pydantic per-field validation failure.\n","type":"object","required":["field","message"],"properties":{"field":{"type":"string","description":"Dotted path to the offending field within the request body,\nusing ` -> ` as separator for nested keys\n(e.g., `proxy -> type`, `upgrade_window -> days -> 0`).\n"},"message":{"type":"string","description":"Pydantic validation message."}}}},"responses":{"Unauthorized":{"description":"Missing or invalid `Authorization` / `x-xdr-auth-id` credentials.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller lacks the `broker_action` permission, or the\ntargeted broker is a cluster member and the operation is rejected\nat that level.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"NotFound":{"description":"The targeted resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"Conflict":{"description":"The action cannot proceed in the current state — most commonly,\nthe broker is disconnected, or an applet is not in the required\nactive/inactive state.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}},"InternalServerError":{"description":"Unexpected server-side failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PapiErrorResponse"}}}}}},"paths":{"/public_api/v1/brokers/{device_id}/upgrade/":{"post":{"tags":["brokers"],"operationId":"upgradeBroker","summary":"Upgrade a Broker VM to the latest available version","description":"Trigger an asynchronous upgrade of the broker to the most recent\nversion available for its OS family. The broker will reboot one or\nmore times during the upgrade; observe progress via\n[`getBrokers`](#operation/getBrokers).\n\n**Required permission:** `broker_action`.\n\n- `404 Not Found` — `device_id` is unknown.\n- `409 Conflict` — broker is disconnected.\n\nThe returned `action_id` can also be polled via [`getActionStatus`](#operation/getActionStatus).\n","parameters":[{"$ref":"#/components/parameters/DeviceIdPath"}],"responses":{"200":{"description":"Upgrade accepted; poll `action_id` for completion status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LifecycleActionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cortex-docs.paloaltonetworks.com/cortex-cloud-api/broker-vm-tenant-side/brokers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
