Skip to main content

PaloAlto Cortex XDR

Fluency collects Cortex XDR detection data through Palo Alto Networks' Cortex XDR public API. Cortex XDR is both a sensor and a correlation layer: its agents and the firewalls, cloud logs and identity sources feeding it produce alerts, and its analytics engine groups related alerts into incidents. What the API exposes is therefore already triaged — scored, grouped, and mapped to MITRE ATT&CK — which makes it good material for driving tickets and a poor substitute for raw endpoint telemetry if you need to hunt across process trees.

Authentication is a two-part credential: an API Key and the numeric API Key ID that identifies it, both sent as headers. Cortex issues keys at one of two security levels, and that choice has to be mirrored back in Fluency. No agent is installed and nothing is pushed from Palo Alto — Fluency polls.

The setup has two halves:

  1. In Cortex XDR — generate an API key with a read-only role, then collect the key, its ID, and the tenant's API URL.
  2. In Fluency — install the PaloAlto Cortex XDR application template and paste those values into its form.
Cortex XDR 5 renamed incidents and alerts in the console — not in the API

From Cortex XDR 5, Incidents are called Cases and Alerts are called Issues, and the Alert Source field is now Detection Method. Palo Alto states that existing APIs continue to function as expected after the upgrade, including the Alerts and Incidents APIs, and adds new Cases and Issues APIs alongside them. This page uses incidents and alerts, because that is what the API this integration calls still says. If your console shows Cases and Issues, you are on Cortex XDR 5 and reading the right page.

What arrives

An API key inherits its permissions from the role assigned at creation, so what a read-only role reaches is the ceiling of what this integration can collect. Every call is a POST, even the reads:

StreamEndpointLicence requiredContents
Incidents/public_api/v1/incidents/get_incidentsCortex XDR Prevent, Pro per Endpoint, or Pro per GBCorrelated groups of alerts — severity, status, assignee, the scoring that drove them, per-severity alert counts, the hosts and users involved, MITRE tactic and technique IDs, and an xdr_url deep link back into the console.
Alerts/public_api/v1/alerts/get_alertsCortex XDR Prevent, Pro per Endpoint, or Pro per GBIndividual detections, after Cortex has applied its own alert exclusions. Each carries a nested events array with the process, file and network detail behind it — image paths, command lines, SHA256 hashes — so alerts are far larger per record than incidents.
Management audit logs/public_api/v1/audits/management_logsnoneConsole activity — sign-ins, configuration changes, response actions — as AUDIT_ENTITY / AUDIT_ENTITY_SUBTYPE pairs with an owner and a result.
Agent audit reports/public_api/v1/audits/agents_reportsCortex XDR Prevent, Pro per Endpoint, or Pro per GBAgent-side events: installs, upgrades, policy applications, scan results.

Incidents arrive as incidents, not as a stream of the alerts inside them. An incident's alert_count tells you how many alerts it groups, and the alert bodies come from the Alerts API — which is why a pipeline that wants both is polling two endpoints, not one.

The template decides which of these it polls — the form does not

PaloAlto Cortex XDR takes four parameters and none of them selects a stream. To see what your installation actually created and where it writes, open the installed application's details panel with the blue eye button and read its Actions list, which records every object the install made. Confirm it is running covers what to look for.

Before you begin

A Cortex XDR licence that covers the APIs you want. The Incidents and Alerts APIs need Cortex XDR Prevent, Cortex XDR Pro per Endpoint or Cortex XDR Pro per GB. This is the one prerequisite that does not fail loudly: a key with the right role on a tenant without the right licence authenticates successfully and then returns 402 Unauthorized access. User does not have the required license type to run this API. Management audit logs need no licence at all, which makes them a useful control when you are trying to tell a licence problem from a credential problem.

An administrator who can reach Settings → Configurations → Integrations → API Keys. The roles offered in the key's Role list are whatever has been defined for the tenant, in Cortex Gateway or in Cortex XDR Access Management — so if the read-only role you want is not on that list, it has to be created there first.

