Skip to content

REST API CMDB

Ed Mozley edited this page Jul 3, 2026 · 1 revision

πŸ—„οΈ REST API: CMDB

The complete usage guide for the CMDB module of the REST API β€” classes, typed properties, configuration items, relationships, impact analysis and ticket links. 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 the CMDB:

🧬 Schema-driven Every class defines typed properties (text, number, date, boolean, dropdown, object_ref). Read the class first (GET /cmdb/classes/{id}), then write objects with a friendly property_key β†’ value map β€” the API validates types, required flags, dropdown options and object_ref target classes.
🌳 Hierarchy + graph Objects nest via parent_id (cycle-guarded) and connect via directed relationships with verb/inverse-verb pairs ("depends on" / "is depended on by").
πŸ’₯ Deletes take the tree Deleting an object removes its whole descendant tree, properties, relationships and ticket links (the module's design). Check GET .../impact first β€” the response tells you deleted_descendants.
πŸ›‘οΈ Ticket links are company-scoped The internal CMDB screen reads linked tickets unscoped (a known multi-tenancy gap); the API deliberately does not reproduce that β€” GET /cmdb/objects/{id}/tickets honours the key's company scope, and link/unlink gate the ticket.
πŸŽ›οΈ Classes are read-only in v1 Class design (properties, options, icons) stays an admin activity in the UI; the API reads definitions so integrations can build valid writes.

πŸš€ Quick start

Discover the shape, then create a CI with validated properties:

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"

# 1. What does a "server" need?
curl -s -H "$K" "$B/cmdb/classes" | jq '.data[] | {id, class_key, name}'
curl -s -H "$K" "$B/cmdb/classes/12" | jq '.data.properties[] | {property_key, type, is_required}'

# 2. Create it (required properties enforced; dropdowns validated against the option list)
curl -s -X POST "$B/cmdb/objects" -H "$K" -H "Content-Type: application/json" -d '{
  "name": "SQL01", "class_key": "server",
  "properties": { "hostname": "sql01.corp.local", "os": "Windows Server 2022" }
}'

# 3. Wire it into the graph
curl -s -X POST "$B/cmdb/objects/44/relationships" -H "$K" -H "Content-Type: application/json" \
  -d '{"to_object_id": 12, "verb": "depends on"}'

🧬 Classes

🟒 GET /cmdb/classes Β  πŸ”‘ cmdb_classes.read

All CI classes with class_key, icon, active flag and object counts.

🟒 GET /cmdb/classes/{id} Β  πŸ”‘ cmdb_classes.read

The class plus its full property definitions β€” everything needed to build a valid write:

{ "data": { "id": 12, "class_key": "server", "name": "Server",
    "properties": [
      { "id": 40, "property_key": "hostname", "label": "Hostname", "type": "text",
        "is_required": true, "target_class": null, "options": [] },
      { "id": 41, "property_key": "os", "label": "OS", "type": "dropdown",
        "is_required": false, "target_class": null,
        "options": [ { "value": "Windows Server 2022", "colour": null }, … ] } ] } }

πŸ—„οΈ Objects

🟒 GET /cmdb/objects β€” list / search Β  πŸ”‘ cmdb_objects.read

Parameter Description
class_id / class_key Filter by class
q Search by name
parent_id Children of an object Β· top_level=true for roots
is_planned true / false β€” planned vs live CIs
sort name (default), id, created_at, updated_at β€” prefix - for descending
page / per_page Pagination β€” default 1 / 25, max 100

πŸ”΅ POST /cmdb/objects β€” create Β  πŸ”‘ cmdb_objects.create

name + class_id/class_key required. properties is a map keyed by property_key. Validation mirrors the UI exactly β€” plus one improvement:

  • required properties enforced on create (422 naming the missing label)
  • number must be numeric Β· date must parse (ISO 8601) Β· boolean coerces sensibly
  • object_ref must exist, can't self-reference, and must match the property's target class
  • dropdown values must be one of the property's options (the UI stores anything β€” the API doesn't)

The class is immutable after creation, like the UI. Returns 201.

🟒 GET /cmdb/objects/{id} β€” get one Β  πŸ”‘ cmdb_objects.read

Fully hydrated: every class property with its typed value (object_ref values come with an embedded {id, name, class_name} card), parent, children, relationships.outgoing/incoming with natural-reading verbs, and the cached ai_summary.

