Skip to content

State Models

The State Models feature provides four independent, lifecycle-managed state dimensions for tracking the operational context of Devices and Virtual Machines:

Model Applies To State Values
PowerState Device, VirtualMachine Configurable via StateType / State (catalog keyed to power state)
OSState Device, VirtualMachine Configurable via StateType / State (catalog keyed to os state)
RuntimeState Device, VirtualMachine Configurable via StateType / State (catalog keyed to runtime state)
AllocationState Device only Configurable via StateType / State (catalog keyed to allocation state)

Every state record is one-per-object: a device or VM can hold at most one record of each state type. Transitions are validated against StateTransitionRule entries, auto-timestamped, and attributed to the actor (user or system) that performed them. The full audit history lives in the NetBox change log.

Breaking change: PowerState now uses the state catalog

As of migration 0017/0018, PowerState.current_state and PowerState.previous_state are FK references to State, not fixed "on"/"off" strings. You must create a StateType named power state with the desired states (e.g. on, off) before creating PowerState records. Existing records are automatically back-filled from the old string values to matching State objects.


Architecture Overview

StateType  ←──── State  (many states per type)
    │                 ↑
    └─── StateTransitionRule  (from_state → to_states)
                      │
             ┌────────┴──────────────────────┐
         PowerState   OSState   RuntimeState   AllocationState
        (device/VM)  (device/VM) (device/VM)   (device only)
  • StateType is a named category (e.g. power state, os state, runtime state, allocation state). Names are stored lower-case.
  • State is one named value within a type (e.g. on, off, running, stopped). Exactly one state per type may be flagged is_initial.
  • StateTransitionRule defines which target states are reachable from a given source state. If no rule exists for the current state, the transition is blocked.
  • All four lifecycle models use FK references to State records — there are no fixed enum values.

Quick Setup Guide

Before creating any state record, you must configure the state catalog for that lifecycle:

  1. Create a StateType — e.g. power state, os state, runtime state, allocation state
  2. Create States for that type — e.g. on, off; mark one is_initial = true
  3. Create StateTransitionRules — define which states may follow which

Once configured, the state card on any Device or VM detail page will offer a one-click Create button that initialises the record at the is_initial state.

Minimum setup for PowerState (the most common first step):

# 1. Create the power state StateType
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-types/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"name": "power state"}'
# → id: 1

# 2. Create the on/off states (mark "off" as initial)
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/states/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '[
    {"state_type": 1, "name": "off", "color": "9e9e9e", "is_initial": true},
    {"state_type": 1, "name": "on",  "color": "4caf50", "is_initial": false}
  ]'
# → ids: 1 (off), 2 (on)

# 3. Create transition rules (on↔off bidirectional)
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"state_type": 1, "from_state": 1, "to_states": [2]}'  # off → on

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"state_type": 1, "from_state": 2, "to_states": [1]}'  # on → off

Common Fields (all state models)

All state models inherit from StateModel, which itself extends NetBoxModel:

Field Type Description
id integer Auto-generated primary key
transitioned_at datetime (auto) Timestamp of the last state change (auto_now)
transitioned_by string (auto) Username of the actor; set automatically from the active request
transition_source string Source of the transition; writable for all state models
created datetime Record creation timestamp
last_updated datetime Last DB-write timestamp
tags array NetBox tags
custom_fields object NetBox custom fields

transition_source choices

Value Label
user User (default)
system System
api API
automation Automation
monitoring Monitoring

PowerState

Tracks the power state of a Device or Virtual Machine. Uses the state catalog keyed to StateType name power state.

State names accepted directly — no need to look up IDs

The current_state field accepts either a state name string (e.g. "on", "off") or an integer PK. Use whichever is more convenient. Responses always return the state name string. This applies to all four state models (PowerState, OSState, RuntimeState, AllocationState).

Model Fields

Field Type Writable Description
assigned_object_type content type ✅ create-only dcim.device or virtualization.virtualmachine
assigned_object_id positive integer ✅ create-only PK of the assigned Device or VM
assigned_object nested object read-only Resolved Device or VM instance
current_state string or integer ✅ State name (e.g. "on") or State PK; must belong to the power state StateType and satisfy the transition rule
previous_state string read-only State name of the prior state; set automatically on update; null on first creation
transitioned_by string read-only Set automatically from request user
transition_source string ✅ user, system, api, automation, or monitoring

Constraints

  • One per object: A Device or VM may have at most one PowerState record.
  • State must change: current_state must differ from the value already in the database. Sending the same value returns 400.
  • Read-only fields: Passing previous_state or transitioned_by in the request body returns 400.
  • Transition rules apply: The current_state must satisfy the applicable StateTransitionRule for the power state type. If no rule is defined for the current state, no transitions are allowed.
  • State catalog required: A StateType named power state with at least one state must exist before creating a PowerState record.

UI

Plugins → IBM NetBox Plugins → Power States

Page Description
List Filterable, sortable table of all records
Detail All fields + inline Transition dropdown (HTMX — no page reload) showing allowed next states
Add Select object type, object, and initial state; metadata fields are hidden
Bulk Import CSV import; required columns: assigned_object_type, assigned_object_id, current_state
Bulk Edit Change current_state across multiple records
Bulk Delete Delete multiple records

The Transition dropdown on the Detail page POSTs to /plugins/ibm-netbox-plugins/power-states/<pk>/transition/.

API Endpoints

Base URL: /api/plugins/ibm-netbox-plugins/power-states/

POST — Create

POST /api/plugins/ibm-netbox-plugins/power-states/
Authorization: Token <token>
Content-Type: application/json

{
  "assigned_object_type": "dcim.device",
  "assigned_object_id": 191688,
  "current_state": "off",
  "transition_source": "api"
}

current_state accepts the state name directly. Integer PK is also accepted ("current_state": 1).

201 Created

{
  "id": 42,
  "url": "http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/42/",
  "display_url": "http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/42/",
  "display": "dal10-server-01 - off",
  "assigned_object_type": "dcim.device",
  "assigned_object_id": 191688,
  "assigned_object": {
    "id": 191688,
    "url": "http://<netbox>/api/dcim/devices/191688/",
    "display": "dal10-server-01",
    "name": "dal10-server-01"
  },
  "current_state": "off",
  "previous_state": null,
  "transitioned_by": "admin",
  "transition_source": "api",
  "transitioned_at": "2025-06-01T10:30:00.000Z",
  "tags": [],
  "custom_fields": {},
  "created": "2025-06-01T10:30:00.000Z",
  "last_updated": "2025-06-01T10:30:00.000Z"
}

