# Palo Alto Networks (PAN-OS API)

> Connect a PAN-OS firewall's REST and XML APIs with a read-only admin's API key: what the agents read, what the estate harvest draws, and the read gate. Drafted from the public docs.

_How-to · Updated 2026-10-28 · Describes release 0.1.164_

> Drafted from Palo Alto Networks' public documentation, then validated against a PA-VM running PAN-OS 11.2.15 (REST API version v11.2) in October 2026: the read-only administrator, the estate harvest (device, interfaces, routes, security rules with hit counts) and the traffic log read over the XML API. Other PAN-OS versions may answer differently. The paths, parameters and response shapes below are the ones the public docs show; [Sources](#sources) lists them. When your firewall answers differently, the harvest notes and the agent's evidence say so.

## Overview {#overview}

A Palo Alto Networks connection reads the firewall's management APIs, never its data path. The REST API (`/restapi/v<major.minor>/…`) reads the configuration: security rules, interfaces, zones, address objects and virtual routers. The XML API (`/api/`) reads the operational state and the logs: `show` commands, the security-policy and route lookups, and traffic, threat and system log retrieval. The **Incident** agent uses both to find which rule a flow meets and what the firewall dropped; the estate harvest puts the firewall, its interfaces and the traffic its rules allow on the estate map. On AWS the firewall runs as a VM-Series instance; connect its management interface.

A built-in skill, `paloalto-flow-check`, walks the agent through a flow that crosses the firewall. The agent sees it only in a workspace with a Palo Alto Networks connection.

## Setup {#setup}

### Before you start {#before-you-start}