🟠 PATCH /cmdb/objects/{id} β€” update Β  πŸ”‘ cmdb_objects.update

Update name, parent_id (existence + cycle-walk guard β€” you can't parent an object to its own descendant), is_planned, and any subset of properties β€” only the keys you send are touched (required checks apply only to sent properties, matching the UI's inline edit). Empty/null clears a property.

πŸ”΄ DELETE /cmdb/objects/{id} β€” delete Β  πŸ”‘ cmdb_objects.delete

Warning

Takes the whole tree. The object, all its descendants, their property values, relationships and ticket links are permanently removed (object_ref properties elsewhere that pointed at them are cleared). The response reports deleted_descendants β€” run GET .../impact first if you're not sure.

🟒 GET /cmdb/objects/{id}/impact β€” impact analysis Β  πŸ”‘ cmdb_objects.read

The blast radius before you touch something:

{ "data": { "descendants": [ { "id": 45, "name": "NODE1", "class_name": "Server", "depth": 1 } ],
    "referenced_by_property": [ { "id": 7, "name": "Payroll", "class_name": "Application", "property": "Runs on" } ],
    "incoming_relationships": [ { "id": 45, "name": "NODE1", "class_name": "Server", "relationship": "is depended on by" } ] } }

πŸ”— Relationships

πŸ”΅ POST /cmdb/objects/{id}/relationships Β  πŸ”‘ cmdb_relationships.create

Creates a directed edge from this object: {"to_object_id": 12, "verb": "depends on"} (or relationship_type_id). No self-links (422); the same from/to/type triple twice β†’ 409. The other side automatically reads with the inverse verb.

πŸ”΄ DELETE /cmdb/objects/{id}/relationships/{rel_id} Β  πŸ”‘ cmdb_relationships.delete

Removes the edge β€” it must involve this object (either direction).


🎫 Ticket links

🟒 GET /cmdb/objects/{id}/tickets Β  πŸ”‘ cmdb_ticket_links.read

The tickets linked to this CI β€” scoped to the key's companies (deliberately tighter than the internal endpoint).

πŸ”΅ POST /cmdb/objects/{id}/tickets Β  πŸ”‘ cmdb_ticket_links.create

Body: {"ticket_id": 141}. The ticket must be within the key's company scope (404 otherwise); already linked β†’ 409.

πŸ”΄ DELETE /cmdb/objects/{id}/tickets/{ticket_id} Β  πŸ”‘ cmdb_ticket_links.delete

Removes the link.


πŸ“š Reference data

Endpoint Permission Returns
🟒 GET /cmdb-relationship-types πŸ”‘ reference.read Verb + inverse-verb pairs (seeded: depends on, connects to, managed by)

πŸ§ͺ Worked example: discovery-tool sync

A network-discovery job upserting CIs and wiring dependencies (cmdb_classes: read + cmdb_objects: read/create/update + cmdb_relationships: create):

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"

# Upsert-by-name within the server class
ID=$(curl -s -H "$K" "$B/cmdb/objects?class_key=server&q=sql01" | jq -r '.data[0].id // empty')
if [ -n "$ID" ]; then
  curl -s -X PATCH "$B/cmdb/objects/$ID" -H "$K" -H "Content-Type: application/json" \
    -d '{"properties": {"os": "Windows Server 2022"}}'
else
  ID=$(curl -s -X POST "$B/cmdb/objects" -H "$K" -H "Content-Type: application/json" \
    -d '{"name":"SQL01","class_key":"server","properties":{"hostname":"sql01.corp.local"}}' | jq -r '.data.id')
fi

# The app depends on the freshly-synced server
curl -s -X POST "$B/cmdb/objects/$APP_ID/relationships" -H "$K" -H "Content-Type: application/json" \
  -d "{\"to_object_id\": $ID, \"verb\": \"depends on\"}"

And change-risk enrichment β€” what breaks if we reboot this?

curl -s -H "$K" "$B/cmdb/objects/$ID/impact" \
  | jq -r '.data.incoming_relationships[] | "\(.class_name): \(.name) (\(.relationship))"'

Under the hood: REST API β€” How It Works Β· Other modules: Tickets Β· Assets Β· Problems Β· Changes Β· Knowledge Β· Tasks Β· Keys & permissions: System β†’ API (System module) Β· Module docs: CMDB.

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally