Skip to main content

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

  1. Overview
  2. API Architecture
  3. Authentication & Access
  4. Endpoint Reference
  5. Configuration Management
  6. Data Retrieval Operations
  7. Common Workflows
  8. Error Handling
  9. 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:

  1. Device credentials (username/password or API keys) are securely stored
  2. Initial connectivity test verifies device is reachable
  3. Device is registered and ready for operations
  4. 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)
  • 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 successful
  • 400 - Invalid parameters or device error
  • 409 - Device already registered
  • 500 - 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:

ParameterTypeRequiredDefaultPurpose
airscale_nameStringYes-Target device name
config_fileStringYes-Path to XML config file on server
take_fallbackBooleanNotrueSave current config as fallback before activation
block_local_changesBooleanNofalseBlock local changes during the operation

Errors:

  • INVALID_FILE - config_file path missing or file does not exist
  • TRANSPORT_ERROR - Network connectivity issue with device
  • SESSION_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:

ParameterTypeExamplePurpose
BtsNameString"SITE_A_Cell_1"Cell/base station identifier
MaxUEsServedInteger256Maximum simultaneous UEs
CellTXPowerInteger40 (dBm)Transmit power level
EnableCarrierAggBooleantrueCarrier aggregation support
HandoverHysteresisInteger3 (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

CodeMeaningExample
200SuccessConfiguration retrieved
201CreatedDevice registered
400Bad RequestInvalid JSON or parameters
401UnauthorizedMissing/invalid API key
404Not FoundDevice doesn't exist
409ConflictDevice already registered
500Server ErrorDatabase connection failure
503UnavailableMaintenance 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 '.'