-
Notifications
You must be signed in to change notification settings - Fork 15
REST API Software
The complete usage guide for the Software module of the REST API — the agent-collected application inventory and the licence register, with computed compliance numbers the UI doesn't have. Mirrors the interactive documentation at System → API → Documentation (with its live "Try it" tester).
Note
New to the API? The basics table on REST API: Tickets covers base URL, authentication, the response envelope, error codes, rate limits and PATCH semantics — identical across all modules.
What's distinctive about Software:
| 🤖 Inventory is read-only | The application catalogue and per-machine installs are 100% agent-owned (the inventory agent full-syncs each host) — analysts can't edit them in the UI and neither can the API. Licences are the writable half. |
| 🧮 Compliance is computed for you | Every licence carries app_installs (distinct non-system-component machines) next to its seat quantity, and app detail returns installs vs summed Active seats with seats_available — the seats-vs-installs comparison the UI never makes. Over-deployed software is one call away. |
| ⏳ Renewal logic server-side | The licence screen colours renewals client-side; the API computes renewal_status (ok / due_soon / overdue — due_soon = within each licence's own notice period, default 30 days) and offers matching list filters. |
| 🔑 Legacy keys stay out | This module's settings screen manages the old plaintext keys for the inventory agent/extension — that's a separate, older mechanism. The REST API uses its own fitsm_… keys. |
The licence-compliance question, answered in one call:
B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"
curl -s -H "$K" "$B/software/apps/227" | jq '.data.compliance'
# { "installs": 368, "licensed_seats": 100, "unmetered_licences": false, "seats_available": -268 }
# ↑ over-deployed by 268 machinesThe application catalogue with install counts (distinct machines) and licence counts.
| Parameter | Description |
|---|---|
q |
Search name and publisher |
filter |
apps (non-components — the UI's default tab), components, or all (default) |
sort |
name (default), publisher, install_count, id — prefix - for descending |
page / per_page
|
Pagination — default 1 / 25, max 100 |
{ "id": 227, "name": "Microsoft Intune Management Extension", "publisher": null,
"install_count": 368, "system_component": false, "licence_count": 1,
"first_detected": "2026-05-10T09:12:44Z" }The app with its licences and the computed compliance block: installs (distinct non-component machines), licensed_seats (sum of Active licence quantities), seats_available (negative = over-deployed 🔥), and unmetered_licences: true when an Active licence has no seat count (e.g. a site licence) — in which case seats_available is null rather than misleading.
Every machine it's installed on — hostname, version, install date, last seen — with asset_id so you can join straight to /assets/{id}.
| Parameter | Description |
|---|---|
app_id |
Licences for one application |
status |
e.g. Active
|
q |
Search app name, licence type and vendor contact |
renewal_within_days |
Renewal date within N days |
due_soon |
true = within each licence's own notice period, not yet overdue |
renewal_overdue |
true = renewal already passed 🔴 |
sort |
renewal_date (default), app, cost, created_at, id — prefix - for descending |
page / per_page
|
Pagination |
The licence shape:
{ "id": 19,
"app": { "id": 227, "name": "Microsoft Intune Management Extension", "publisher": null },
"licence_type": "Per-seat subscription", "licence_key": null,
"quantity": 100, "app_installs": 368,
"renewal_date": "2026-07-23", "renewal_status": "due_soon", "notice_period_days": 30,
"portal_url": null, "cost": 2400.0, "currency": "GBP", "purchase_date": null,
"vendor_contact": null, "notes": null, "status": "Active",
"created_by": { "id": 1, "name": "Administrator" },
"created_at": "2026-07-03T17:26:11Z", "updated_at": "2026-07-03T17:26:11Z" }quantity: 100 vs app_installs: 368 — your compliance report writes itself.
| Field | Required | Description |
|---|---|---|
app_id |
✅ | The application (validated — 422 on unknown) |
licence_type |
✅ | Free text, e.g. "Per-seat subscription" |
quantity |
Seat count — omit for site/unmetered licences | |
renewal_date / purchase_date
|
YYYY-MM-DD |
|
notice_period_days |
Drives due_soon (default 30) |
|
cost / currency
|
Amount + currency (default GBP) |
|
licence_key / portal_url / vendor_contact / notes / status
|
Admin fields (status defaults Active) |
created_by is stamped as the analyst the key acts as. Returns 201.
Everything creatable is patchable (created_by is never touched — UI parity). Delete is a clean leaf-table removal.
A read-only key (software_inventory: read + software_licences: read):
B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"
# Every licensed app where installs exceed Active seats
curl -s -H "$K" "$B/software/licences?status=Active&per_page=100" \
| jq -r '.data[] | select(.quantity != null and .app_installs > .quantity)
| "🔥 \(.app.name): \(.app_installs) installs vs \(.quantity) seats (\(.app_installs - .quantity) over)"'
# Renewals needing action (each licence's own notice window)
curl -s -H "$K" "$B/software/licences?due_soon=true&sort=renewal_date" \
| jq -r '.data[] | "\(.renewal_date) \(.app.name) \(.cost // 0) \(.currency)"'And the procurement direction — recording the true-up you just bought:
curl -s -X PATCH "$B/software/licences/19" -H "$K" -H "Content-Type: application/json" \
-d '{"quantity": 400, "cost": 9600, "notes": "True-up July 2026 (PO-1042)."}'Under the hood: REST API — How It Works · Other modules: Tickets · Assets · Problems · Changes · Knowledge · Tasks · CMDB · Contracts · Calendar · Keys & permissions: System → API (System module) · Module docs: Software.
FreeITSM — an open-source IT Service Management platform · github.com/edmozley/freeitsm · MIT licence
- Installation
- ⏰ Scheduled tasks (cron jobs)
- Architecture
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- Theming & Dark Mode
- ⌨️ Command palette (⌘K)
- 🔍 Searching inside tickets
- 📄 Attached documents
- Mobile‑Friendly
-
Security
- Layer 1 — which modules you can enter
- ↳ 🧩 Module Access Control
- ↳ 🛠️ Module Access — Developer Guide
- Layer 2 — what you can administer
- ↳ 🎭 Roles & Permissions
- ↳ 🛠️ Roles — Developer Guide
- ↳ 🔤 Why capabilities are constants
- Layer 3 — the System module
- ↳ 🔑 Admin Access Control
- Hardening
- ↳ 📄 Security review response 2026-08
- ↳ 🛡️ Security hardening 2026-08
- ↳ 🛠️ Security hardening 2026-08 — Developer Guide
- ↳ 🛡️ Round three — plain English
- ↳ 🛠️ Round three — Developer Guide
- Single Sign-On (SSO)
- 🗂️ LDAP & Active Directory
- Browser Extension
- API Reference
-
🔌 REST API — how it works
- ↳ 🎫 REST API: Tickets
- ↳ 💻 REST API: Assets
- ↳ 🔴 REST API: Problems
- ↳ 🟠 REST API: Changes
- ↳ 📚 REST API: Knowledge
- ↳ ✅ REST API: Tasks
- ↳ 🗄️ REST API: CMDB
- ↳ 📜 REST API: Contracts
- ↳ 🗓️ REST API: Calendar
- ↳ 💿 REST API: Software
- ↳ 🚦 REST API: Service Status
- ↳ ☀️ REST API: Morning Checks
- ↳ 📝 REST API: Forms
- ↳ ⚙️ REST API: Workflow
- ↳ 🗺️ REST API: Network Mapper
- ↳ 🧭 Using the API docs page
- ↳ 📐 OpenAPI specification
- ↳ ✅ OpenAPI: kept correct
- ↳ 🛠️ Maintaining the catalogue
- Watchtower
-
Tickets
- ↳ Mailbox Authentication
- ↳ 📤 Email send log
- ↳ Basic IMAP mailboxes
- ↳ Email rendering & images
- ↳ SLA Management
- ↳ WhatsApp channel
- ↳ 💬 Web chat channel
- ↳ 🟣 Slack channel
- ↳ 🔗 Linking tickets
- ↳ 🗒️ Canned responses
- ↳ ✉️ Limiting replies to particular senders
- ↳ ✍️ Email signatures
- ↳ 🌐 The public web address
- ↳ 🙋 Raising a ticket for someone else
- ↳ 🔀 Merging tickets
- ↳ ⑂ Splitting tickets
- ↳ ✅ Selecting several tickets
- ↳ 🛠️ Snoozing tickets — Developer Guide
- ↳ 👥 Collision detection
- ↳ ⏱️ Time tracking
- Problem Management
- Tasks
- Assets
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
- Forms
- Contracts
- Service Status
- 🔔 Notifications
- 🚨 War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- ↳ 📊 Progress tracker
- ↳ Concepts & vocabulary
- ↳ Email routing & mailboxes
- ↳ Settings: global vs per-company
- ↳ Users & self-service
- ↳ Staff cross-company access
- ↳ Worked examples
- ↳ Pitfalls & gotchas
- ↳ Scope: what it's for
- ↳ 🛠️ Developer Guide (make a module multi-company)
- ↳ 🗄️ Case study: CMDB (a linked graph)
- ↳ 🧪 Test harness (prove it's isolated)