For a VirtualMachine, change assigned_object_type to "virtualization.virtualmachine".

GET — Retrieve by ID

GET /api/plugins/ibm-netbox-plugins/power-states/42/
Authorization: Token <token>

200 OK — same structure as the POST response above with current field values.

GET — List (with filters)

GET /api/plugins/ibm-netbox-plugins/power-states/?device=191688
Authorization: Token <token>

200 OK

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 42,
      "display": "dal10-server-01 - on",
      "assigned_object_type": "dcim.device",
      "assigned_object_id": 191688,
      "current_state": "on",
      "previous_state": "off",
      "transitioned_by": "admin",
      "transition_source": "api",
      "transitioned_at": "2025-06-01T11:00:00.000Z"
    }
  ]
}

Look up PowerState ID before PATCH / DELETE

The URL path {id} refers to the PowerState record's own id, not the device's id. Filter by ?device=<device_id> or ?assigned_object_id=<id> to find the PowerState id first.

PATCH — Transition state

Pass the target state as a name string or integer PK. The value must be allowed by the StateTransitionRule from the currently stored state.

PATCH /api/plugins/ibm-netbox-plugins/power-states/42/
Authorization: Token <token>
Content-Type: application/json

{
  "current_state": "on"
}

200 OK — returns the full updated record with previous_state set to the prior value, transitioned_at updated, and transitioned_by set to the request user.

PUT — Full update

PUT /api/plugins/ibm-netbox-plugins/power-states/42/
Authorization: Token <token>
Content-Type: application/json

{
  "assigned_object_type": "dcim.device",
  "assigned_object_id": 191688,
  "current_state": "off"
}

200 OK — same response shape as PATCH.

DELETE — Remove

DELETE /api/plugins/ibm-netbox-plugins/power-states/42/
Authorization: Token <token>

204 No Content — empty body. The Device or VM is not affected.

State Transition Example

Initial creation          → current_state: "off",  previous_state: null
PATCH "on"  (or id=2)     → current_state: "on",   previous_state: "off"
PATCH "off" (or id=1)     → current_state: "off",  previous_state: "on"
PATCH "off"               → 400 "Current state must differ from previous state."
PATCH "standby"           → 400 'No state named "standby" in "power state". Available: off, on.'
PATCH "on" (from "on")    → 400 'Invalid transition from "on". Allowed: off.'

PowerState Filter Parameters

Parameter Type Example Description
id integer ?id=42 Filter by PowerState record ID
assigned_object_type integer ?assigned_object_type=12 Content-type ID
assigned_object_id integer ?assigned_object_id=191688 PK of Device or VM
device integer ?device=191688 Shorthand — filter by Device ID
virtual_machine integer ?virtual_machine=5001 Shorthand — filter by VM ID
current_state integer (multi) ?current_state=1&current_state=2 State ID(s) — filter params still use IDs; use ?current_state=<id>
previous_state integer (multi) ?previous_state=1 State ID(s)
transition_source string (multi) ?transition_source=api One or more of user, system, api, automation, monitoring
transitioned_by string ?transitioned_by=admin Username (exact)
hostname string ?hostname=dal10 Case-insensitive substring match on Device/VM hostname
site integer (multi) ?site=3 Site ID; matches both Devices and VMs
location integer (multi) ?location=7 Location ID; matches Devices only
rack integer (multi) ?rack=22 Rack ID; Devices only
room integer (multi) ?room=9 Room ID; Devices only
q string ?q=dal10 Free-text search across state fields + hostnames, sites, locations, racks, rooms
limit integer ?limit=50 Page size
offset integer ?offset=100 Pagination offset

PowerState Error Reference

Scenario HTTP Field Message
Passing previous_state in request 400 previous_state This field is set automatically and cannot be provided.
Passing transitioned_by in request 400 transitioned_by This field is set automatically and cannot be provided.
PATCH with same current_state 400 current_state Current state must differ from previous state.
State name not found in catalog 400 current_state No state named "<name>" in "power state". Available: <names>.
State ID not found 400 current_state No state found with ID <id>.
State ID belongs to wrong StateType 400 current_state State "<name>" (ID <id>) belongs to "<type>", not "power state".
Invalid transition (rule disallows it) 400 current_state Invalid transition from "<from>". Allowed: <states>.
Creating second PowerState for same object 400 non-field A power state already exists for this object. Please edit the existing power state instead of creating a new one.
assigned_object_id does not exist 400 assigned_object_id No <app>.<model> found with ID <id>.
assigned_object_type not device or VM 400 assigned_object_type Invalid content type.
PowerState id not found 404 — No PowerState matches the given query.
Insufficient permissions 403 — You do not have permission to perform this action.

POST — Upsert by device serial (/device/set/)

This endpoint is designed for automation and monitoring callers that identify devices by serial number rather than NetBox PK. It is idempotent: sending the same state twice is safe and returns 200 without writing to the database.

URL: POST /api/plugins/ibm-netbox-plugins/power-states/device/set/

Request payload

Field Required Type Description
serial ✅ string Device serial number
current_state ✅ string or integer Target state name (e.g. "on") or State PK
transition_source ⬜ string One of user, system, api, automation, monitoring. Defaults to "user"

Fields not accepted in the payload (set automatically):

Field Set by
transitioned_by Pre-save signal from request.user.username
previous_state Pre-save signal from the existing DB value
transitioned_at auto_now=True on the model field

Behaviour

Scenario HTTP status Side effects
No existing PowerState for this device 201 Created Record created
Existing PowerState, current_state differs 200 OK Record updated, previous_state set to prior value
Existing PowerState, current_state already matches 200 OK No write — existing record returned as-is

Required permissions

Permission Branch
ibm_netbox_plugins.add_powerstate Create
ibm_netbox_plugins.change_powerstate Update
dcim.view_device All branches (implied by knowing the serial)

Example — create

POST /api/plugins/ibm-netbox-plugins/power-states/device/set/
Authorization: Token <token>
Content-Type: application/json

{
  "serial": "ABC123XYZ",
  "current_state": "off",
  "transition_source": "api"
}

201 Created

{
  "id": 42,
  "url": "http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/42/",
  "display": "dal10-server-01 - off",
  "assigned_object_type": "dcim.device",
  "assigned_object_id": 191688,
  "assigned_object": { "id": 191688, "display": "dal10-server-01" },
  "current_state": "off",
  "previous_state": null,
  "transitioned_by": "svc-automation",
  "transition_source": "api",
  "transitioned_at": "2025-06-01T10:30:00.000Z",
  "tags": [],
  "custom_fields": {},
  "created": "2025-06-01T10:30:00.000Z",
  "last_updated": "2025-06-01T10:30:00.000Z"
}