The tenant's API URL — copied, not constructed. Cortex XDR is deployed into one of 21 regions, and the host name carries both the tenant and the region: https://api-<tenant>.xdr.<region>.paloaltonetworks.com. Step 4 copies it out of the console. Do not type it from memory.

The console URL and the API URL differ by five characters

The address in the administrator's browser is https://<tenant>.xdr.<region>.paloaltonetworks.com. The API host is the same name with api- in front of it. Paste the console URL into Fluency and you get a host that resolves, answers, and returns the sign-in page instead of JSON — a failure that looks nothing like a bad credential. Use Copy API URL and you cannot get this wrong.

On Cortex XDR 5, check whether Scope Based Access Control is on. SBAC is disabled by default under Settings → Configurations → General → Server Settings. Where it has been enabled, an API key also carries a Scope, and a key whose scope excludes the assets you care about authenticates, returns 200, and returns nothing. If SBAC is on in this tenant, set the key's scope deliberately in step 2 rather than accepting the default.

Access to the Fluency portal with permission to install applications.

Part 1 — Cortex XDR

These captures are of the Cortex XDR 3.x console

The screenshots in this section are borrowed from another vendor's published guide and show the pre-5 Generate API Key dialog, with a General tab and a Components accordion. On Cortex XDR 5 the same dialog has a Role tab and a Scope tab instead; the fields named below are all still there, under Role. The navigation path is unchanged.

1. Open the API Keys page

In the Cortex XDR console, select Settings at the foot of the left rail, then Configurations.

Cortex XDR left rail with Settings selected and the Configurations item highlighted in the flyout menu

In the CONFIGURATIONS panel, scroll to Integrations and select API Keys.

Configurations panel showing the Integrations group with API Keys highlighted

2. Create the key

On the API Keys page, select + New Key.

Generate API Key dialog with Advanced selected under Security Level and a read-only role checked in the Role list

  • Security LevelAdvanced. See the caution below; this is the field that has to agree with Fluency.
  • Role — a read-only role. See the tip below.
  • Enable Expiration Date — optional, and worth using. Cortex tracks the expiry on the API Keys page and raises an API Key Expiration notification in the Notification Center one week and one day before the date. Fluency gives you no such warning, so this checkbox is the only advance notice you will get.
  • Comment — free text. Say which Fluency instance holds the key, so a later reader of this list knows what revoking it would break.
  • Scope — Cortex XDR 5 only, and only relevant where SBAC has been enabled. See Before you begin.

Select Generate.

Security Level has to match the AuthMode parameter in Fluency

The two levels are not two strengths of the same credential — they are two different ways of signing a request. A Standard key is sent verbatim in the Authorization header. An Advanced key is never sent at all: the client hashes it together with a nonce and a timestamp and sends the digest, which is why Palo Alto describes Advanced as replay-resistant and unsuitable for plain cURL.

The Fluency template records that choice in its AuthMode parameter, which arrives pre-filled with advanced. Generate an Advanced key and the default is already right. Generate a Standard key and you have a free-text field to correct with a value the form does not offer, does not validate, and does not document — so unless you have a reason to prefer Standard, choose Advanced and leave AuthMode alone.

Pick a read-only role

This integration only reads. Palo Alto ships a default role called Viewer, described as broad read-only access across almost all areas — dashboards, policies, endpoints, configurations and audit — with no edit, respond or configure permissions. That is the right shape for a collector: it covers every stream in What arrives and it cannot isolate an endpoint or change a policy if the key leaks.

Do not reach for Instance Administrator because it is the one you recognise. A role that turns out too broad is a standing risk; a role that turns out too narrow fails as 403 Forbidden access. The provided API Key does not have the required RBAC permissions to run this API. after the application is already installed, which is a more expensive place to discover it than the verification step below.

Tenants often define their own read-only roles too — the capture above shows one named Read-Only. Either works, provided it can view incidents and alerts.

3. Copy the API key

Cortex shows the generated key once.

Generated Key dialog with the key value redacted, a copy button, and the notice that the key will not be accessible once the window is closed

