Network Documentation Platform - SDK
Project description
NetDoc SDK
Async Python SDK for the NetDoc /api/v1 API. Provides a modern, type-safe interface for building network discoveries, managing inventory, and querying topology data.
Table of Contents
- Installation
- Quick Start
- Features
- API Reference
- Authentication
- Error Handling
- Advanced Usage
- Troubleshooting
- Source Code
- Contributing
Installation
Via pip (PyPI)
pip install netdoc-sdk
Development version
git clone https://github.com/netdoclab/netdoc-sdk.git
cd netdoc-sdk
pip install -e .
Quick Start
Basic usage with async context manager:
import asyncio
from netdoc_sdk import NetDocClient
async def main():
# Create client and connect
async with NetDocClient("https://netdoc.example.com", token="your-api-token") as client:
# List snapshots
snapshots = await client.snapshots_list()
print(f"Found {len(snapshots)} snapshots")
# Get a specific snapshot
snapshot = await client.snapshots_retrieve(id="snapshot-1")
print(f"Snapshot: {snapshot.label}")
asyncio.run(main())
Creating Network Topology
Build and submit network snapshots using the fluent builder API:
import asyncio
from netdoc_sdk import NetDocClient, DeviceBuilder, SnapshotBuilder
async def main():
async with NetDocClient("https://netdoc.example.com", token="your-api-token") as client:
# Build topology
snapshot = (
SnapshotBuilder(label="nightly", description="Nightly collection")
.add_device(
DeviceBuilder("switch-01", snapshot="snapshot-id")
.vendor("cisco")
.platform("ios-xe")
.software_version("17.9")
.add_vlan(10, "Users")
.add_interface("GigabitEthernet1/0/1", switchport_mode="trunk")
.add_ip_address("Vlan10", "10.0.10.1/24", is_primary=True)
.add_route("0.0.0.0/0", next_hop="10.0.10.254", protocol="static")
.build()
)
.add_link("switch-01", "GigabitEthernet1/0/1", "switch-02", "GigabitEthernet1/0/1")
.build()
)
# Submit to server
result = await client.snapshots_create(snapshot)
print(f"Created snapshot: {result.id}")
asyncio.run(main())
Querying Network Data
async with NetDocClient(base_url, token=token) as client:
# List all devices in a snapshot
devices = await client.devices_list(snapshot="snapshot-id", page_size=50)
# Get topology graph
topology = await client.get_topology_graph(
snapshot="snapshot-id",
include_endpoints=True
)
# Query specific device
device = await client.devices_retrieve(id="device-1")
interfaces = await client.devices_interfaces_list(device=device.id)
# Fetch L2 topology
vlans = await client.vlan_list(snapshot="snapshot-id")
mac_table = await client.mac_entry_list(snapshot="snapshot-id")
Features
✅ Full API Coverage - Every OpenAPI operation exposed as a method
✅ Async/Await - Modern async/await syntax for non-blocking I/O
✅ Type Safe - Full type hints and IDE autocomplete support
✅ Builder Pattern - Fluent API for constructing complex objects
✅ Error Handling - Structured exceptions with status codes and details
✅ Pagination - Automatic page size handling for list operations
✅ Flexible Auth - Token-based or username/password authentication
✅ Multi-tenant - Support for tenant scoping with tenant_id
✅ Connection Pooling - Efficient HTTP connection reuse
✅ Comprehensive Docs - Inline docstrings and examples
API Reference
Discovery & Snapshots
# Snapshot management
await client.snapshots_list()
await client.snapshots_create(snapshot)
await client.snapshots_retrieve(id="...")
await client.snapshots_latest_retrieve()
await client.snapshots_pin_create(id="...")
await client.snapshots_unpin_create(id="...")
# Device management
await client.devices_list(snapshot="...", page_size=50)
await client.devices_create(snapshot, device)
await client.devices_retrieve(id="...")
await client.devices_create_many_create(snapshot, devices)
# Device details
await client.devices_interfaces_list(device="...")
await client.devices_routes_list(device="...")
Network Inventory
Query and explore network elements:
# VLANs, IP addresses, routes
await client.vlan_list(snapshot="...")
await client.ip_address_list(snapshot="...")
await client.route_list(snapshot="...")
# MAC and ARP
await client.mac_entry_list(snapshot="...")
await client.arp_entry_list(snapshot="...")
# Endpoints
await client.endpoint_list(snapshot="...")
await client.canonical_endpoint_list()
# VRF routing
await client.vrf_list(snapshot="...")
Topology
Analyze network topology and connections:
# Topology graph
await client.get_topology_graph(snapshot="...", include_endpoints=True)
# Device connections
await client.device_connection_list(snapshot="...")
# Tunnel connections
await client.tunnel_connection_list(snapshot="...")
# Endpoint connections
await client.endpoint_connection_list(snapshot="...")
# L2 domain lookup
await client.l2_domain_lookup(snapshot="...", vlan=10)
Core / Tenants
Manage credentials, users, and access:
# Credentials
await client.credential_list()
await client.credential_create(credential)
# Tenants
await client.tenant_list()
await client.tenant_create(tenant)
# Users
await client.user_list()
await client.user_create(user)
# Tokens
await client.token_list()
await client.token_create(token)
# Profile
await client.profile_read()
Base URL handling:
base_urlaccepts server root:https://netdoc.example.com- Or API endpoint:
https://netdoc.example.com/api/v1 - Client automatically normalizes both forms
Friendly Aliases
Common operations have shorter aliases:
# Long form
await client.snapshots_list()
await client.snapshots_create(snapshot)
await client.snapshots_retrieve(id="...")
# Short aliases (equivalent)
await client.list_snapshots()
await client.create_snapshot(snapshot)
await client.get_snapshot("...")
# More aliases
await client.list_devices()
await client.create_device(...)
await client.get_topology_graph(...)
Authentication
Token Authentication
Recommended for production use:
client = NetDocClient(
base_url="https://netdoc.example.com",
token="your-api-token"
)
Tokens are sent as Authorization: Token <token> header.
Username/Password Authentication
Authenticate with credentials:
client = await NetDocClient.from_credentials(
base_url="https://netdoc.example.com",
username="collector",
password="secret",
)
Tenant Scoping
For superuser access across tenants:
client = NetDocClient(
base_url="https://netdoc.example.com",
token="admin-token",
tenant_id="tenant-uuid", # Sent as X-Tenant-ID header
)
Custom Headers
Add custom headers to all requests:
client = NetDocClient(
base_url="...",
token="...",
headers={
"X-Custom-Header": "value",
"X-Request-ID": "12345",
}
)
Error Handling
Exception Types
from netdoc_sdk.exceptions import (
NetDocError, # Base exception
AuthenticationError, # 401 Unauthorized
PermissionDeniedError, # 403 Forbidden
NotFoundError, # 404 Not Found
ValidationError, # 400 Bad Request
ConflictError, # 409 Conflict
RateLimitError, # 429 Too Many Requests
ServerError, # 500+ Server Error
ConnectionError, # Network/connection error
)
Handling Errors
from netdoc_sdk import NotFoundError, ValidationError
try:
snapshot = await client.snapshots_retrieve("missing-id")
except NotFoundError as exc:
print(f"Not found: {exc.detail}")
print(f"Status: {exc.status_code}")
except ValidationError as exc:
print(f"Validation errors: {exc.errors}")
except Exception as exc:
print(f"Unexpected error: {exc}")
Error Details
All SDK exceptions include:
try:
await client.device_create(snapshot, device)
except ValidationError as exc:
exc.status_code # HTTP status (400)
exc.detail # Human-readable error message
exc.errors # Structured validation errors dict
str(exc) # Full error representation
Advanced Usage
Pagination
Automatic pagination for list operations:
# Get all devices with automatic pagination
all_devices = []
async for device in await client.devices_list(snapshot="...", page_size=100):
all_devices.append(device)
# Or fetch specific page
response = await client.devices_list(snapshot="...", page=2, page_size=50)
Filtering
Many list operations support filtering:
# Filter devices by vendor
devices = await client.devices_list(
snapshot="snapshot-1",
vendor="cisco",
page_size=100,
)
# Filter snapshots by status
snapshots = await client.snapshots_list(status="completed")
Response Objects
All responses are Pydantic models with type safety:
snapshot = await client.snapshots_retrieve("...")
print(snapshot.id) # IDE autocomplete
print(snapshot.label) # Type checking
print(snapshot.created_at) # datetime object
Connection Management
Explicit connection lifecycle:
# Via context manager (recommended)
async with NetDocClient(base_url, token=token) as client:
result = await client.snapshots_list()
# Manual lifecycle
client = NetDocClient(base_url, token=token)
result = await client.snapshots_list()
await client.close()
Troubleshooting
Connection Issues
Problem: ConnectionError: Failed to connect to netdoc.example.com
Solutions:
- Verify server is running and accessible
- Check firewall rules and network connectivity
- Ensure HTTPS/HTTP protocol is correct
- Try with curl:
curl -H "Authorization: Token $TOKEN" https://netdoc.example.com/api/v1/snapshots/
Authentication Errors
Problem: AuthenticationError: 401 Unauthorized
Solutions:
- Verify API token is correct
- Check token hasn't expired
- Ensure token is passed correctly (not URL encoded)
- Try creating a new token in the web UI
Validation Errors
Problem: ValidationError: 400 Bad Request
Solutions:
- Check error message for specific field issues
- Verify request data matches API schema
- Inspect
exc.errorsdict for per-field details - Review example in quick start above
Type Issues
Problem: mypy or IDE errors about type mismatcements
Solutions:
- Ensure SDK is installed:
pip install netdoc-sdk - Update IDE/mypy cache: Restart IDE or
mypy --no-incremental - Check Python version is 3.12+:
python --version
Source Code
The SDK source code is well-documented and organized:
- Comprehensive docstrings - All classes, functions, and modules have detailed docstrings
- Type hints - Full typing throughout for IDE support and mypy checking
- Clean architecture - Layered design with clear separation of concerns
For detailed information about the source code structure, internal implementation, and development guidelines, see Source Code Reference.
Key Modules
| Module | Purpose | Lines |
|---|---|---|
client.py |
Main async HTTP client | 773 |
exceptions.py |
Exception hierarchy | 270+ |
models/ |
Pydantic request/response models | 612 |
For Developers
- Contributing Code: See CONTRIBUTING.md for development workflow, code standards, and PR process
- Running Tests: See tests/README.md for comprehensive test documentation
- Source Architecture: See docs/source-code.md for internal implementation details
Requirements
- Python: 3.12 or higher
- Dependencies: httpx, pydantic, python-dateutil
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines on:
- Development setup
- Running tests
- Code quality standards
- Commit conventions
- Pull request process
Support
License
MIT License - see LICENSE file for details
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file netdoc_sdk-0.6.2.tar.gz.
File metadata
- Download URL: netdoc_sdk-0.6.2.tar.gz
- Upload date:
- Size: 155.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d615db39f5da552b24441ad1e5fe012971e9d03694ddf4e4850fab6b124f3b3a
|
|
| MD5 |
068f76e36c099e743e2a9beb9d6dce93
|
|
| BLAKE2b-256 |
ef0dcb9eac88b34eb56e94c3e631e363f43406079c2b365f94562129ca993e9c
|
File details
Details for the file netdoc_sdk-0.6.2-py3-none-any.whl.
File metadata
- Download URL: netdoc_sdk-0.6.2-py3-none-any.whl
- Upload date:
- Size: 42.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f636bd795f2ea826f55fe70715a00fc171dbb3854ff56de44a8c9f5b38e00742
|
|
| MD5 |
257114510edda2d5dc8f66d8cab6ecb4
|
|
| BLAKE2b-256 |
af0561109072285874353858aa4ec0f21d3cf82b72955388092804c433ca670b
|