Example — update (transition off → on)

POST /api/plugins/ibm-netbox-plugins/power-states/device/set/
Authorization: Token <token>
Content-Type: application/json

{
  "serial": "ABC123XYZ",
  "current_state": "on",
  "transition_source": "automation"
}

200 OK — same shape as above with current_state: "on", previous_state: "off".

Example — no-op (state already matches)

POST /api/plugins/ibm-netbox-plugins/power-states/device/set/
Authorization: Token <token>
Content-Type: application/json

{
  "serial": "ABC123XYZ",
  "current_state": "on"
}

200 OK — existing record returned unchanged. No database write occurs.

Error reference

Scenario HTTP Field Message
serial missing 400 serial This field is required.
current_state missing 400 current_state This field is required.
No device with that serial 400 serial No device found with serial '<value>'.
Multiple devices with same serial 400 serial Multiple devices found with serial '<value>'. Use the standard endpoint with assigned_object_id.
State name not in catalog 400 current_state No state named "<name>" in "power state". Available: <names>.
State ID not found 400 current_state No state found with ID <id>.
Invalid transition rule 400 current_state Invalid transition from "<from>". Allowed: <states>.
Invalid transition_source value 400 transition_source '<value>' is not a valid choice. Valid choices are: user, system, api, automation, monitoring.
Insufficient permissions (create) 403 — Permission denied
Insufficient permissions (update) 403 — Permission denied
Concurrent create race 409 detail A power state was created concurrently for this device. Please retry.

State Catalog (StateType, State, StateTransitionRule)

Before any state records can be created, a state catalog must be defined. These three management models are used together for all four lifecycle types.

The catalog follows a strict dependency order:

StateType  →  State  →  StateTransitionRule

You must create them in that order. A State cannot exist without a parent StateType, and a StateTransitionRule cannot exist without both a StateType and the State records it references.

The plugin identifies which catalog drives which lifecycle model by matching StateType.name against a reserved string (case-insensitive):

Reserved Name (exact, stored lower-case) Drives
power state PowerState
os state OSState
runtime state RuntimeState
allocation state AllocationState

StateType

A StateType is a named category that groups a set of related states. It is the top-level container in the state catalog. All State and StateTransitionRule records belong to exactly one StateType.

Names are stored and matched case-insensitively. Creating a StateType with name OS State stores os state.

StateType Fields

Field Type Writable Description
id integer — Auto PK
name string ✅ Unique name; stored lower-case
tags array ✅ NetBox tags
custom_fields object ✅ NetBox custom fields

StateType UI

Plugins → IBM NetBox Plugins → State Types

Page URL Description
List /plugins/ibm-netbox-plugins/state-types/ Table of all state types; columns: Name, State Count, Transition Rule Count
Detail /plugins/ibm-netbox-plugins/state-types/<pk>/ Name, all states belonging to this type (name + color badge + is_initial flag), and all transition rules in a table
Add /plugins/ibm-netbox-plugins/state-types/add/ Single field: Name
Edit /plugins/ibm-netbox-plugins/state-types/<pk>/edit/ Rename the state type
Delete /plugins/ibm-netbox-plugins/state-types/<pk>/delete/ Confirmation page; blocked if any states exist under it
Bulk Delete /plugins/ibm-netbox-plugins/state-types/delete/ Delete multiple selected types

Start here

Navigate to State Types first, create the type, then use the Add State button on the detail page to add states inline — the state form pre-fills the state_type field automatically.

StateType API

Base URL: /api/plugins/ibm-netbox-plugins/state-types/

POST — Create a StateType

POST /api/plugins/ibm-netbox-plugins/state-types/
Authorization: Token <token>
Content-Type: application/json

{
  "name": "power state"
}

201 Created

{
  "id": 1,
  "url": "http://<netbox>/api/plugins/ibm-netbox-plugins/state-types/1/",
  "display": "power state",
  "name": "power state",
  "tags": [],
  "custom_fields": {},
  "created": "2025-06-01T09:00:00.000Z",
  "last_updated": "2025-06-01T09:00:00.000Z"
}

GET — List

GET /api/plugins/ibm-netbox-plugins/state-types/

PATCH — Update name

PATCH /api/plugins/ibm-netbox-plugins/state-types/1/
Content-Type: application/json

{ "name": "power state" }

DELETE

DELETE /api/plugins/ibm-netbox-plugins/state-types/1/

204 No Content on success. Deleting a StateType cascades to its State records. If PowerState / OSState / RuntimeState / AllocationState records reference those states, the FK PROTECT constraint will block deletion.

StateType Filter Parameters

Parameter Type Description
q string Free-text search on name
name string Substring match on name

StateType Error Reference

Scenario HTTP Field Message
Duplicate name (case-insensitive) 400 name A state type with this name already exists.

State

A State is a single named value within a StateType (e.g. on, off, running, stopped, decommissioned). Each state has an optional color (shown as a colored badge in list and detail views) and an is_initial flag.

is_initial behaviour

  • At most one state per StateType may have is_initial = true.
  • When a state record (PowerState, OSState, RuntimeState, AllocationState) is created via the quick-create button on a device/VM detail page, the is_initial state is assigned automatically as current_state.
  • If no is_initial state exists, the plugin falls back to the first state alphabetically.
  • Setting is_initial on a second state in the same type raises a 400 validation error.

State Fields