Copy the key now — Cortex will not show it again

The dialog says it plainly: "This key will not be accessible once you close this window." There is no reveal and no regenerate. If you lose it, delete the key on the API Keys page and generate a new one.

4. Read the API Key ID and the API URL

The key you just copied is only half the credential, and the other half is not in that dialog — it is a column in the table behind it.

API Keys table showing the ID column and the Copy API URL button

  1. Find your key's row and note the value in the ID column. It is a small integer — 1, 2, 3 — not a long string.
  2. With the row selected, click Copy API URL. That puts https://api-<tenant>.xdr.<region>.paloaltonetworks.com on the clipboard. Paste it somewhere you can read before it is overwritten.
The ID is a counter, not a key

The API Key ID is a one- or two-digit number; The API Key is a long random string. They are easy to tell apart and still easy to swap, because the ID field is short and a short field invites whatever short value is on the clipboard. A transposed pair authenticates as nothing and returns 401, exactly like a mistyped key.

You should now be holding four values:

ValueWhere it came from
API KeyThe Generated Key dialog in step 3
API Key IDThe ID column of the API Keys table
API URLThe Copy API URL button, scheme and api- prefix included
Security LevelAdvanced or Standard, as chosen in step 2

The console, the Fluency form and Palo Alto's API reference each name these differently:

Value in the Cortex XDR consoleFluency parameterSent to the API as
The key from the Generated Key dialogThe API KeyAuthorization — verbatim for a Standard key, as a SHA-256 digest for an Advanced one
ID columnAPI Key IDx-xdr-auth-id
Copy API URLTenant API base URLthe request host
Security LevelAuthModenot a header — it selects which headers are sent

Verify before you leave Cortex XDR

One request confirms the URL, the key, the ID, the role and the licence together. For an Advanced key, Cortex expects the SHA-256 digest of the key, a 64-character nonce and a millisecond timestamp concatenated in that order:

FQDN='api-yourtenant.xdr.us.paloaltonetworks.com'
KEY='<the API Key>'
KEYID='<the API Key ID>'

NONCE=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 64)
TS=$(( $(date -u +%s) * 1000 ))
SIG=$(printf '%s%s%s' "$KEY" "$NONCE" "$TS" | sha256sum | cut -d' ' -f1)

curl -s -w '\n%{http_code}\n' -X POST "https://$FQDN/public_api/v1/incidents/get_incidents" \
-H "x-xdr-timestamp: $TS" \
-H "x-xdr-nonce: $NONCE" \
-H "x-xdr-auth-id: $KEYID" \
-H "Authorization: $SIG" \
-H "Content-Type: application/json" \
-d '{"request_data":{"search_from":0,"search_to":1}}'

With a Standard key, drop the x-xdr-timestamp and x-xdr-nonce headers and send Authorization: $KEY unhashed — everything else is identical. On macOS, use shasum -a 256 in place of sha256sum.

ResponseWhat it means
200 with an incidents arrayURL, key, ID, role and licence are all correct.
200 with "result_count": 0The credential is fine; the tenant had no incidents matching, or SBAC is scoping them away. See Confirm it is running before treating this as a fault.
400 Bad Request. Got an invalid JSON.The request body is malformed — check the -d argument survived the paste.
401 Unauthorized access.Wrong key, wrong ID, the two swapped, an expired key, or an Advanced key signed as Standard. Back to step 2.
402 Unauthorized access. User does not have the required license type to run this API.The credential is good and the tenant's licence does not cover this API. Re-run against /public_api/v1/audits/management_logs, which needs no licence — a 200 there confirms the key and isolates the problem to entitlement.
403 Forbidden access.The key authenticated but its role is too narrow. Generate a new key with a read-only role that can view incidents and alerts.
429 / Too many requestsMore than 10 requests per second reached the tenant, across every consumer of its API. Wait and retry.
An HTML sign-in page instead of JSONThe host is the console, not the API. Add the api- prefix, or use Copy API URL.
curl: (6) Could not resolve hostThe host name is mistyped. Copy it from the console.

