Docs

Integration Guide

This guide covers how to integrate NetBox change management with external systems using webhooks, scripts, and the REST API. For a general overview of the change management workflow, see the Introduction. For event rule configuration details in NetBox, see the event rules documentation.

Automating with Event Rules

Creating an Event Rule for Change Requests

To trigger a webhook or script when change request activity occurs:

  1. Navigate to Operations > Event Rules and click Add
  2. Under Object Types, select NetBox Changes > change request
  3. Under Events, select the standard object events you want to match (e.g., Object updated)
  4. Optionally, add Conditions to filter for specific lifecycle transitions (see below)
  5. Under Action, select your webhook or script
  6. Save the event rule

Filtering by Status with Conditions

Event rule conditions let you target specific change request lifecycle transitions. Conditions are evaluated against the serialized object data using JSON logic.

Trigger when a change request is approved:

{
  "attr": "status.value",
  "value": "approved"
}

Trigger when a change request reaches a terminal state (completed or rejected):

{
  "or": [
    {
      "attr": "status.value",
      "value": "completed"
    },
    {
      "attr": "status.value",
      "value": "rejected"
    }
  ]
}

Trigger only for high-priority change requests:

{
  "and": [
    {
      "attr": "status.value",
      "value": "approved"
    },
    {
      "attr": "priority.value",
      "op": "gte",
      "value": 4
    }
  ]
}

The status.value field contains the raw status string (e.g., draft, needs-review, changes-requested, approved, completed, rejected). The priority.value field is an integer where 5 is the highest priority (High) and 1 is the lowest (Low).

Custom Event Types vs. Standard Events

The plugin registers custom event types (e.g., "Change request approved") that generate in-app notifications for relevant users. To trigger webhooks or scripts, use the standard object created/object updated/object deleted events with conditions as described above. See Event Rules for more detail on the distinction.

Webhook Payloads

Default Payload Structure

When no body template is configured, the webhook sends a JSON payload containing all available context. Here is an example payload for a change request that has just been approved (via an object updated event rule):

{
  "event": "updated",
  "timestamp": "2025-01-15T14:30:00.123456+00:00",
  "object_type": "netbox_changes.changerequest",
  "username": "admin",
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "data": {
    "id": 42,
    "url": "https://netbox.example.com/api/plugins/changes/change-requests/42/",
    "display": "Update core switch configs",
    "name": "Update core switch configs",
    "branch": {
      "id": 7,
      "url": "https://netbox.example.com/api/plugins/branching/branches/7/",
      "display": "update-core-switches",
      "name": "update-core-switches",
      "status": "ready",
      "description": ""
    },
    "owner": {
      "id": 3,
      "url": "https://netbox.example.com/api/users/users/3/",
      "display": "jsmith",
      "username": "jsmith"
    },
    "policy": {
      "id": 1,
      "url": "https://netbox.example.com/api/plugins/changes/policies/1/",
      "display": "Standard Review",
      "name": "Standard Review",
      "description": "",
      "rule_count": 2
    },
    "status": {
      "value": "approved",
      "label": "Approved"
    },
    "priority": {
      "value": 3,
      "label": "Medium"
    },
    "comment_count": 2,
    "summary": "Updating management IPs and descriptions for core switches in DC1.",
    "last_updated": "2025-01-15T14:30:00.123456+00:00"
  },
  "snapshots": {
    "prechange": { ... },
    "postchange": { ... }
  },
  "context": {
    "last_branch_change": {
      "id": 1583,
      "time": "2025-01-15T14:25:12.456789+00:00",
      "action": "update",
      "changed_object_type": "dcim.device"
    }
  }
}

Key fields:

  • event: created, updated, or deleted for standard object events; the raw event type string (e.g., event_retriggered) for custom event types
  • data: The serialized ChangeRequest object
  • snapshots: Pre-change and post-change snapshots of the object (populated for standard object events)
  • context: Additional data from webhook callback enrichment, including last_branch_change

Using Body Templates

Webhooks support Jinja2 body templates for formatting the payload to match what an external system expects. All fields from the default payload structure above are available as template variables.

Example: Slack incoming webhook

{
  "text": "Change request *{{ data.name }}* is now *{{ data.status.label }}*",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*<{{ data.url }}|{{ data.name }}>* is now *{{ data.status.label }}*\nOwner: {{ data.owner.display }}\nPolicy: {{ data.policy.display }}\nPriority: {{ data.priority.label }}"
      }
    }
  ]
}

The data.url field contains the API URL of the change request. To link to the UI instead, construct the URL from the NetBox base URL and the change request ID (e.g., https://netbox.example.com/plugins/changes/change-requests/{{ data.id }}/).

Integration Patterns

Status-Driven Automation

Combine object updated event rules with status conditions to drive workflows in external systems:

  • Approval triggers CI/CD: Create an event rule matching {"attr": "status.value", "value": "approved"} to trigger a validation pipeline before merge. The context.last_branch_change field identifies the most recent change on the branch, which can be used to scope the validation.
  • Completion closes tickets: Match {"attr": "status.value", "value": "completed"} to close a corresponding ticket in your ITSM system.
  • Rejection triggers notification: Match {"attr": "status.value", "value": "rejected"} to alert the CR owner through a channel outside NetBox (e.g., email or chat).

Recovery with Retrigger

When an external system misses or fails to process a webhook, use the retrigger action to re-emit the event. This can be done through the UI (retrigger button on the change request detail page) or the API:

POST /api/plugins/changes/change-requests/{id}/retrigger/

Retrigger emits the event_retriggered event type, not the original event type. If your event rules use conditions that filter by event type, you may need a separate event rule for event_retriggered to handle retriggers. Alternatively, configure your external system to treat event_retriggered as a signal to re-check the current state of the change request via the REST API.

Polling via REST API

For systems that prefer pull-based integration or need to periodically sync state, use the REST API to query change requests directly:

GET /api/plugins/changes/change-requests/?status=approved
GET /api/plugins/changes/change-requests/?status=needs-review&priority=1

All standard filtering and pagination parameters are supported. See the REST API reference for the full list of endpoints.

Best Practices

  • Design for idempotency. External systems should handle duplicate or reordered events gracefully. A change request may be updated multiple times in quick succession (e.g., during policy re-evaluation), and each save triggers a separate webhook.
  • Use conditions to reduce noise. Without conditions, an object updated event rule fires on every change request save, including internal state transitions like stale review detection and approval invalidation. Add status conditions to match only the transitions you care about.
  • Keep retrigger in your recovery toolkit. If a webhook target is temporarily unavailable, retrigger lets you replay the event once it recovers. Consider building a monitoring check that calls the retrigger API when it detects missed events.
  • Prefer webhooks for real-time, REST API for batch. Webhooks provide immediate notification of state changes. The REST API is better suited for periodic sync jobs, bulk queries, or systems that need to reconstruct the full state of all active change requests.

On this page