Field Type Writable Description
id integer — Auto PK
state_type integer (FK) ✅ The parent StateType ID
name string ✅ Unique within the state type; stored lower-case
color string ✅ Hex color (without #) used in badges, e.g. "4caf50"
is_initial boolean ✅ At most one state per type may be true
tags array ✅ NetBox tags
custom_fields object ✅ NetBox custom fields

State UI

Plugins → IBM NetBox Plugins → States

Page URL Description
List /plugins/ibm-netbox-plugins/states/ All states; filterable by state_type, name; columns: State Type, Name, Color, Initial
Add /plugins/ibm-netbox-plugins/states/add/ Fields: State Type, Name, Color (color picker), Is Initial checkbox. After save, redirects back to the parent StateType detail page.
Edit /plugins/ibm-netbox-plugins/states/<pk>/edit/ Same fields; save redirects back to the parent StateType detail page.
Delete /plugins/ibm-netbox-plugins/states/<pk>/delete/ Blocked if the state is referenced in any StateTransitionRule.
Bulk Delete /plugins/ibm-netbox-plugins/states/delete/ Delete multiple selected states.

Adding states to a type quickly

From the StateType detail page, click Add State to open the add form with the state_type field pre-filled. Use Save and Add Another to create all states in one session without re-selecting the type each time.

State API

Base URL: /api/plugins/ibm-netbox-plugins/states/

POST — Create a State

POST /api/plugins/ibm-netbox-plugins/states/
Authorization: Token <token>
Content-Type: application/json

{
  "state_type": 1,
  "name": "off",
  "color": "9e9e9e",
  "is_initial": true
}

201 Created

{
  "id": 1,
  "url": "http://<netbox>/api/plugins/ibm-netbox-plugins/states/1/",
  "display": "power state / off",
  "state_type": 1,
  "name": "off",
  "color": "9e9e9e",
  "is_initial": true,
  "tags": [],
  "custom_fields": {},
  "created": "2025-06-01T09:05:00.000Z",
  "last_updated": "2025-06-01T09:05:00.000Z"
}

Create multiple states for the same type

POST /api/plugins/ibm-netbox-plugins/states/
Content-Type: application/json

[
  { "state_type": 1, "name": "off",  "color": "9e9e9e", "is_initial": true  },
  { "state_type": 1, "name": "on",   "color": "4caf50", "is_initial": false }
]

NetBox REST API supports bulk POST by sending a JSON array.

GET — List states for a specific type

GET /api/plugins/ibm-netbox-plugins/states/?state_type=power+state

PATCH — Update a state

PATCH /api/plugins/ibm-netbox-plugins/states/1/
Content-Type: application/json

{ "color": "f44336" }

DELETE

DELETE /api/plugins/ibm-netbox-plugins/states/1/

State deletion is blocked if transition rules reference it

A state cannot be deleted while it is referenced as a from_state or to_state in any StateTransitionRule. Delete the rules first, then the state.

State Filter Parameters

Parameter Type Description
q string Free-text search on name and state_type name
name string Substring match
state_type string (multi) Filter by StateType name (exact)
state_type_id integer (multi) Filter by StateType ID

State Error Reference

Scenario HTTP Field Message
Duplicate name within same StateType 400 name A state with this name already exists for this state type.
Second is_initial=true for same type 400 is_initial Another state is already marked as the initial state for this state type.
Delete state referenced in transition rules 400/409 — Cannot delete state "<name>" — it is used as the "from" state in N transition rule(s).

StateTransitionRule

Defines which target states are reachable from a given source state within a StateType. There is at most one rule per (state_type, from_state) pair. A rule has one source and one or more targets.

If no rule is defined for the current state, the transition is blocked (no targets allowed). If the StateType itself does not exist, all transitions are permitted (permissive fallback for new installs).

StateTransitionRule Fields

Field Type Writable Description
id integer — Auto PK
state_type integer (FK) ✅ Parent StateType
from_state integer (FK) ✅ The source State (must belong to state_type)
to_states array of integers ✅ One or more target State PKs (must all belong to state_type)
tags array ✅ NetBox tags
custom_fields object ✅ NetBox custom fields

StateTransitionRule UI

Plugins → IBM NetBox Plugins → State Transition Rules

Page URL Description
List /plugins/ibm-netbox-plugins/state-transition-rules/ All rules; filterable by state_type, from_state; columns: State Type, From State, To States
Detail /plugins/ibm-netbox-plugins/state-transition-rules/<pk>/ Shows the full rule: state type, from state, and each target state as a badge
Add /plugins/ibm-netbox-plugins/state-transition-rules/add/ Fields: State Type (dropdown), From State (dropdown filtered to the chosen type), To States (multi-select filtered to the chosen type). After save, redirects back to the parent StateType detail page.
Edit /plugins/ibm-netbox-plugins/state-transition-rules/<pk>/edit/ Same fields; to_states can be extended or replaced.
Delete /plugins/ibm-netbox-plugins/state-transition-rules/<pk>/delete/ Confirmation page; deleting a rule does not delete the states themselves.
Bulk Delete /plugins/ibm-netbox-plugins/state-transition-rules/delete/ Delete multiple selected rules.

One rule per (StateType, From State) pair

If you try to create a second rule for the same (state_type, from_state) combination, the form will reject it. To add more target states, edit the existing rule and extend the to_states list.

Deleting a rule makes the from_state terminal

Once a rule is deleted, the from_state becomes unreachable for further transitions. Any device/VM currently in that state will be stuck there. Only delete rules intentionally.

StateTransitionRule API

Base URL: /api/plugins/ibm-netbox-plugins/state-transition-rules/

POST — Create a rule

POST /api/plugins/ibm-netbox-plugins/state-transition-rules/
Authorization: Token <token>
Content-Type: application/json

{
  "state_type": 1,
  "from_state": 1,
  "to_states": [2]
}

201 Created

{
  "id": 1,
  "url": "http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/1/",
  "display": "power state: off → ...",
  "state_type": 1,
  "from_state": 1,
  "to_states": [2],
  "tags": [],
  "custom_fields": {},
  "created": "2025-06-01T09:10:00.000Z",
  "last_updated": "2025-06-01T09:10:00.000Z"
}

PATCH — Add/replace target states

PATCH /api/plugins/ibm-netbox-plugins/state-transition-rules/1/
Content-Type: application/json

{ "to_states": [2] }

DELETE

DELETE /api/plugins/ibm-netbox-plugins/state-transition-rules/1/

StateTransitionRule Filter Parameters

Parameter Type Description
q string Free-text search on state_type name and from_state name
state_type string (multi) Filter by StateType name
state_type_id integer (multi) Filter by StateType ID
from_state integer (multi) Filter by from_state ID

StateTransitionRule Error Reference

Scenario HTTP Field Message
from_state doesn't belong to state_type 400 from_state From state must belong to the selected state type.
A to_state doesn't belong to state_type 400 to_states States do not belong to the selected state type: <names>
Duplicate (state_type, from_state) 400 non-field Database unique constraint violation

OSState

Tracks the operating-system lifecycle state of a Device or VirtualMachine. Uses the state catalog keyed to state type name os state.

OSState Fields

Field Type Writable Description
assigned_object_type content type ✅ create-only dcim.device or virtualization.virtualmachine
assigned_object_id positive integer ✅ create-only PK of the assigned Device or VM
assigned_object nested object read-only Resolved Device or VM
current_state string or integer ✅ State name (e.g. "provisioning") or State PK; must belong to os state StateType and satisfy the transition rule
previous_state string read-only State name of the prior state; set automatically on update
transitioned_by string read-only Set automatically
transition_source string ✅ user, system, api, automation, or monitoring

OSState Constraints

  • One per object: A Device or VM may have at most one OSState record.
  • Transition rules apply: The current_state must satisfy the applicable StateTransitionRule. If no rule is defined for the current state, no transitions are allowed.
  • State must change: Setting current_state to the same value as currently stored returns 400.
  • State must belong to type os state: Any State FK not of the correct StateType returns a validation error.

OSState API

Base URL: /api/plugins/ibm-netbox-plugins/os-states/

POST — Create

POST /api/plugins/ibm-netbox-plugins/os-states/
Authorization: Token <token>
Content-Type: application/json

{
  "assigned_object_type": "dcim.device",
  "assigned_object_id": 191688,
  "current_state": "provisioning",
  "transition_source": "api"
}

201 Created

{
  "id": 7,
  "url": "http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/7/",
  "display_url": "http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/7/",
  "display": "dal10-server-01 - provisioning",
  "assigned_object_type": "dcim.device",
  "assigned_object_id": 191688,
  "assigned_object": {
    "id": 191688,
    "url": "http://<netbox>/api/dcim/devices/191688/",
    "display": "dal10-server-01",
    "name": "dal10-server-01"
  },
  "current_state": "provisioning",
  "previous_state": null,
  "transitioned_by": "admin",
  "transition_source": "api",
  "transitioned_at": "2025-06-01T10:00:00.000Z",
  "tags": [],
  "custom_fields": {},
  "created": "2025-06-01T10:00:00.000Z",
  "last_updated": "2025-06-01T10:00:00.000Z"
}

GET — Retrieve

GET /api/plugins/ibm-netbox-plugins/os-states/7/
Authorization: Token <token>

200 OK — same structure as above.

GET — List (filtered by device)

GET /api/plugins/ibm-netbox-plugins/os-states/?device=191688
Authorization: Token <token>

PATCH — Transition state

Pass the target state as a name string or integer PK. The value must satisfy the transition rule from the state currently stored.

PATCH /api/plugins/ibm-netbox-plugins/os-states/7/
Authorization: Token <token>
Content-Type: application/json

{
  "current_state": "running",
  "transition_source": "automation"
}

200 OK

{
  "id": 7,
  "current_state": "running",
  "previous_state": "provisioning",
  "transitioned_by": "admin",
  "transition_source": "automation",
  "transitioned_at": "2025-06-01T11:00:00.000Z"
}

DELETE

DELETE /api/plugins/ibm-netbox-plugins/os-states/7/

204 No Content

OSState State Transition Example

Given these states and rules for os state:

States:  provisioning, running, stopped, decommissioned

Rules:
  provisioning → [running]
  running      → [stopped]
  stopped      → [running, decommissioned]
  decommissioned → []  (terminal — no rule defined, no further transitions)
Create OSState: current="provisioning", previous=null
PATCH "running":        ✅  previous="provisioning"
PATCH "stopped":        ✅  previous="running"
PATCH "running":        ✅  previous="stopped"
PATCH "decommissioned": ✅  previous="running"
PATCH "running":        ❌ 400 — Invalid transition from "decommissioned". Allowed: none.
PATCH "decommissioned": ❌ 400 — Current state must differ from the existing state.

OSState Filter Parameters

Parameter Type Description
q string Free-text search on state name, transitioned_by, device/VM name
assigned_object_type integer Content-type ID
assigned_object_id integer PK of Device or VM
device integer Shorthand — filter by Device ID
virtual_machine integer Shorthand — filter by VM ID
current_state integer (multi) Filter by State ID(s)

OSState Error Reference

Scenario HTTP Field Message
Duplicate OSState for same object 400 non-field An OS state already exists for this object.
Invalid transition (rule disallows it) 400 current_state Invalid transition from "<from>". Allowed: <states>.
Same current_state as stored 400 current_state Current state must differ from the existing state.
assigned_object_id does not exist 400 assigned_object_id No <app>.<model> found with ID <id>.
OSState id not found 404 — No OSState matches the given query.

RuntimeState

Tracks the runtime lifecycle state of a Device or VirtualMachine. Uses the state catalog keyed to state type name runtime state.

The model, API, and validation rules are identical to OSState. All constraints, filter parameters, and error messages follow the same patterns — substitute runtime state for os state, and /os-states/ with /runtime-states/ in all URLs.

RuntimeState Fields

Identical to OSState fields — assigned_object_type, assigned_object_id, assigned_object, current_state, previous_state, transitioned_by, transition_source.

RuntimeState API

Base URL: /api/plugins/ibm-netbox-plugins/runtime-states/

POST — Create

POST /api/plugins/ibm-netbox-plugins/runtime-states/
Authorization: Token <token>
Content-Type: application/json

{
  "assigned_object_type": "virtualization.virtualmachine",
  "assigned_object_id": 5001,
  "current_state": "initialising",
  "transition_source": "system"
}

201 Created — structure identical to OSState. current_state and previous_state in the response are state name strings.

PATCH — Transition

PATCH /api/plugins/ibm-netbox-plugins/runtime-states/3/
Content-Type: application/json

{ "current_state": "healthy" }

RuntimeState State Transition Example

Given these states and rules for runtime state:

States:  initialising, healthy, degraded, failed

Rules:
  initialising → [healthy, failed]
  healthy      → [degraded, failed]
  degraded     → [healthy, failed]
  failed       → []  (terminal)
Create: current="initialising", previous=null
PATCH "healthy":    ✅  previous="initialising"
PATCH "degraded":   ✅  previous="healthy"
PATCH "failed":     ✅  previous="degraded"
PATCH "healthy":    ❌ 400 — Invalid transition from "failed". Allowed: none.

RuntimeState Filter Parameters

Same as OSState: q, assigned_object_type, assigned_object_id, device, virtual_machine, current_state.

RuntimeState Error Reference

Same as OSState error messages with runtime state substituted.


AllocationState

Tracks the allocation lifecycle state of a Device only (VMs are not supported). Uses the state catalog keyed to state type name allocation state.

AllocationState Fields

Field Type Writable Description
device integer (FK → Device) ✅ create-only The Device this state belongs to (one-to-one)
current_state string or integer ✅ State name (e.g. "available") or State PK; must belong to allocation state StateType and satisfy the transition rule
previous_state string read-only State name of the prior state; set automatically on update
transitioned_by string read-only Set automatically
transition_source string ✅ user, system, api, automation, or monitoring

AllocationState Constraints

  • One per device: A Device may have at most one AllocationState record.
  • Transition rules apply: Same rule-based validation as OSState and RuntimeState.
  • State must change: Same as other state models.
  • Device only: VMs are not supported; use OSState or RuntimeState for VMs.

AllocationState API

Base URL: /api/plugins/ibm-netbox-plugins/allocation-states/

POST — Create

POST /api/plugins/ibm-netbox-plugins/allocation-states/
Authorization: Token <token>
Content-Type: application/json

{
  "device": 191688,
  "current_state": "available",
  "transition_source": "user"
}

201 Created

{
  "id": 15,
  "url": "http://<netbox>/api/plugins/ibm-netbox-plugins/allocation-states/15/",
  "display_url": "http://<netbox>/api/plugins/ibm-netbox-plugins/allocation-states/15/",
  "display": "dal10-server-01 - available",
  "device": 191688,
  "current_state": "available",
  "previous_state": null,
  "transitioned_by": "admin",
  "transition_source": "user",
  "transitioned_at": "2025-06-01T10:00:00.000Z",
  "tags": [],
  "custom_fields": {},
  "created": "2025-06-01T10:00:00.000Z",
  "last_updated": "2025-06-01T10:00:00.000Z"
}

GET — Retrieve

GET /api/plugins/ibm-netbox-plugins/allocation-states/15/

GET — List (filtered)

GET /api/plugins/ibm-netbox-plugins/allocation-states/?device=191688

PATCH — Transition

PATCH /api/plugins/ibm-netbox-plugins/allocation-states/15/
Content-Type: application/json

{
  "current_state": "reserved",
  "transition_source": "api"
}

200 OK — same structure with updated fields.

DELETE

DELETE /api/plugins/ibm-netbox-plugins/allocation-states/15/

204 No Content

AllocationState State Transition Example

Given these states and rules for allocation state:

States:  available, reserved, allocated, decommissioned

Rules:
  available      → [reserved, allocated]
  reserved       → [available, allocated]
  allocated      → [available, decommissioned]
  decommissioned → []  (terminal)
Create:  current="available",      previous=null
PATCH "reserved":       ✅  previous="available"
PATCH "allocated":      ✅  previous="reserved"
PATCH "decommissioned": ✅  previous="allocated"
PATCH "available":      ❌ 400 — Invalid transition from "decommissioned". Allowed: none.

AllocationState Filter Parameters

Parameter Type Description
q string Free-text on state name, transitioned_by, device name
device integer (multi) Filter by Device ID(s)
current_state integer (multi) Filter by State ID(s)

AllocationState Error Reference

Scenario HTTP Field Message
Duplicate AllocationState for same device 400 non-field An allocation state already exists for this device.
Invalid transition 400 current_state Invalid transition from "<from>". Allowed: <states>.
Same current_state as stored 400 current_state Current state must differ from the existing state.
AllocationState id not found 404 — No AllocationState matches the given query.

UI — State Cards on Device / VM Detail Pages

When viewing a Device or Virtual Machine, each configured state dimension renders as an inline card:

┌──────────────────────────────────────────┐
│  Power State                    [ON]     │
│  Last changed: 2025-06-01 11:00 by admin │
│  Source: api                             │
│  [Transition ▼]  → Off                  │
└──────────────────────────────────────────┘

┌──────────────────────────────────────────┐
│  OS State                  [RUNNING]     │
│  Previous: PROVISIONING                  │
│  Allowed transitions: STOPPED            │
│  [Transition ▼]                          │
└──────────────────────────────────────────┘
  • If no state record exists yet, the card shows a Create button. Clicking it POSTs to the quick-create endpoint and sets the is_initial state automatically.
  • For all four state types (Power, OS, Runtime, Allocation), the card shows a Transition dropdown listing the allowed next states from the applicable StateTransitionRule.
  • Transitions via the card are HTMX-powered (no full page reload).
  • The Transition URL pattern for PowerState is: POST /plugins/ibm-netbox-plugins/power-states/<pk>/transition/

State Models Dashboard View

A combined view for a single device or VM is available at:

/plugins/ibm-netbox-plugins/state-models/<content_type>/<object_id>/

Where content_type is device or virtualmachine.

This page displays all four state dimensions side-by-side, plus a filterable state history panel.

History Filter Values
State Type all, power (others TBD)
Time Range 24h, 7d, 30d, 90d
Changed By Username substring

Signals

A pre_save signal fires automatically on every save of any state model and performs two actions:

  1. Sets transitioned_by to the username of the currently authenticated request user (via netbox.context.current_request).
  2. Sets previous_state to the value of current_state currently in the database (the value being replaced). On first creation, previous_state is set to null.

This means transitioned_by and previous_state are always accurate regardless of whether the save originates from the UI, the API, a management command, or a direct ORM call with a request in context.

The signal is registered for all four lifecycle models: PowerState, OSState, RuntimeState, AllocationState.


Permissions

All state models follow standard NetBox model permissions:

Permission Codename
View ibm_netbox_plugins.view_powerstate
Add ibm_netbox_plugins.add_powerstate
Change ibm_netbox_plugins.change_powerstate
Delete ibm_netbox_plugins.delete_powerstate

Replace powerstate with osstate, runtimestate, or allocationstate for the other models. State catalog models (statetype, state, statetransitionrule) follow the same pattern.


Complete API Endpoint Reference

Method URL Description
GET / POST /api/plugins/ibm-netbox-plugins/power-states/ List / Create PowerState
GET / PATCH / PUT / DELETE /api/plugins/ibm-netbox-plugins/power-states/{id}/ Retrieve / Update / Delete PowerState
POST /plugins/ibm-netbox-plugins/power-states/{id}/transition/ UI transition (HTMX)
GET / POST /api/plugins/ibm-netbox-plugins/os-states/ List / Create OSState
GET / PATCH / PUT / DELETE /api/plugins/ibm-netbox-plugins/os-states/{id}/ Retrieve / Update / Delete OSState
GET / POST /api/plugins/ibm-netbox-plugins/runtime-states/ List / Create RuntimeState
GET / PATCH / PUT / DELETE /api/plugins/ibm-netbox-plugins/runtime-states/{id}/ Retrieve / Update / Delete RuntimeState
GET / POST /api/plugins/ibm-netbox-plugins/allocation-states/ List / Create AllocationState
GET / PATCH / PUT / DELETE /api/plugins/ibm-netbox-plugins/allocation-states/{id}/ Retrieve / Update / Delete AllocationState
GET / POST /api/plugins/ibm-netbox-plugins/state-types/ List / Create StateType
GET / PATCH / PUT / DELETE /api/plugins/ibm-netbox-plugins/state-types/{id}/ Retrieve / Update / Delete StateType
GET / POST /api/plugins/ibm-netbox-plugins/states/ List / Create State
GET / PATCH / PUT / DELETE /api/plugins/ibm-netbox-plugins/states/{id}/ Retrieve / Update / Delete State
GET / POST /api/plugins/ibm-netbox-plugins/state-transition-rules/ List / Create StateTransitionRule
GET / PATCH / PUT / DELETE /api/plugins/ibm-netbox-plugins/state-transition-rules/{id}/ Retrieve / Update / Delete StateTransitionRule

All endpoints also support bulk operations via array request bodies.
Interactive documentation is available at: /api/docs/ → ibm-netbox-plugins section.


End-to-End Example: Full PowerState Lifecycle

This walk-through sets up the catalog and then toggles a device's power state.

1. Create the PowerState StateType

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-types/ \
  -H "Authorization: Token <token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "power state"}'
# → id: 1

2. Create States

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/states/ \
  -H "Authorization: Token <token>" \
  -H "Content-Type: application/json" \
  -d '[
    {"state_type": 1, "name": "off", "color": "9e9e9e", "is_initial": true},
    {"state_type": 1, "name": "on",  "color": "4caf50", "is_initial": false}
  ]'