Part 2 — Fluency

Install the Application

Go to Platform → Applications → Install Application From Template and choose PaloAlto Cortex XDR from the Endpoint Management category. Every parameter is required:

ParameterNotes
Tenant API base URLThe value from Copy API URL in step 4, pasted whole: scheme, api- prefix, no trailing path. Not the console URL.
API Key IDThe small integer from the ID column — the identifier of the key, not the key itself.
AuthModeA plain text field, not a drop-down, pre-filled with advanced. It records the Security Level the key was issued at. Leave it alone if you followed step 2.
The API KeyThe key value from step 3. Masked once the application is installed.
datalakePre-filled managed.
datalake index namePre-filled Cortex. Two applications writing to the same index name in the same lake will collide, and the second one aborts.

Setup New PaloAlto Cortex XDR Application panel

Leave Name and Display Name at default / Default unless you are installing a second instance — collecting from two Cortex tenants, for example — in which case give each one a name you will recognise on the applications list, and give the second one its own datalake index name.

Press Install. The application then appears in the Installed Applications view, where its badge reads Running once the pipeline is up.

Confirm it is running

The application appears under Installed Applications as PaloAlto Cortex XDR: Default. Its badge should read Running in green within a few seconds; Aborted in red means the pipeline stopped on an error, and the details panel will carry the message.

Every field in that panel is read-only. Changing the key, the ID, the URL or the AuthMode means uninstalling the application and installing it again.

An empty Cortex index shortly after install is not by itself evidence of a fault. Cortex XDR only raises incidents when its analytics correlate something, and a quiet estate can go days without one. Before treating silence as a failure, work down this list:

  1. Open Incident Response in the Cortex XDR consoleCases on Cortex XDR 5 — for the same time window. If Palo Alto's own queue is empty, so is the feed, and nothing is wrong.
  2. Check the licence with the management_logs probe from Verify before you leave Cortex XDR. A 200 there and a 402 on incidents is an entitlement problem, not a collection problem.
  3. Check SBAC, if this tenant has it enabled. A key with no scope sees no cases and no issues.
  4. Only then go to Troubleshooting.

See Confirm data is arriving for how to check that events are landing.

Maintenance

Rotating the API key

If you set an expiry, Cortex will tell you a week ahead in its own Notification Center — but nothing tells Fluency, and collection simply stops on the day. Rotate before then:

  1. In Cortex XDR, go to Settings → Configurations → Integrations → API Keys and generate a new key with the same Security Level and role. Leave the old key in place for now.
  2. Copy the new key, and note its new ID — a new key gets a new ID, and reusing the old one is the most common way to get a 401 out of a rotation.
  3. In Fluency, uninstall the PaloAlto Cortex XDR application and install it again with the new key and ID. Template parameters are read-only after install, so reinstalling is the supported way to change a credential.
  4. Once data is flowing again, delete the old key in Cortex XDR. Generating a new key does not revoke the old one — it stays valid until you remove it.

Removing the integration

Uninstall the application in Fluency first, so the pipeline stops cleanly before its credentials stop working. Then delete the key on the Cortex XDR API Keys page.

Troubleshooting

