Facade API¶
netbox_sdk now includes an async convenience layer for common NetBox workflows.
It is feature-equivalent to the familiar PyNetBox-style navigation model, but it is
implemented on top of the existing async NetBoxApiClient and schema-driven SDK
internals. It is not a synchronous clone of pynetbox.
Entry point¶
Use api() to create an Api object:
import asyncio
from netbox_sdk import api
async def main():
nb = api("https://netbox.example.com", token="my-token")
version = await nb.version()
print(version)
asyncio.run(main())
Top-level apps are exposed as attributes:
CRUD and filtering¶
Retrieve a single object:
Filter a collection:
devices = nb.dcim.devices.filter(site="lon", role="leaf-switch")
async for device in devices:
print(device.name)
Count matching rows:
Create:
device = await nb.dcim.devices.create(
name="sw-lon-01",
site={"id": 1},
role={"id": 2},
device_type={"id": 3},
)
print(device.id)
Bulk update:
result = await nb.dcim.devices.update(
[
{"id": 10, "name": "sw-lon-10"},
{"id": 11, "name": "sw-lon-11"},
]
)
Bulk delete:
Record helpers¶
Objects returned by the facade are lightweight records with endpoint context.
Refresh full details:
Save only changed fields:
device.name = "sw-lon-01-renamed"
print(device.updates()) # {"name": "sw-lon-01-renamed"}
await device.save()
Delete a single record:
Detail endpoints¶
The facade exposes common NetBox subresources directly from records.
Available IPs and prefixes:
prefix = await nb.ipam.prefixes.get(123)
available_ips = await prefix.available_ips.list()
new_ip = await prefix.available_ips.create({})
new_prefix = await prefix.available_prefixes.create({"prefix_length": 28})
Rack elevation:
rack = await nb.dcim.racks.get(5)
units = await rack.elevation.list()
svg = await rack.elevation.list(render="svg")
NAPALM and render-config:
device = await nb.dcim.devices.get(42)
facts = await device.napalm.list(method="get_facts")
rendered = await device.render_config.create()
Trace and path helpers¶
Traceable records expose trace():
Path-aware records expose paths():
Plugins and app config¶
Installed plugin metadata:
Plugin resources:
Per-app config:
Branch activation¶
Branch-scoped requests can be made with activate_branch():
branch = type("Branch", (), {"schema_id": "feature-x"})()
with nb.activate_branch(branch):
device = await nb.dcim.devices.get(42)
This sets X-NetBox-Branch on requests made within the context.
Strict filters¶
Enable OpenAPI-backed filter validation at API construction time:
Or override per query:
Unknown filters raise ParameterValidationError.
Notes¶
- The facade is async-first. Use it inside
async deffunctions. - It reuses the lower-level client;
NetBoxApiClientremains available when you want direct request control. - The implementation is intentionally explicit. It does not try to reproduce PyNetBox's synchronous or implicit lazy-fetch behavior exactly.