# → ids: 1 (off), 2 (on)

3. Create Transition Rules

# off → on
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"state_type": 1, "from_state": 1, "to_states": [2]}'

# on → off
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"state_type": 1, "from_state": 2, "to_states": [1]}'

4. Create the PowerState for a device (starts at off)

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{
    "assigned_object_type": "dcim.device",
    "assigned_object_id": 191688,
    "current_state": "off",
    "transition_source": "api"
  }'
# → id: 42,  current_state: "off",  previous_state: null

5. Transition the power state

# off → on  (name string)
curl -sX PATCH http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/42/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"current_state": "on"}'

# on → off  (name string)
curl -sX PATCH http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/42/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"current_state": "off"}'

# off → off (BLOCKED — same state)
curl -sX PATCH http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/42/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"current_state": "off"}'
# → 400 {"current_state": ["Current state must differ from previous state."]}

6. Check the final state

curl -s http://<netbox>/api/plugins/ibm-netbox-plugins/power-states/42/ \
  -H "Authorization: Token <token>"
{
  "id": 42,
  "current_state": "off",
  "previous_state": "on",
  "transitioned_by": "admin",
  "transition_source": "api",
  "transitioned_at": "2025-06-01T15:45:00.000Z"
}

End-to-End Example: Full OS State Lifecycle

