Getting Started

Install

pip install pyfsr

Optional extras:

pip install "pyfsr[mcp]"    # bundled Model Context Protocol server
pip install "pyfsr[dev]"    # linters + test + docs + mcp extras

Connect

Create a FortiSOAR client with either an API token or a (username, password) tuple:

from pyfsr import FortiSOAR

# API token (recommended)
client = FortiSOAR("soar.example.com", "your-api-token")

# Username / password
client = FortiSOAR("soar.example.com", ("admin", "password"))

For self-signed appliances you can disable certificate verification (and silence the resulting warnings):

client = FortiSOAR(
    "soar.example.com",
    "your-api-token",
    verify_ssl=False,
    suppress_insecure_warnings=True,
)

See Authentication for environment-based config.

First calls

>>> client = demo_client()

>>> # Generic CRUD against any module
>>> incidents = client.records("incidents")
>>> incident = incidents.get("0740411d-e852-4eee-b33b-596210d09a9b")
>>> incident["name"]
'pyfsr doctest incident'

>>> # Raw REST escape hatch
>>> data = client.get("/api/3/alerts")
>>> data["hydra:totalItems"]
1

client.alerts.list()/.get(uuid) work the same way as the generic path above, via the typed, module-specific AlertsAPI — see Working with Records for the typed-model walkthrough.

Creating records & picklists

Picklist fields (severity, status, …) are stored as IRIs, not friendly strings — but pyfsr resolves friendly values for you automatically, so you can just pass "High":

alert = client.alerts.create(
    name="Test Alert",
    description="This is a test alert",
    severity="High",        # resolved to its IRI automatically
)

Same on the generic record path — captured live (created, fetched, deleted in the same session; box left with no extra incidents):

>>> created = client.records("incidents").create(
...     {"name": "pyfsr doctest incident", "description": "temporary, will be deleted",
...      "severity": "Critical"},
...     resolve_picklists=False,   # already an IRI-resolved doctest fixture; see note below
... )
>>> created["name"]
'pyfsr doctest incident'

Note

Resolution is on by default (the example above passes resolve_picklists=False only because this doctest replays a captured response rather than a live metadata lookup). Pass it yourself to skip resolution — and the metadata lookup it needs — when every value you send is already an IRI.

Next steps