Automation

Automating Device Onboarding into Monitoring with Python and REST APIs

A step-by-step approach to automating network device onboarding into monitoring platforms with Python and REST APIs, including a working script pattern with validation, idempotency and a dry-run mode.

On this page
  1. What "onboarded" should mean
  2. Design principles
  3. Example: a reusable onboarding script
  4. Extending the pattern
  5. Reconciliation: the report that pays for itself
  6. Security considerations

In many organizations, a new switch is racked, cabled and configured in a day, and then waits a week to appear in monitoring. Someone has to add it to the fault manager, the performance platform and the syslog destination list, often by hand, often inconsistently. Until then, it is a blind spot.

Automating onboarding closes that gap. This article describes a pattern that works with any monitoring platform that exposes a REST API, and includes a Python script you can adapt.

What "onboarded" should mean

Agree on a definition first. A device is fully onboarded when:

  1. It is in the source of truth (inventory or CMDB) with correct name, IP, site, role and owner.
  2. It is reachable from the monitoring collectors: ICMP and SNMPv3 or telemetry.
  3. It exists in the fault management platform with the correct device type.
  4. It exists in the performance platform with the right policy for its role.
  5. It sends syslog and traps to the correct collectors.
  6. It is visible on the right dashboards and alert routes.

Automation should check and perform each step, and report what it did.

Design principles

Drive everything from a source of truth. The script should never invent data. It reads device records from your inventory, a CSV export or an API such as NetBox.

Make it idempotent. Running it twice should not create duplicates. Always check whether a device exists before creating it, and update it if attributes differ.

Validate before acting. Check reachability and credentials first. A device that fails validation should be reported, not half-onboarded.

Support a dry run. Engineers should be able to see exactly what would change before anything does.

Log everything. Every create, update and failure should be logged with the device name and reason.

Example: a reusable onboarding script

The example below reads devices from a CSV file, validates reachability and onboards each device into a monitoring platform through its REST API. The API paths and payload fields are placeholders. Replace them with the endpoints documented by your platform.

#!/usr/bin/env python3
"""Onboard network devices into a monitoring platform via REST API."""
import csv
import logging
import os
import subprocess
import sys

import requests

API_BASE = os.environ["MON_API_BASE"]        # e.g. https://monitor.example.com/api/v1
API_TOKEN = os.environ["MON_API_TOKEN"]      # never hard-code credentials
DRY_RUN = "--dry-run" in sys.argv

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
session = requests.Session()
session.headers.update({"Authorization": f"Bearer {API_TOKEN}",
                        "Content-Type": "application/json"})

# Map device role to a monitoring policy/group in your platform
ROLE_POLICY = {"spine": "dc-core", "leaf": "dc-access", "edge": "wan-edge"}


def reachable(ip: str) -> bool:
    """Return True if the device answers ping (Linux ping syntax)."""
    result = subprocess.run(["ping", "-c", "2", "-W", "2", ip],
                            capture_output=True)
    return result.returncode == 0


def find_device(name: str):
    r = session.get(f"{API_BASE}/devices", params={"name": name}, timeout=30)
    r.raise_for_status()
    matches = r.json().get("devices", [])
    return matches[0] if matches else None


def desired_payload(row: dict) -> dict:
    return {
        "name": row["name"],
        "ip": row["ip"],
        "site": row["site"],
        "policy": ROLE_POLICY.get(row["role"], "default"),
        "snmp_profile": "snmpv3-default",
    }


def onboard(row: dict) -> str:
    name, ip = row["name"], row["ip"]
    if not reachable(ip):
        return "FAILED: not reachable"

    want = desired_payload(row)
    existing = find_device(name)

    if existing is None:
        if DRY_RUN:
            return "WOULD CREATE"
        session.post(f"{API_BASE}/devices", json=want, timeout=30).raise_for_status()
        return "CREATED"

    changes = {k: v for k, v in want.items() if existing.get(k) != v}
    if not changes:
        return "OK (no change)"
    if DRY_RUN:
        return f"WOULD UPDATE {sorted(changes)}"
    session.patch(f"{API_BASE}/devices/{existing['id']}", json=changes,
                  timeout=30).raise_for_status()
    return f"UPDATED {sorted(changes)}"


def main(path: str) -> None:
    with open(path, newline="") as f:
        for row in csv.DictReader(f):
            try:
                status = onboard(row)
            except requests.HTTPError as e:
                status = f"FAILED: API error {e.response.status_code}"
            logging.info("%-20s %-15s %s", row["name"], row["ip"], status)


if __name__ == "__main__":
    main(sys.argv[1])

A matching devices.csv looks like this:

name,ip,site,role
dc1-leaf-07,10.20.1.17,DC1,leaf
dc1-leaf-08,10.20.1.18,DC1,leaf
dc1-spine-01,10.20.0.1,DC1,spine

Run python3 onboard.py devices.csv --dry-run first, review the output, then run it without the flag.

Extending the pattern

Multiple platforms. Wrap each platform (fault, performance, log) in a small class with the same find, create and update methods. The main loop then onboards the device everywhere in one pass.

SNMPv3 validation. Before onboarding, confirm SNMPv3 credentials with a quick snmpget of sysName or use a Python SNMP library. Reachability by ping alone doesn't prove the monitoring will work.

Device-side configuration. Use Ansible or your configuration management tool to push the SNMPv3 user, trap targets and syslog servers, so the device side and the monitoring side are always configured together.

Test with Postman first. Before writing code, explore the API in Postman: authenticate, list devices, create a test device. Save the requests as a collection and run it with Newman in CI. It becomes a regression test for your integration whenever the monitoring platform is upgraded.

Trigger from events. Once the script is reliable, trigger it automatically, for example when a device's status in the inventory changes to "active", or on a nightly schedule that reconciles inventory with monitoring.

Reconciliation: the report that pays for itself

The same code can run in audit mode: compare the inventory with each monitoring platform and report:

  • Devices in inventory but missing from monitoring (blind spots)
  • Devices in monitoring but not in inventory (stale or unmanaged devices)
  • Devices with the wrong policy for their role

In our experience, the first reconciliation report in any large environment finds gaps that no one knew existed.

Security considerations

  • Store API tokens and SNMP credentials in a secrets manager or environment variables, never in scripts or Git.
  • Use a dedicated service account with only the permissions onboarding needs.
  • Verify TLS certificates (requests does this by default. Don't turn it off).
  • Log actions, but never log credentials.

Key takeaways

  • Define what "onboarded" means, then automate every step of it.
  • Drive automation from a source of truth, and make it idempotent with a dry-run mode.
  • Validate reachability and credentials before touching monitoring platforms.
  • Use the same code for reconciliation reports to find and fix blind spots.