This walk-through sets up the catalog and then drives a device through the full OS state lifecycle.

1. Create the StateType

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-types/ \
  -H "Authorization: Token <token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "os state"}'
# → id: 2

2. Create States

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/states/ \
  -H "Authorization: Token <token>" \
  -H "Content-Type: application/json" \
  -d '[
    {"state_type": 2, "name": "provisioning",    "color": "ff9800", "is_initial": true},
    {"state_type": 2, "name": "running",          "color": "4caf50", "is_initial": false},
    {"state_type": 2, "name": "stopped",          "color": "f44336", "is_initial": false},
    {"state_type": 2, "name": "decommissioned",   "color": "9e9e9e", "is_initial": false}
  ]'
# → ids: 10, 11, 12, 13

3. Create Transition Rules

# provisioning → running
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"state_type": 2, "from_state": 10, "to_states": [11]}'

# running → stopped
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"state_type": 2, "from_state": 11, "to_states": [12]}'

# stopped → running or decommissioned
curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/state-transition-rules/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"state_type": 2, "from_state": 12, "to_states": [11, 13]}'

# decommissioned → (terminal — no rule)

4. Create the OSState for a device (starts at provisioning)

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{
    "assigned_object_type": "dcim.device",
    "assigned_object_id": 191688,
    "current_state": "provisioning",
    "transition_source": "api"
  }'
