API Endpoints & Configuration Management
REST API for Managing RAN Device Configuration and Operations
Guide to managing base station configuration, querying device state, and automating RAN operations using the vendor-agnostic API
Table of Contents
- Overview
- API Architecture
- Authentication & Access
- Endpoint Reference
- Configuration Management
- Data Retrieval Operations
- Common Workflows
- Error Handling
- API Examples
Overview
RAN Monitor exposes a comprehensive REST API for managing RAN device configuration and querying operational data. The API provides a vendor-agnostic interface that abstracts the underlying device communication protocols. The API enables:
- Device Management - Register, unregister, and monitor devices
- Configuration Queries - Retrieve device parameters and system state
- Data Collection - Pull performance metrics, alarms, and topology
- Session Control - Manage communication sessions with devices
- Network Operations - Automate routine management tasks
API Architecture
API Features
- RESTful Design - Standard HTTP methods (GET, POST, PUT, DELETE)
- JSON Format - All requests and responses are JSON
- Vendor Abstraction - Unified API across different device vendors
- Stateful Operations - Maintains device sessions and state
- Error Handling - Detailed error messages and status codes
- Async Processing - Non-blocking requests for long operations
Authentication & Access
Device Registration
Before any operations, a device must be registered with RAN Monitor. Registration establishes the connection between RAN Monitor and the device using each vendor's native authentication mechanism.
Registration Process:
- Device credentials (username/password or API keys) are securely stored
- Initial connectivity test verifies device is reachable
- Device is registered and ready for operations
- Continuous health monitoring begins
API Access Control
Currently, RAN Monitor API is accessible within the management network. For production deployments, consider:
-
Authentication Methods:
- API key in header:
Authorization: Bearer <api-key> - OAuth2 for integration with identity providers
- Network-based access control (firewall/VPN)
- API key in header:
-
Rate Limiting:
- Per-client limits to prevent abuse
- Per-device limits for operation frequency
-
Audit Logging:
- All API calls are logged with timestamps and user/client info
- Configuration changes are tracked with before/after values
API Architecture
REST API Endpoints
The RAN Monitor API is organized into resource-based endpoints:
/api/v1/
├── /devices # Device management
│ ├── GET # List all devices
│ ├── POST # Register new device
│ └── /:id # Device operations
│ ├── GET # Get device details
│ ├── PUT # Update device config
│ ├── DELETE # Remove device
│ ├── /sessions # Session management
│ ├── /config # Configuration operations
│ ├── /alarms # Alarm queries
│ └── /metrics # Performance data
│
├── /operations # Bulk operations
│ ├── /get # Retrieve data
│ ├── /set # Modify configuration
│ └── /search # Search devices
│
└── /health # System health
├── /status # Overall status
└── /devices/:id/ping # Device connectivity
Base URL
http://<ran-monitor-ip>:4000/api/v1
Endpoint Reference
Device Management
List All Devices
GET /api/v1/devices
Response:
{
"data": [
{
"name": "SITE_A_BS1",
"address": "192.168.1.100:8080",
"registration_status": "registered",
"session_status": "active",
"bts_status": "connected",
"vendor": "Nokia",
"agent_type": "AirScale",
"software_release": "BSC-2250.5.0",
"hardware_version": "2.0",
"agent_unique_id": "airscale-001",
"manager_vendor": "Nokia",
"manager_release": "NE3S-5.0",
"license_required": false,
"retention_hours": 720,
"last_connected_at": "2025-12-10T14:30:00Z",
"disconnected_at": null,
"last_error_code": null,
"last_error_string": null,
"data": {
"pm_points": 45320,
"pm_last_write": "2025-12-10T14:15:00Z",
"config_points": 1200,
"config_last_write": "2025-12-10T14:30:00Z",
"alarm_points": 15
},
"pm_warning": null
}
],
"meta": {
"total": 50,
"page": 1,
"per_page": 25,
"total_pages": 2
},
"status_counts": {
"total": 50,
"connected": 45,
"waiting_for_pm": 2,
"pending": 1,
"registering": 0,
"disconnected": 2
}
}
Get Device Details
GET /api/v1/devices/:id
Response:
{
"device": {
"id": "nokia_bs1",
"name": "SITE_A_BS1",
"vendor": "Nokia",
"address": "192.168.1.100",
"registration_status": "registered",
"registration_key": "base64_encoded_key",
"session_id": "nonuniquesession",
"session_expiry": "2025-12-11T14:30:00Z",
"device_info": {
"type": "AirScale",
"software_release": "5.0.0",
"hardware_version": "2.0",
"agent_unique_id": "airscale-001"
}
}
}
Register a Device
PUT /api/v1/devices/:id/register
Content-Type: application/json
{
"address": "192.168.1.100:8080",
"web_username": "admin",
"web_password": "password",
"webhook_url": "http://manager.example.com:9076/webhook",
"private_key_path": "/etc/certs/private.key",
"public_key_path": "/etc/certs/public.key"
}
Response:
{
"result": "Success",
"registration_key": "base64_encoded_nonce",
"device_id": "nokia_bs1",
"message": "Device registered successfully"
}
Status Codes:
200- Registration successful400- Invalid parameters or device error409- Device already registered500- Internal error
Unregister a Device
DELETE /api/v1/devices/:id
Response:
{
"result": "Success",
"message": "Device unregistered",
"device_id": "nokia_bs1"
}
Session Management
Start a Session
PUT /api/v1/devices/:id/sessions
Content-Type: application/json
{
"session_id": "session_unique_identifier"
}
Response:
{
"result": "Success",
"session_id": "session_unique_identifier",
"session_timeout": 86400,
"expires_at": "2025-12-11T14:30:00Z"
}
Session Lifetime:
- Default timeout: 24 hours
- Keep-alive required before timeout
- Automatic refresh every 20 hours
Check Session Status
GET /api/v1/devices/:id/sessions
Response:
{
"session": {
"active": true,
"session_id": "session_unique_identifier",
"expires_at": "2025-12-11T14:30:00Z",
"time_remaining_seconds": 82400,
"last_activity": "2025-12-10T14:30:00Z"
}
}
Keep-Alive Session
POST /api/v1/devices/:id/sessions/keep-alive
Response:
{
"result": "Success",
"new_expiry": "2025-12-11T14:30:00Z"
}
Configuration Management
Query Configuration
Retrieve device configuration parameters:
PUT /api/v1/devices/:id/config/upload
Content-Type: application/json
{
"filter": {
"uploadType": "configuration",
"objects": [
{
"sdn": "/BSC-1/BTS-23/*",
"depth": 100
}
],
"objectClass": ""
}
}
Response:
{
"result": "Success",
"configuration": {
"timestamp": "2025-12-10T14:30:00Z",
"device_id": "nokia_bs1",
"parameters": {
"/BSC-1/BTS-23": {
"BtsBasics": {
"BtsName": "CELL_A",
"BtsType": "MACRO",
"EnvironmentalSpecifications": {
"TemperatureRange": "Industrial"
}
},
"CarrierAggregation": {
"CarrierAggregationCapability": true,
"MaxUECarriers": 5
}
}
}
}
}
Provision Configuration
Push a configuration file to a device, performing download, validation, and activation in a single atomic operation. A fallback of the current running config is saved automatically.
PUT /api/ne3s/function/provision
Content-Type: application/json
{
"airscale_name": "nokia_bs1",
"config_file": "/path/to/config.xml",
"take_fallback": true,
"block_local_changes": false
}
Response:
{
"status": "success",
"operation": "provision",
"plan_id": "plan_1741484400000000000",
"data": "<provisionResponse>...</provisionResponse>"
}
Parameters:
| Parameter | Type | Required | Default | Purpose |
|---|---|---|---|---|
| airscale_name | String | Yes | - | Target device name |
| config_file | String | Yes | - | Path to XML config file on server |
| take_fallback | Boolean | No | true | Save current config as fallback before activation |
| block_local_changes | Boolean | No | false | Block local changes during the operation |
Errors:
INVALID_FILE- config_file path missing or file does not existTRANSPORT_ERROR- Network connectivity issue with deviceSESSION_ERROR- Could not establish NE3S session- SOAP faults from device (e.g. validation errors, schema violations)
Set Configuration Parameter
PUT /api/v1/devices/:id/config/set
Content-Type: application/json
{
"parameter_path": "/BSC-1/BTS-23/BtsBasics/BtsName",
"value": "NEW_CELL_NAME",
"value_type": "string"
}
Response:
{
"result": "Success",
"parameter": "/BSC-1/BTS-23/BtsBasics/BtsName",
"old_value": "CELL_A",
"new_value": "NEW_CELL_NAME",
"applied_at": "2025-12-10T14:30:45Z"
}
Common Configuration Parameters:
| Parameter | Type | Example | Purpose |
|---|---|---|---|
| BtsName | String | "SITE_A_Cell_1" | Cell/base station identifier |
| MaxUEsServed | Integer | 256 | Maximum simultaneous UEs |
| CellTXPower | Integer | 40 (dBm) | Transmit power level |
| EnableCarrierAgg | Boolean | true | Carrier aggregation support |
| HandoverHysteresis | Integer | 3 (dB) | Handover sensitivity |
Get Configuration History
GET /api/v1/devices/:id/config/history?limit=10&days=7
Response:
{
"history": [
{
"timestamp": "2025-12-10T14:30:45Z",
"change_type": "parameter_modified",
"parameter": "/BSC-1/BTS-23/BtsBasics/BtsName",
"old_value": "CELL_A",
"new_value": "NEW_CELL_NAME",
"reason": "Manual config update"
}
]
}
Data Retrieval
Get Performance Metrics
Retrieve performance counter data:
PUT /api/v1/devices/:id/metrics/upload
Content-Type: application/json
{
"filter": {
"uploadType": "measurement",
"objects": [
{
"sdn": "*",
"depth": 100
}
]
}
}
Response:
{
"result": "Success",
"metrics": {
"timestamp": "2025-12-10T14:30:00Z",
"measurement_interval": 300,
"counters": [
{
"id": "M1C1",
"name": "DL Cell Throughput",
"value": 125.4,
"unit": "Mbps",
"cell_dn": "/BSC-1/BTS-23/Cell-1"
},
{
"id": "M1C2",
"name": "UL Cell Throughput",
"value": 89.2,
"unit": "Mbps",
"cell_dn": "/BSC-1/BTS-23/Cell-1"
}
]
}
}
Get Active Alarms
PUT /api/v1/devices/:id/alarms/upload
Content-Type: application/json
{
"filter": {
"uploadType": "active_faults"
}
}
Response:
{
"result": "Success",
"alarms": [
{
"alarm_id": "a1b2c3d4",
"severity": "Critical",
"probable_cause": "Cell Unavailable",
"specific_problem": "Power Supply Failure",
"affected_dn": "/BSC-1/BTS-23/Cell-1",
"event_time": "2025-12-10T14:15:30Z",
"description": "Cell 1 is unavailable due to power supply failure"
}
]
}
Get Device Topology
PUT /api/v1/devices/:id/topology/upload
Content-Type: application/json
{
"filter": {
"uploadType": "topology",
"objects": [
{
"sdn": "*",
"depth": 100
}
]
}
}
Response:
{
"result": "Success",
"topology": {
"device_dn": "/BSC-1",
"managed_elements": [
{
"name": "BTS-23",
"type": "BaseTransceiverStation",
"dn": "/BSC-1/BTS-23",
"cells": [
{
"name": "Cell-1",
"type": "EUtranCell",
"physical_cell_id": 100,
"frequency": 2110
}
]
}
]
}
}
Health Checks
Ping Device
PUT /api/v1/devices/:id/ping
Response:
{
"result": "Success",
"device_id": "nokia_bs1",
"latency_ms": 45,
"status": "reachable"
}
Get System Metrics
GET /api/system-metrics
Returns batch writer stats, PM spool status, per-device InfluxDB stats, and system resource usage.
Response:
{
"data": {
"batch_writer": {
"queue_depth": 120,
"queue_max": 50000,
"flush_count": 8452,
"points_written": 1250000,
"bytes_written": 89000000
},
"pm_spool": {
"pending_files": 3,
"files_processed": 1420,
"files_failed": 0,
"points_written": 980000,
"points_filtered": 4200000,
"bytes_read": 650000000,
"last_file_ms": 245,
"started_at": "2025-12-10T08:00:00Z"
},
"influxdb_stats": [
{
"name": "2045_Booker",
"total": 12500,
"last_write": "2025-12-10T14:15:00Z",
"performance_metrics": 11000,
"configuration": 1200,
"alarms": 300
}
],
"system": {
"memory_total": 524288000,
"memory_processes": 312000000,
"memory_binary": 89000000,
"memory_ets": 45000000,
"process_count": 1250,
"run_queue": 0
}
}
}
Get System Health
GET /api/v1/health/status
Response:
{
"status": "healthy",
"devices": {
"total": 50,
"registered": 48,
"active_sessions": 45,
"unreachable": 2
},
"database": {
"influxdb": "connected"
},
"timestamp": "2025-12-10T14:30:00Z"
}
Configuration Management
Configuration Data Model
Nokia eNodeB configuration is organized hierarchically:
/SystemFunctions
├── /BSC-1 (Base Station Controller)
│ └── /BTS-23 (Base Transceiver Station)
│ ├── BtsBasics (Name, type, location)
│ ├── /Cell-1
│ │ ├── CellCommonData
│ │ ├── CellAdvanced
│ │ └── CarrierAggregation
│ └── /Cell-2
│ └── ...
└── /Connectivity
├── S1Interface
├── X2Interface
└── NetworkConfiguration
Common Configuration Tasks
Enable/Disable a Cell
{
"parameter_path": "/BSC-1/BTS-23/Cell-1/CellCommonData/AdminState",
"value": "UNLOCKED",
"value_type": "enum"
}
Possible values: LOCKED, UNLOCKED, SHUTTING_DOWN
Adjust Cell Power
{
"parameter_path": "/BSC-1/BTS-23/Cell-1/CellAdvanced/CellTXPower",
"value": "35",
"value_type": "integer"
}
Range: 0-46 dBm (device-dependent)
Configure Handover Hysteresis
{
"parameter_path": "/BSC-1/BTS-23/Cell-1/CellAdvanced/HandoverHysteresis",
"value": "3",
"value_type": "integer"
}
Unit: dB, typical range: 0-8 dB
Set Maximum Connected Users
{
"parameter_path": "/BSC-1/BTS-23/MaxUEsServed",
"value": "256",
"value_type": "integer"
}
Device-dependent limit
Common Workflows
Workflow 1: Device Onboarding
Example:
# 1. Create device entry
curl -X POST http://localhost:4000/api/v1/devices \
-H "Content-Type: application/json" \
-d '{
"id": "site_a_bs1",
"name": "SITE_A_BS1",
"vendor": "Nokia",
"address": "192.168.1.100:8080",
"credentials": {
"username": "admin",
"password": "password"
}
}'
# 2. Register with device
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/register \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "http://manager.example.com:9076/webhook"
}'
# 3. Start session
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/sessions \
-H "Content-Type: application/json" \
-d '{"session_id": "session_001"}'
# 4. Get configuration
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/config/upload \
-H "Content-Type: application/json" \
-d '{
"filter": {
"uploadType": "configuration",
"objects": [{"sdn": "*", "depth": 100}]
}
}'
Workflow 2: Configuration Update
# 1. Query current value
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/config/upload \
-H "Content-Type: application/json" \
-d '{
"filter": {
"uploadType": "configuration",
"objects": [{"sdn": "/BSC-1/BTS-23/Cell-1", "depth": 10}]
}
}' | jq '.configuration.parameters["/BSC-1/BTS-23/Cell-1"]'
# 2. Modify parameter
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/config/set \
-H "Content-Type: application/json" \
-d '{
"parameter_path": "/BSC-1/BTS-23/Cell-1/CellAdvanced/CellTXPower",
"value": "38",
"value_type": "integer"
}'
# 3. Verify change
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/config/upload \
-H "Content-Type: application/json" \
-d '{
"filter": {
"uploadType": "configuration",
"objects": [{"sdn": "/BSC-1/BTS-23/Cell-1/CellAdvanced", "depth": 5}]
}
}' | jq '.configuration.parameters["/BSC-1/BTS-23/Cell-1/CellAdvanced/CellTXPower"]'
Workflow 3: Performance Monitoring
# Continuous monitoring loop (example script)
#!/bin/bash
DEVICE="site_a_bs1"
INTERVAL=300 # 5 minutes
while true; do
# Pull metrics
METRICS=$(curl -s -X PUT http://localhost:4000/api/v1/devices/$DEVICE/metrics/upload \
-H "Content-Type: application/json" \
-d '{
"filter": {
"uploadType": "measurement",
"objects": [{"sdn": "*", "depth": 100}]
}
}')
# Extract key metrics
DL=$(echo $METRICS | jq '.metrics.counters[] | select(.id=="M1C1") | .value')
CELLS=$(echo $METRICS | jq '.metrics.counters | length')
echo "$(date): DL=$DL Mbps, Cells=$CELLS"
# Check alarms
ALARMS=$(curl -s -X PUT http://localhost:4000/api/v1/devices/$DEVICE/alarms/upload \
-H "Content-Type: application/json" \
-d '{
"filter": {
"uploadType": "active_faults"
}
}' | jq '.alarms | length')
if [ "$ALARMS" -gt 0 ]; then
echo "WARNING: $ALARMS active alarms"
fi
sleep $INTERVAL
done
Error Handling
HTTP Status Codes
| Code | Meaning | Example |
|---|---|---|
200 | Success | Configuration retrieved |
201 | Created | Device registered |
400 | Bad Request | Invalid JSON or parameters |
401 | Unauthorized | Missing/invalid API key |
404 | Not Found | Device doesn't exist |
409 | Conflict | Device already registered |
500 | Server Error | Database connection failure |
503 | Unavailable | Maintenance mode |
Error Response Format
{
"error": {
"code": "DEVICE_NOT_FOUND",
"message": "Device 'site_a_bs1' not found",
"details": {
"device_id": "site_a_bs1",
"timestamp": "2025-12-10T14:30:00Z"
}
}
}
Common Errors
Device Not Registered:
{
"error": {
"code": "NOT_REGISTERED",
"message": "Device must be registered before operations",
"solution": "Call PUT /api/devices/:id/register first"
}
}
Session Expired:
{
"error": {
"code": "SESSION_EXPIRED",
"message": "Device session has expired",
"solution": "Call PUT /api/devices/:id/sessions to start new session"
}
}
Configuration Parameter Invalid:
{
"error": {
"code": "INVALID_PARAMETER",
"message": "Parameter value out of range",
"details": {
"parameter": "/BSC-1/BTS-23/Cell-1/CellAdvanced/CellTXPower",
"value": "99",
"valid_range": "0-46 dBm"
}
}
}
API Examples
Python Client Example
import requests
import json
class RanMonitorClient:
def __init__(self, base_url="http://localhost:4000/api/v1"):
self.base_url = base_url
self.session = requests.Session()
def register_device(self, device_id, address, username, password):
"""Register a new device"""
url = f"{self.base_url}/devices/{device_id}/register"
payload = {
"address": address,
"web_username": username,
"web_password": password,
"webhook_url": "http://manager:9076/webhook"
}
response = self.session.put(url, json=payload)
return response.json()
def get_config(self, device_id, sdn="*", depth=100):
"""Retrieve device configuration"""
url = f"{self.base_url}/devices/{device_id}/config/upload"
payload = {
"filter": {
"uploadType": "configuration",
"objects": [{"sdn": sdn, "depth": depth}]
}
}
response = self.session.put(url, json=payload)
return response.json()
def set_config(self, device_id, parameter_path, value, value_type="string"):
"""Update a configuration parameter"""
url = f"{self.base_url}/devices/{device_id}/config/set"
payload = {
"parameter_path": parameter_path,
"value": value,
"value_type": value_type
}
response = self.session.put(url, json=payload)
return response.json()
def get_metrics(self, device_id):
"""Retrieve performance metrics"""
url = f"{self.base_url}/devices/{device_id}/metrics/upload"
payload = {
"filter": {
"uploadType": "measurement",
"objects": [{"sdn": "*", "depth": 100}]
}
}
response = self.session.put(url, json=payload)
return response.json()
# Example usage
client = RanMonitorClient()
# Register device
result = client.register_device(
device_id="site_a_bs1",
address="192.168.1.100:8080",
username="admin",
password="password"
)
print(f"Registration: {result}")
# Get configuration
config = client.get_config("site_a_bs1")
print(f"Config: {json.dumps(config, indent=2)}")
# Update parameter
update = client.set_config(
"site_a_bs1",
"/BSC-1/BTS-23/Cell-1/CellAdvanced/CellTXPower",
"38",
"integer"
)
print(f"Update: {update}")
cURL Examples
Register Device:
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/register \
-H "Content-Type: application/json" \
-d '{
"address": "192.168.1.100:8080",
"web_username": "admin",
"web_password": "password",
"webhook_url": "http://manager:9076/webhook"
}'
Get Device Status:
curl -X GET http://localhost:4000/api/v1/devices/site_a_bs1
Query Configuration:
curl -X PUT http://localhost:4000/api/v1/devices/site_a_bs1/config/upload \
-H "Content-Type: application/json" \
-d '{
"filter": {
"uploadType": "configuration",
"objects": [{"sdn": "/BSC-1/*", "depth": 50}]
}
}' | jq '.'