- The `datasources.manage` permission; the built-in owner and operator roles carry it.
- A dedicated API administrator on the firewall with a read-only role ([Installation](#installation)), and its API key.
- A network path from the platform to the management URL, or a [private-network agent](/help/private-access.md) where the platform cannot reach it.

### Installation {#installation}

On the firewall:

1. Choose the role. The simplest is the dynamic role `Superuser (read-only)`. For a narrower one, create an Admin Role profile under `Device > Admin Roles`. On its REST API tab set the resources the agent reads to `Read Only` (Ethernet interfaces, zones and virtual routers under Network, addresses under Objects, security rules under Policies) and disable the rest. On its XML API tab enable `Operational Requests` (the `show` commands and the two lookups) and `Log`; enable `Configuration` only if the agent should also read configuration subtrees over the XML API. The harvest reads the configuration over REST, and the XML API tab offers only enable or disable, so `Configuration` is also the permission that writes. Leave `Commit`, `User-ID Agent`, `Import`, `Export` and `Report` disabled, and give the role no Web UI or Command Line access, so the administrator can only call the API. The platform's own gate below judges every XML API request whatever the role allows.
2. Under `Device > Administrators`, add an administrator for the platform alone, such as `aiops-reader`, with that role. Palo Alto Networks recommends a separate admin account for API access; the firewall's logs then name the platform's calls, and its key can be revoked without touching anyone's login.
3. Generate its API key with the XML API's `type=keygen` request, as a `POST` with the credentials in the form body rather than the URL, the way the docs show it: `curl -X POST "https://<firewall>/api/?type=keygen" -H "Content-Type: application/x-www-form-urlencoded" -d 'user=aiops-reader&password=<password>'`. Copy the `<key>` from the answer. The key belongs to that administrator: deleting it or changing its password invalidates the key.
4. Set a key lifetime: `Device > Setup > Management`, edit `Authentication Settings`, `API Key Lifetime (min)` (1 to 525600 minutes; the default 0 means keys never expire), then commit. Palo Alto Networks recommends a short lifetime. When it elapses, generate a new key and replace it on **Edit**. `Expire all API Keys` on the same page revokes every key at once, for instance after one is exposed.

The platform sends the key in the `X-PAN-KEY` header, never as `key=` in the URL, where it would land in web server and proxy logs; a request through the connector that carries `key` or `password` in its query is refused. The read gate below is a floor, not a substitute for a read-only role.

### Configuration {#configuration}

1. Open **Settings · Data in → Data sources** and select **Connect datasource**.
2. Under **Type**, choose **Palo Alto Networks (PAN-OS API)**. Enter a **Connection name**; the connected list shows it, and the agent's tool is named after it (`<name>_request`).
3. Fill the fields; the TLS-skip field sits under **Advanced connection settings**:

| Field (portal label) | API key | Value |
|---|---|---|
| Management URL (https://\<firewall\>, without /restapi or /api) | `url` | The management interface |
| API key of a read-only administrator | `api_key` | The key from `type=keygen` for the dedicated API administrator; stored write-only |
| Virtual system (optional — blank = vsys1) | `vsys` | Set on a multi-vsys firewall; the harvest reads one virtual system |
| REST API version (optional — e.g. v11.1; blank = read from the firewall's software version) | `api_version` | Set only when the detected `v<major>.<minor>` is not a REST version your firewall serves |
| Skip TLS verify for a self-signed cert (optional — type: true) | `insecure` | `true` for the default self-signed management certificate |

4. Optionally, open **Optional · describe this environment** and say in **What should AIOps know about it?** what the firewall protects and which zones face the internet.
5. Under **Use this connection for**, choose **Investigate only** and select **Connect and verify**.

The same connection through the API (`POST /api/aiops/{tenant_id}/datasources`, requires `datasources.manage`; the key goes in `secret_values`):

```json
{
  "type_key": "paloalto",
  "name": "pa-edge",
  "description": "VM-Series in the inspection VPC; untrust faces the internet, trust holds the app subnets.",
  "config": {
    "url": "https://pa-fw.example.com",
    "vsys": "vsys1",
    "api_version": "v11.1",
    "insecure": "true"
  },
  "secret_values": {
    "api_key": "<API key>"
  },
  "role": "read",
  "enabled": true
}
```

### Validation {#validation}

**Connect and verify**, and **Test** on the row later, sends a GET to `/api/?type=version` with the key in `X-PAN-KEY`. **You should see** a dialog titled `<connection name> is connected` with **Connected — verified from the control plane**, and later in the row's **Last test** `ok · HTTP 200 /api/?type=version — <response status="success"><result><sw-version>…`. A `403` means the key is wrong or its role does not enable the XML API. The REST permissions show on the first harvest or rule read.

### If something fails {#if-something-fails}

The dialog shows **Needs a fix**, what to fix and the check's own detail; the row is saved either way. Select **Edit**, correct the field the detail names and save again, or select **Retry** once a cause outside the form (network, role) is fixed. Every verdict this connector produces is in [Troubleshooting](#troubleshooting) below.

## Data collected {#data-collected}

### Tools the agent gets {#tools}

- `<name>_request` — the HTTP tool against the management URL with the key: `method`, `path`, `query`, `body`, `content_type`. REST reads are `GET /restapi/v<ver>/<resource>` with `location` and `vsys` in `query`. An XML API request is `path: "/api/"` with the request in `query`, such as `{"type": "op", "cmd": "<show><interface>all</interface></show>"}` or `{"type": "log", "log-type": "traffic", "query": "(action neq allow)", "nlogs": "50"}` followed by `{"type": "log", "action": "get", "job-id": "<id>"}`.

Responses are capped at 20,000 characters per call.

### Read surface {#read-surface}

The XML API writes over `GET` as easily as it reads (`type=config&action=set` is a `GET`), so the method proves nothing there and the platform judges the request itself. What runs freely:

- REST: `GET` only. `POST`, `PUT`, `DELETE`, a rename and a move are refused, and so are the REST profiles that hold a credential (IKE gateways, LDAP, SNMP trap and HTTP server profiles).
- XML API, as `GET` or as `POST` with the request in the URL and no body: `type=version`; `type=op` with one `show` command, except a whole-configuration dump (`show config running` and the like; `show config list` stays free), plus the two lookups `test security-policy-match` and `test routing fib-lookup`; `type=config` with `action=get` or `action=show` on an absolute xpath of plain steps through a rulebase, address, service, zone, interface, virtual-router, tag, application or schedule subtree that names no credential node (`mgt-config`, `phash`, `password`, `passwd`, `private-key`, `pre-shared-key`, `key`, `secret`, `certificate`); `type=log` to start a retrieval job for a documented log type, and `action=get` with a numeric `job-id` to read it.
- Everything else is refused in an investigation, never offered for approval: `set`, `edit`, `delete`, `rename`, `clone`, `move`, `override`, `commit`, `keygen` (it mints a key from a password), `user-id`, `import`, `export`, `report`, every other `test`, a request that carries a key twice or under two spellings, a `key` or `password` in the query (REST or XML), and any request with a body. The refusal reads `Investigation connections are read-only. This operation was not executed; prepare an incident change using a write connection and obtain approval.`

The full rule table is under **The read/write gate in detail** in [Connections and remediation access](/help/read-and-write-roles.md#the-read-write-gate-in-detail).

### Estate harvest {#estate-harvest}

**Harvest now** on the row, the daily inventory job and an estate x-ray scan read `show system info` over the XML API (hostname, model, serial, software version, management address), then over REST `Network/EthernetInterfaces`, `Network/Zones` and `Objects/Addresses`, then `show rule-hit-count` for the security rulebase over the XML API (the rule hit counters), then over REST `Policies/SecurityRules` and `Network/VirtualRouters`, all of one virtual system. They become:

- one **Firewall** node named after the hostname, carrying the vendor, model, PAN-OS version, serial, management address and the counts of rules (allow, deny, disabled), interfaces, address objects and static routes;
- one interface node per Ethernet interface, with its address, subnet (`cidr`), zone and the static route destinations that leave through it;
- one rule node per enabled `allow` rule, linked to the interfaces of its `to` zones (applies to) and of its `from` zones (allows from), with its sources and destinations summarised as `name=value` from the address objects, its services and applications, and `world_open` when the source is `any`. The rules then derive that the destination interface is reachable from the source one, which is the traffic the firewall lets through. Each rule node also carries its usage: `hit_count`, `first_used` and `last_used` in UTC (PAN-OS counts no bytes per rule). `last_used` reads `never` for a rule with no hit since its counters were last reset. When the role cannot run the command, the harvest notes it and the rules carry no usage at all, which means unknown, not unused. The counters move with traffic, so the scan report's estate changes never list them as a change;
- one rule node per enabled rule that does not allow (`deny`, `drop`, `reset-client`, `reset-server`, `reset-both`), with its `action`, its zones, sources, destinations, services, applications and the same usage, but no link to an interface and no `world_open`: a deny never reads as traffic the firewall lets through.

Deny rules are drawn with their action and usage and no interface links; disabled rules are counted, not drawn. Interfaces and rules are leaf detail: on the [Estate map](/portal/estate) (in the product: `/portal/estate`) they show when you tick *Show every object, rules and interfaces included* or focus the firewall. The firewall counts for the map's firewall check and the x-ray report's **Firewall** line, and an enabled Palo Alto Networks connection counts on its own before the first harvest. A denied or failed read is a note on the harvest, never a crash, and what it would have listed is not marked stale. Not read yet: subinterfaces, shared-location objects, address groups, NAT rules, Panorama-pushed pre- and post-rules. A VM-Series firewall the AWS harvest also lists as an instance is joined to it by address (its management address, or an interface's, is the private address of the instance or of one of its network interfaces): it counts as one firewall, and its row in a [service group](/help/estate-harvest-and-xray.md#service-group) carries the enabled rules and the connection that read them. An address two instances or two firewalls hold joins nothing.

## Troubleshooting {#troubleshooting}

| What you see | Cause | What to do |
|---|---|---|
| `failed · HTTP 403 /api/?type=version` | The key is wrong, past its `API Key Lifetime`, or void because its administrator's password changed or `Expire all API Keys` ran; or its role does not enable the XML API. | Generate a new key with `type=keygen` and replace it on **Edit**, or enable the XML API in the role. |
| `failed · ConnectError: …` or a certificate error | A management interface the platform cannot reach, or the self-signed certificate. | Use a [private-network agent](/help/private-access.md), or `insecure: true`. |
| The harvest notes `REST API version unknown` | `show system info` did not answer, so the `v<major.minor>` path could not be built. | Fix the XML API access, or set **REST API version** on **Edit**. |
| The harvest notes `HTTP 403` on a REST listing (`paloalto GET /restapi/v11.1/Policies/SecurityRules: …`) | The role's REST API tab does not read that resource. | Set it to `Read Only`; the next harvest fills it in. |
| The harvest notes `paloalto GET /api/ show rule-hit-count: the vsys is not a vsys name …` | The virtual system is not a `vsysN` name, so the command was not sent. | Set **Virtual system** to the `vsysN` name on **Edit**. Meanwhile the rules are drawn without hit counts. |
| The harvest notes `paloalto GET /api/ show rule-hit-count: HTTP 403 …` or `… the answer is not a success` | The role cannot run the operational command, or the firewall answered it with an error. | Check that `Operational Requests` is enabled on the role's XML API tab; if it is, pass the note to your platform contact. Meanwhile the rules are drawn without hit counts. |
| The harvest notes `HTTP 400` on a REST listing | The REST version or the `location` the harvest sends is not what this PAN-OS version expects. | Set **REST API version** on **Edit**. This reader is validated on PAN-OS 11.2.15 with `v11.2`; on another version, pass the note to your platform contact. |
| An XML `type=config&action=set`, a `commit` or `show config running` answers `Investigation connections are read-only.` | The write gate. | Expected; name the rulebase or object subtree you need. |

The generic verdict strings are explained in [Test a connection and read the failure](/help/manage-connections.md#troubleshooting). Every connection status word is in the [status and error reference](/help/status-and-error-reference.md#connection-statuses).

## Next steps {#next-steps}

- Choose **Harvest now** on the connection's row in [Data sources](/portal/datasources) (in the product: `/portal/datasources`) to draw the firewall on the map: [Estate harvest](/help/estate-harvest-and-xray.md#estate-harvest).
- Select **Discover this connection** in the success dialog to find the services behind the firewall: [Launch a scan](/help/estate-harvest-and-xray.md#launch-a-scan).
- Give approved firewall changes their own credential: [Write connections and approved fixes](/help/setup-write-connections.md).

## Sources {#sources}

- API authentication: the key in `X-PAN-KEY`, a key lifetime, revoking all keys, `POST` for anything sensitive: https://docs.paloaltonetworks.com/ngfw/api/api-authentication-and-security
- API access, admin roles, the XML API tab and a separate admin account for API access: https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-panorama-api/pan-os-api-authentication/enable-api-access
- `type=keygen` as a `POST`, and what invalidates a key: https://docs.paloaltonetworks.com/ngfw/api/api-authentication-and-security/generate-api-key
- The API key lifetime setting: https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-admin/firewall-administration/manage-firewall-administrators/configure-administrative-accounts-and-authentication/configure-api-key-lifetime
- The REST request and response structure (`X-PAN-KEY`, `@status`, `result.entry[]`): https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-panorama-api/get-started-with-the-pan-os-rest-api/pan-os-rest-api-request-response-structure
- REST resources: https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-panorama-api/get-started-with-the-pan-os-rest-api/access-the-rest-api, the security rule fields: https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-panorama-api/get-started-with-the-pan-os-rest-api/create-security-policy-rule-rest-api, interfaces: https://docs.paloaltonetworks.com/ngfw/api/pan-os-rest-api-use-cases/configure-ethernet-interface-rest-api, virtual routers: https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-panorama-api/get-started-with-the-pan-os-rest-api/update-a-virtual-router-rest-api
- XML API configuration actions: https://docs.paloaltonetworks.com/ngfw/api/pan-os-xml-api-request-types-and-actions/configuration-api, operational commands: https://docs.paloaltonetworks.com/ngfw/api/pan-os-xml-api-request-types-and-actions/run-operational-mode-commands-api, log retrieval: https://docs.paloaltonetworks.com/ngfw/api/pan-os-xml-api-request-types-and-actions/retrieve-logs