# → id: 7,  current_state: "provisioning",  previous_state: null

5. Transition through the lifecycle

# provisioning → running
curl -sX PATCH http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/7/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"current_state": "running"}'

# running → stopped
curl -sX PATCH http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/7/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"current_state": "stopped"}'

# stopped → decommissioned
curl -sX PATCH http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/7/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"current_state": "decommissioned"}'

# decommissioned → running (BLOCKED — terminal state)
curl -sX PATCH http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/7/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '{"current_state": "running"}'
# → 400 {"current_state": ["Invalid transition from \"decommissioned\". Allowed: none."]}

6. Check the final state

curl -s http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/7/ \
  -H "Authorization: Token <token>"
{
  "id": 7,
  "current_state": "decommissioned",
  "previous_state": "stopped",
  "transitioned_by": "admin",
  "transition_source": "api",
  "transitioned_at": "2025-06-01T15:45:00.000Z"
}

Frequently Asked Questions

Q: How do I find a state record for a specific device without knowing its state ID?

Filter using ?device=<device_id> for AllocationState / OSState / RuntimeState, or ?device=<device_id> / ?assigned_object_id=<id> for PowerState. The response's id field is the state record ID to use in subsequent PATCH / DELETE requests.

Q: Can the same device have OSState, RuntimeState, AllocationState, AND PowerState all at the same time?

Yes. Each is an independent model. One device can hold one record of each type simultaneously.

Q: What happens if I try to create a PowerState but no power state StateType exists?

The transition check allows any state on creation (permissive fallback). However, you still need a valid State FK with current_state. If no matching StateType exists, transition enforcement is skipped. The safe approach is to always create the StateType, States, and TransitionRules first.

Q: Does PowerState still have fixed on/off values?

No. As of migration 0017/0018, current_state and previous_state are FK references to State catalog objects. You define the states yourself (name them anything, e.g. on, off, standby, maintenance). The recommended setup for simple power tracking is two states on and off with bidirectional transition rules.

Q: How were existing on/off PowerState records migrated?

Migration 0017 renamed the old current_state/previous_state CharFields to current_state_old/previous_state_old, added new FK columns, then back-filled the FK IDs by matching State.name (case-insensitive) within the power state StateType. Migration 0018 made current_state non-nullable and dropped the old columns. Rows that had no matching State remain with current_state_id = NULL until manually corrected.

Q: What is a terminal state?

A state that has no StateTransitionRule with it as the from_state. Once an object reaches a terminal state, no further transitions are possible via the API or UI. To make a terminal state non-terminal, create a StateTransitionRule for it.

Q: Can I delete a state that is currently in use by a device?

No. If a state is referenced by active PowerState / OSState / RuntimeState / AllocationState records as current_state or previous_state, the database will block deletion due to PROTECT foreign-key constraints.

Q: Is there a bulk-create endpoint for state records?