SymptomLikely causeFix
The application shows Aborted immediately after installThe key was mistyped — it is shown exactly once, so a bad paste is easy — or the base URL is missing its api- prefixUninstall, then reinstall. If the key was never captured, delete it and generate a new one; it cannot be recovered.
Every call returns 401 although the key was pasted correctlyThe API Key ID and The API Key are the wrong way round, the ID belongs to a different key, or AuthMode does not match the key's Security LevelCheck the ID against the ID column, and check AuthMode against the SECURITY LEVEL column on the same page.
Authentication succeeds, then every call returns 402The tenant's licence does not cover the Incidents and Alerts APIsConfirm with the management_logs probe, then take it to your Palo Alto account team — no key can work around this.
Authentication succeeds, then every call returns 403The key's role cannot view incidents and alertsGenerate a new key with a read-only role that can, and reinstall.
The application is Running, no data, and the console shows incidentsSBAC is enabled and the key's scope excludes themGenerate a key with the scope you need and reinstall.
Collection worked, then stopped on a dateThe key hit the expiry set when it was createdRotate the key.
Collection stops with no expiry dueThe key was deleted, or the role behind it was changed or removedCheck the API Keys page and the role's permissions; generate a fresh key and reinstall.
429 in the logsThe tenant is over 10 requests per second across all API consumers — Fluency, XSOAR, a script, another SIEMGive each consumer its own key so the traffic is attributable, then reduce whatever is loudest. A second Fluency instance polling the same tenant doubles the load for no benefit.
An HTML page in the logs where JSON was expectedThe Tenant API base URL is the console URLReinstall with the value from Copy API URL.
The customer runs Cortex XSIAM, Cortex XSOAR or Cortex Cloud and has no Cortex XDR consoleThose are different products on the same platformThis template does not apply to them.

Under the hood

Engineering reference — the API surface behind this integration

The Fluency template's internal polling schedule and output format are not exposed on the form. What follows is Palo Alto's side of the contract, which bounds anything the template can do.

Authentication

Every request carries x-xdr-auth-id: {key_id}. What goes in Authorization depends on the key's security level:

Security LevelHeadersAuthorization contains
StandardAuthorization, x-xdr-auth-idThe API key, verbatim
AdvancedAuthorization, x-xdr-auth-id, x-xdr-timestamp, x-xdr-noncesha256(api_key + nonce + timestamp), hex-encoded

The nonce is 64 random alphanumeric characters, generated fresh per request. The timestamp is the current UTC time in milliseconds. Neither is a secret; together they make a captured request useless to replay. The key itself never crosses the wire in Advanced mode, which is the whole point of it.

There is no token exchange, no refresh and no OAuth flow — the key generated in the console is the credential until it expires or is deleted, and its permissions are fixed at creation by the role assigned to it.

Endpoints and paging

POST /public_api/v1/incidents/get_incidents
POST /public_api/v1/alerts/get_alerts
POST /public_api/v1/audits/management_logs
POST /public_api/v1/audits/agents_reports

All are POST with a JSON body of the shape {"request_data": {...}}; an empty request_data returns everything. Paging is by offset — search_from and search_to — with a maximum result set size of 100 per call, so a busy day is a loop, not a request. Filters combine with AND only; OR is not supported. Timestamps in both directions are epoch milliseconds.

total_count is capped at 10,000: a filter matching more than that does not report a true total, and you page through the result set rather than reading one. Some response fields are permission-dependent — original_tags and tags on an incident are only returned to a key whose role has full permissions — so a narrower role produces a slightly narrower record, not an error.

Cortex XDR 5 adds /public_api/v1/case/search and /public_api/v1/issue/search as the successors to the incidents and alerts endpoints, and Palo Alto recommends moving to them over time. The older endpoints remain supported.

Limits

There is a limit of 10 API requests per second for each tenant. This includes all endpoints.

That budget is per tenant, not per key, so every consumer of the Cortex API shares it — Fluency, XSOAR, any home-grown script. Exceeding it returns 429 and a Too many requests error. Palo Alto notes that these limits are subject to change.

Retention, and what it bounds

An outage longer than Cortex's retention window is unrecoverable — the data is gone from Palo Alto's side, not merely un-collected.

DataCortex XDR PreventCortex XDR per Endpoint / Cloud per HostCortex XDR per GB
Case and Issue data (incidents and alerts)186 days, minimum 200 endpoints186 days186 days
Query data186 days186 days186 days
Ingested datanot applicable31 days31 days
Forensic datanot applicable365 days, with the Forensics add-on

Incidents and alerts sit in the 186-day tier, which is generous as these integrations go. The 31-day figure on ingested data is the one to watch if you are ever asked to backfill from Cortex's raw logs rather than from its detections. Both can be extended with paid retention add-ons.

References

Palo Alto Networks

Fluency