QRadar API

Authoritative QRadar REST API mechanics for real-world SIEM work: authentication, Ariel search orchestration, offense pulls, asset queries, and JSON shaping.

The QRadar REST API uses SEC header authentication, not Bearer token authentication. This is non-standard and differs from most REST APIs. Secrets are sourced via dsec d001 dev/network, which exports QRADAR_TOKEN and QRADAR_HOST into the shell environment.

All Ariel searches are asynchronous: submit, poll, fetch. There is no synchronous query path via the API.

Authentication Model

Header Value

SEC

Authorized Service token generated under Admin → Authorized Services

Accept

application/json

Content-Type

application/json only when required for POST with JSON body

The SEC header is QRadar-specific. Do not substitute Authorization: Bearer; it will not authenticate.

Authorized Services are only visible to roles with full admin access. Read-only configuration roles cannot create tokens. If the option is not visible under the Admin tab, open a ticket for token provisioning.

Ariel Search Model

Ariel searches follow a three-step asynchronous pattern:

  1. Submit - POST /api/ariel/searches returns a search_id and initial status of WAIT

  2. Poll - GET /api/ariel/searches/{search_id} until completed is true

  3. Fetch - GET /api/ariel/searches/{search_id}/results to retrieve data

Results are returned as JSON. The events array contains the result rows. Redirect to a file with > for downstream processing with jq or pandas.

In QRadar 7.5.0 UP13, submitting the query as a JSON body via --data returns error 1005. Use query_expression= as a URL parameter instead.

Error Semantics

HTTP Code QRadar Code Meaning

200

 — 

Success

422

 — 

Malformed request, usually shell escaping issue with query string. Write query to a file or use URL encoding.

422

1005

Invalid parameter. Query submitted as JSON body instead of URL parameter in QRadar 7.5.0 UP13.

401

 — 

Invalid or expired token. Regenerate via Admin → Authorized Services.

404

 — 

Search ID not found. Search may have expired. Default retention is 24 hours.

Operational Gotchas

Production-verified against QRadar 7.5.0 UP13 at CHLA. Validate behavior against your specific version before using in automation.

Gotcha Detail

JSON body POST returns error 1005

QRadar 7.5.0 UP13 rejects --data JSON body for Ariel searches. Use query_expression= URL parameter instead.

422 on POST

Usually a shell escaping issue. Write the query to a file or switch to URL parameter format.

GET on searches endpoint returns GUIDs

GET /api/ariel/searches returns existing search IDs, not API documentation. Use /api/help/capabilities for endpoint discovery.

SEC header not Bearer

QRadar uses SEC: token, not Authorization: Bearer token. Easy to get wrong when copying generic REST API examples.

Authorized Services not visible

Requires full admin role. Read-only configuration access cannot create tokens. Open a ticket if not visible.

Search results expire

Default search retention is 86400000 ms (24 hours). Results are gone after that and must be re-queried.

Ariel retention approximately 3 days at CHLA

QRadar 7.5.0 UP13 at CHLA had roughly 3 days of Ariel data available. For longer windows, extend retention or pull from archive.

Command Patterns

curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/help/capabilities"
# Query must be URL-encoded and passed as query parameter.
# JSON body POST returns error 1005 in QRadar 7.5.0 UP13.
curl -k -X POST \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/ariel/searches?query_expression=SELECT+sourceip+FROM+events+LIMIT+5"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/ariel/searches/$SEARCH_ID"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/ariel/searches/$SEARCH_ID/results" \
  > /tmp/qradar_results.json
# Full automated submit -> poll -> fetch workflow
# Usage: pass URL-encoded query as $1
SEARCH_ID=$(curl -s -k -X POST \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/ariel/searches?query_expression=$1" \
  | jq -r '.search_id')

printf 'Search submitted: %s\n' "$SEARCH_ID"

while true; do
  STATUS=$(curl -s -k \
    -H "SEC: $QRADAR_TOKEN" \
    -H "Accept: application/json" \
    "https://$QRADAR_HOST/api/ariel/searches/$SEARCH_ID" \
    | jq -r '.status')
  printf 'Status: %s\n' "$STATUS"
  [ "$STATUS" = "COMPLETED" ] && break
  sleep 3
done

curl -s -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/ariel/searches/$SEARCH_ID/results" \
  > /tmp/qradar_results.json

printf 'Results: %s\n' /tmp/qradar_results.json
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/siem/offenses?fields=id,description,magnitude,status,offense_source"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/siem/offenses?filter=status%3DOPEN&sort=-magnitude"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/siem/offenses/$OFFENSE_ID/rules"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/asset_model/assets?limit=100&offset=0"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/config/event_sources/log_source_management/log_sources"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/config/event_sources/log_source_management/log_source_types"
curl -k \
  -H "SEC: $QRADAR_TOKEN" \
  -H "Accept: application/json" \
  "https://$QRADAR_HOST/api/config/event_retention_buckets"
cat /tmp/qradar_results.json | jq '.events | length'
cat /tmp/qradar_results.json | jq '.'
cat /tmp/qradar_results.json | jq '.events[] | {source: .LogSource, count: .EventCount}'
cat /tmp/qradar_results.json | jq '.events[] | select(.severity >= 7)'
cat /tmp/qradar_results.json | jq -r '.events[] | [.LogSource, .EventCount] | @csv'
cat /tmp/submit_response.json | jq -r '.search_id'
cat /tmp/poll_response.json | jq -r '.status'

Quick Reference

Operation Command

Load credentials

dsec d001 dev/network

Validate token

curl -k -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/help/capabilities"

Submit AQL search

curl -k -X POST -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/ariel/searches?query_expression=SELECT+…​"

Poll search status

curl -k -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/ariel/searches/$SEARCH_ID"

Fetch results

curl -k -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/ariel/searches/$SEARCH_ID/results" > /tmp/out.json

List offenses

curl -k -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/siem/offenses"

List log sources

curl -k -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/config/event_sources/log_source_management/log_sources"

List assets

curl -k -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/asset_model/assets"

Check retention

curl -k -H "SEC: $QRADAR_TOKEN" -H "Accept: application/json" "https://$QRADAR_HOST/api/config/event_retention_buckets"

Count results

`cat /tmp/qradar_results.json

jq '.events

length'`

Extract to CSV

`cat /tmp/qradar_results.json

jq -r '.events[]

[.LogSource, .EventCount]

Key gotchas:

  • Use SEC header, not Bearer authentication.

  • Submit POST query as URL parameter, not JSON body.

  • Poll until completed is true before fetching results.

  • Search results expire after 24 hours.