Yes. The NetBox REST API supports bulk POST via a JSON array on any list endpoint. For example:

curl -sX POST http://<netbox>/api/plugins/ibm-netbox-plugins/os-states/ \
  -H "Authorization: Token <token>" -H "Content-Type: application/json" \
  -d '[
    {"assigned_object_type": "dcim.device", "assigned_object_id": 191688, "current_state": "provisioning"},
    {"assigned_object_type": "dcim.device", "assigned_object_id": 191689, "current_state": "provisioning"}
  ]'

Q: Why does transition_source appear in the PowerState error reference as a blocked field in older docs?

In older versions, transition_source was read-only for PowerState. It is now writable for all four lifecycle models (PowerState, OSState, RuntimeState, AllocationState), allowing automation pipelines to identify themselves.


Filtering Devices and VMs by State

In addition to the dedicated state-model list endpoints, state filters are injected directly into the Device and Virtual Machine list endpoints so you can find objects by their current state without first querying the state records separately.

Where they appear

Context Endpoint / UI
Device list UI Devices → Devices filter sidebar, under the States fieldset
VM list UI Virtualization → Virtual Machines filter sidebar, under the States fieldset
Device list API GET /api/dcim/devices/
VM list API GET /api/virtualization/virtual-machines/

Device state filter parameters

These parameters are available on /api/dcim/devices/:

Parameter Type Description
power_state integer (multi) Filter devices whose current PowerState matches one of the given State IDs. Use GET /api/plugins/ibm-netbox-plugins/states/?state_type=power+state to look up IDs. Devices with no PowerState record are excluded.
os_state_id integer (multi) Filter devices whose current OSState matches one of the given State IDs. The UI dropdown is automatically scoped to states belonging to the os state StateType.
runtime_state_id integer (multi) Filter devices whose current RuntimeState matches one of the given State IDs. UI dropdown scoped to runtime state.
allocation_state_id integer (multi) Filter devices whose current AllocationState matches one of the given State IDs. UI dropdown scoped to allocation state.

allocation_state_id is device-only

AllocationState is not supported on VMs, so allocation_state_id does not appear on the VM endpoint.

PowerState filter now accepts State IDs

The power_state filter on Device/VM list endpoints now accepts State record IDs (integers) rather than string literals on/off. Look up the IDs for your power state states using GET /api/plugins/ibm-netbox-plugins/states/?state_type=power+state.

Device API examples

Find all devices in the "on" power state (assuming State id=2 is "on"):

GET /api/dcim/devices/?power_state=2
Authorization: Token <token>

Find all devices in "off" power state at a specific site:

GET /api/dcim/devices/?power_state=1&site_id=3
Authorization: Token <token>

Find devices in a specific OS state (by State ID):

GET /api/dcim/devices/?os_state_id=11
Authorization: Token <token>

Find devices in multiple runtime states:

GET /api/dcim/devices/?runtime_state_id=21&runtime_state_id=22
Authorization: Token <token>

Find devices in a specific allocation state:

GET /api/dcim/devices/?allocation_state_id=32
Authorization: Token <token>

Combine state filters with other device filters:

GET /api/dcim/devices/?power_state=2&allocation_state_id=31&site_id=3
Authorization: Token <token>


Virtual Machine state filter parameters

These parameters are available on /api/virtualization/virtual-machines/:

Parameter Type Description
power_state integer (multi) Filter VMs whose current PowerState matches one of the given State IDs. VMs with no PowerState record are excluded.
os_state_id integer (multi) Filter VMs whose current OSState matches one of the given State IDs. UI dropdown scoped to os state.
runtime_state_id integer (multi) Filter VMs whose current RuntimeState matches one of the given State IDs. UI dropdown scoped to runtime state.

VM API examples

Find all powered-on VMs (assuming State id=2 is "on"):

GET /api/virtualization/virtual-machines/?power_state=2
Authorization: Token <token>

Find VMs in a specific runtime state:

GET /api/virtualization/virtual-machines/?runtime_state_id=21
Authorization: Token <token>

Combine with cluster filter:

GET /api/virtualization/virtual-machines/?power_state=2&cluster_id=5
Authorization: Token <token>


How the filters work

Each filter performs a reverse join through the state model to find matching object IDs:

power_state=2  (State id=2 = "on")
  → PowerState.objects.filter(assigned_object_type=<device or vm CT>, current_state_id=2)
  → collect assigned_object_ids
  → Device/VM.objects.filter(pk__in=<ids>)

This means:

  • Objects with no state record are excluded when a state filter is applied. If a device has no PowerState record and you filter by power_state=2, that device will not appear in the results.
  • Multiple values for the same parameter are OR'd — ?power_state=1&power_state=2 returns all devices that have a PowerState record set to either state ID 1 or state ID 2.
  • Different state parameters are AND'd — ?power_state=2&allocation_state_id=31 returns only devices that are both in power state 2 AND in allocation state 31.
  • All state ID parameters accept State record IDs (integers), not state names. Use GET /api/plugins/ibm-netbox-plugins/states/?state_type=<type+name> to look up the IDs for the states you want to filter by.

Looking up State IDs for use in filters

# Get all power state IDs
curl -s "http://<netbox>/api/plugins/ibm-netbox-plugins/states/?state_type=power+state" \
  -H "Authorization: Token <token>" | python3 -m json.tool

# Response excerpt:
# { "results": [
#     { "id": 1, "name": "off", ... },
#     { "id": 2, "name": "on",  ... }
# ]}

# Get all OS state IDs
curl -s "http://<netbox>/api/plugins/ibm-netbox-plugins/states/?state_type=os+state" \
  -H "Authorization: Token <token>" | python3 -m json.tool

# Then filter devices by os_state_id=11 (running)
curl -s "http://<netbox>/api/dcim/devices/?os_state_id=11" \
  -H "Authorization: Token <token>"

UI — States fieldset

Both the Device and VM filter forms show a States fieldset in the filter sidebar panel:

Device filter sidebar → States:

Field Type Description
Power State dynamic dropdown Shows all states under the power state StateType
OS State dynamic dropdown Shows all states under the os state StateType
Runtime State dynamic dropdown Shows all states under the runtime state StateType
Allocation State dynamic dropdown Shows all states under the allocation state StateType

VM filter sidebar → States:

Field Type Description
Power State dynamic dropdown Shows all states under the power state StateType
OS State dynamic dropdown Shows all states under the os state StateType
Runtime State dynamic dropdown Shows all states under the runtime state StateType

The dynamic dropdowns are pre-filtered server-side to show only states belonging to the correct StateType, so the OS State dropdown will never show power or runtime states.