How to Export FortiSIEM Logs

How to Export FortiSIEM Logs

SOC Prime Team
SOC Prime Team linkedin icon Follow

Use FortiSIEM’s REST event query API. Post an XML query to /phoenix/rest/query/eventQuery, which returns a query ID, poll the progress until it reaches 100, then fetch the events. The results come back as XML. The original log line of each event is in the rawEventMsg attribute, so a few lines of Python turn the result into raw logs. Exports from the Analytics screen come out in formats LogTotal doesn’t read today. 

FortiSIEM is common wherever Fortinet runs the network, and it often holds far more than firewall logs. Prime Core has 19,692 detection rules for FortiSIEM, mapped to 664 MITRE ATT&CK techniques. Below is how to get events out, sanitize them, and investigate them for free in LogTotal.

Get Started For Free

Before you start

An API user. Use an account with rights to run analytics queries. The API authenticates with basic auth, with the organization in the username: super/<user> on an enterprise install, <org>/<user> for a specific organization in a service provider install.

Retention. Online event storage is limited. Older events may sit in archive storage that needs extra steps. 

Attribute names. FortiSIEM queries use its own attribute names, such as reptDevName (reporting device), reptDevIpAddr, eventType and phRecvTime. Build the filter in Analytics first.

Export with the event query API

Save the query as query.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Reports><Report><Name>LogTotal export</Name><Description/>
  <SelectClause><AttrList>phRecvTime,reptDevIpAddr,eventType,rawEventMsg</AttrList></SelectClause>
  <ReportInterval><Low>1792368000</Low><High>1792454400</High></ReportInterval>
  <PatternClause><SubPattern id="1" name="Filter">
    <SingleEvtConstr>reptDevName = "web-03"</SingleEvtConstr>
  </SubPattern></PatternClause>
</Report></Reports>

The interval is epoch seconds for 2026-10-19 00:00 UTC to 2026-10-20 00:00 UTC. Then run it:

FSM="https://fortisiem.example.com"
AUTH="super/apiuser:$FSM_PASS"

QID=$(curl -sS -u "$AUTH" -X POST -H 'Content-Type: text/xml' --data @query.xml "$FSM/phoenix/rest/query/eventQuery")
until [ "$(curl -sS -u "$AUTH" "$FSM/phoenix/rest/query/progress/$QID")" = "100" ]; do sleep 5; done
curl -sS -u "$AUTH" "$FSM/phoenix/rest/query/events/$QID/0/1000" > fsm_web03_1019.xml

The last two path segments are the start offset and the count. Page through large results in steps of 1,000. Then pull out the raw messages:

import xml.etree.ElementTree as ET

import xml.etree.ElementTree as ET

root = ET.parse("fsm_web03_1019.xml").getroot()
with open("fsm_web03_1019.log", "w") as out:
    for attr in root.iter("attribute"):
        if attr.get("name") == "rawEventMsg" and attr.text:
            out.write(attr.text.strip() + "\n")

Upload, sanitize and review in LogTotal

  1. Upload. Open logtotal.com and drop in the file.
  2. Sanitize.
  3. Review.

What this looks like on real data. 

When it goes wrong

SymptomLikely causeFix
401Organization missing from the usernameUse super/<user> or <org>/<user>
Query returns an error instead of an IDXML syntax or an unknown attribute nameTest the filter in Analytics; check attribute names
Progress never reaches 100Query too broadNarrow the time range and filter
rawEventMsg emptyThe attribute wasn’t selectedAdd rawEventMsg to AttrList
Old events missingThey’re in archive storageCheck archive options

FAQ

Why XML?

That’s what this FortiSIEM API speaks. The Python step converts it to the original raw lines, which is usually what you want to upload anyway.

Can I export incidents instead?

Incidents have their own API calls. For LogTotal, export the events behind them.

Join SOC Prime's Detection as Code platform to improve visibility into threats most relevant to your business. To help you get started and drive immediate value, book a meeting now with SOC Prime experts.