OmniLCS REST API Reference
The OmniLCS REST API is served over HTTPS on port 8443. The base URL is https://<host>:8443/api.
API documentation (Swagger UI) is available at https://<host>:8443/api/docs. The OpenAPI schema is at https://<host>:8443/api/schema.
Authentication
The API does not currently enforce authentication. Access should be restricted at the network level.
Response Format
All responses use JSON. Successful responses include a "status": "ok" field. Error responses include "status": "error" and a "reason" field.
System Status
GET /api/status
Returns system health and operational status.
Response (200)
{
"status": "ok",
"version": "1.0.0",
"name": "OmniLCS",
"diameter_peers": [
{
"host": "dra01.epc.mnc380.mcc313.3gppnetwork.org",
"realm": "epc.mnc380.mcc313.3gppnetwork.org",
"state": "Connected",
"transport": "sctp"
}
],
"active_sessions": 2,
"completed_sessions": 47,
"cells_loaded": 128,
"cell_sync": {
"last_sync": "2025-01-15T10:30:00Z",
"last_result": "ok (128 cells)",
"sync_count": 42
},
"uptime_seconds": 86400
}
| Field | Type | Description |
|---|---|---|
version | string | Application version |
name | string | Instance name |
diameter_peers | array | Connected Diameter peers with state |
active_sessions | integer | Number of in-progress location sessions |
completed_sessions | integer | Number of completed location sessions |
cells_loaded | integer | Number of cells in the database |
cell_sync | object | InfluxDB sync status |
uptime_seconds | integer | Process uptime in seconds |
Location Services
POST /api/location
Request a new location for a UE.
Request Body
{
"imsi": "001010000000001",
"method": "gnss",
"timeout": 30000,
"mme_host": "mme01.epc.mnc380.mcc313.3gppnetwork.org",
"accuracy": 50
}
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
imsi | string | Yes | -- | IMSI of the UE to locate |
method | string | No | "cell" | Positioning method: "cell", "ecid", "gnss", "otdoa", "hybrid" |
timeout | integer | No | 30000 | Timeout in milliseconds |
mme_host | string | No | -- | Target MME Diameter host. If omitted, uses connected peers. |
accuracy | integer | No | -- | Desired accuracy in meters. Overrides method selection. |
When accuracy is provided, the method is auto-selected:
| Accuracy (meters) | Selected Method |
|---|---|
| <= 50 | GNSS |
| <= 200 | OTDOA |
| <= 500 | E-CID |
| > 500 | Cell ID |
Response (200)
{
"status": "ok",
"imsi": "001010000000001",
"method": "gnss",
"latitude": 40.7128,
"longitude": -74.0060,
"altitude": null,
"uncertainty": 10.5,
"confidence": null,
"source": "gnss",
"duration_ms": 5230,
"timestamp": "2025-01-15T10:30:00Z"
}
| Field | Type | Description |
|---|---|---|
imsi | string | UE identifier |
method | string | Method requested |
latitude | float/null | Latitude in decimal degrees |
longitude | float/null | Longitude in decimal degrees |
altitude | float/null | Altitude in meters (if available) |
uncertainty | float/null | Position uncertainty in meters |
confidence | float/null | Confidence percentage |
source | string | Actual positioning source used |
duration_ms | integer | Time taken in milliseconds |
timestamp | string | ISO 8601 timestamp |
Error Responses
| Status | Reason | Description |
|---|---|---|
| 400 | "imsi is required" | Missing IMSI parameter |
| 404 | "User not found" | IMSI unknown |
| 404 | "User not connected" | UE not attached to network |
| 422 | "No MME host available for this subscriber" | No MME to route the request |
| 504 | "Positioning timed out" | Positioning method did not complete in time |
| 500 | (varies) | Internal error |
GET /api/location
List recent completed location fixes.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Maximum number of results |
Response (200)
{
"status": "ok",
"data": [
{
"imsi": "001010000000001",
"method": "gnss",
"state": "completed",
"latitude": 40.7128,
"longitude": -74.0060,
"uncertainty": 10.5,
"source": "gnss",
"created_at": "2025-01-15T10:29:55Z",
"completed_at": "2025-01-15T10:30:00Z"
}
],
"count": 1
}
GET /api/location/:imsi
Get the last known location for a UE by IMSI.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
imsi | string | IMSI of the UE |
Response (200)
{
"status": "ok",
"imsi": "001010000000001",
"latitude": 40.7128,
"longitude": -74.0060,
"altitude": null,
"uncertainty": 10.5,
"confidence": null,
"source": "gnss",
"timestamp": "2025-01-15T10:30:00Z"
}
Error Responses
| Status | Reason |
|---|---|
| 404 | "No location found for IMSI" |
| 404 | "No completed location for IMSI" |
GET /api/location/:imsi/history
Get location fix history for an IMSI.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
imsi | string | IMSI of the UE |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
from | string | -- | Start of time range (ISO 8601 or date) |
to | string | -- | End of time range (ISO 8601 or date) |
limit | integer | 100 | Maximum number of results |
Response (200)
{
"status": "ok",
"data": [
{
"timestamp": "2025-01-15T10:30:00Z",
"imsi": "001010000000001",
"method": "gnss",
"latitude": 40.7128,
"longitude": -74.0060,
"altitude": null,
"uncertainty": 10.5,
"confidence": null,
"source": "gnss",
"duration_ms": 5230
}
],
"count": 1
}
GET /api/location/:imsi/history/csv
Export location history for an IMSI as a CSV file.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
imsi | string | IMSI of the UE |
Query Parameters
Same as /api/location/:imsi/history.
Response (200)
Returns a CSV file download with headers:
timestamp,imsi,method,latitude,longitude,altitude,uncertainty,confidence,source,duration_ms
Content-Type: text/csv
Content-Disposition: attachment; filename="location_history_<imsi>_<date>.csv"
Cell Database
GET /api/cells
List all cells in the database.
Response (200)
{
"status": "ok",
"data": [
{
"cell_id": "001-01-0001-01",
"latitude": 40.7128,
"longitude": -74.0060,
"pci": 100,
"earfcn": 1300,
"radius": 500,
"azimuth": null,
"height": null,
"prs_config": null,
"updated_at": "2025-01-15T10:00:00Z"
}
],
"count": 1
}
GET /api/cells/:id
Get a single cell by cell_id.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Cell identifier |
Response (200)
{
"status": "ok",
"data": {
"cell_id": "001-01-0001-01",
"latitude": 40.7128,
"longitude": -74.0060,
"pci": 100,
"earfcn": 1300,
"radius": 500,
"azimuth": null,
"height": null,
"prs_config": {
"bandwidth": 50,
"config_index": 0,
"num_dl_frames": 1,
"cp_length": null,
"num_antenna_ports": null
},
"updated_at": "2025-01-15T10:00:00Z"
}
}
Error Response
| Status | Reason |
|---|---|
| 404 | "Cell not found: <id>" |
POST /api/cells
Create a new cell.
Request Body
{
"cell_id": "001-01-0001-01",
"latitude": 40.7128,
"longitude": -74.0060,
"pci": 100,
"earfcn": 1300,
"radius": 500,
"azimuth": 120.0,
"height": 30.0,
"prs_config": {
"bandwidth": 50,
"config_index": 0,
"num_dl_frames": 1,
"cp_length": "normal",
"num_antenna_ports": 2
}
}
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
cell_id | string | Yes | -- | Unique cell identifier |
latitude | float | Yes | -- | Cell latitude (-90 to 90) |
longitude | float | Yes | -- | Cell longitude (-180 to 180) |
pci | integer | No | -- | Physical Cell Identity (0-503) |
earfcn | integer | No | -- | E-UTRA Absolute Radio Frequency Channel Number |
radius | integer | No | 1000 | Coverage radius in meters |
azimuth | float | No | -- | Antenna azimuth in degrees |
height | float | No | -- | Antenna height in meters |
prs_config | object | No | -- | PRS configuration for OTDOA |
tac | integer | No | -- | Tracking Area Code (used for 4G CAP alert broadcast targeting) |
lac | integer | No | -- | Location Area Code (used for 2G and 3G CAP alert broadcast targeting) |
rat | string | No | -- | Radio Access Technology: "4g", "3g", or "2g" |
Response (201)
Returns the created cell in the same format as GET /api/cells/:id.
Error Responses
| Status | Reason |
|---|---|
| 400 | "cell_id is required" |
| 400 | "latitude and longitude are required" |
PUT /api/cells/:id
Update an existing cell. Only provided fields are updated.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Cell identifier |
Request Body
Any cell fields to update (same as POST, but all fields are optional).
Response (200)
Returns the updated cell.
Error Response
| Status | Reason |
|---|---|
| 404 | "Cell not found: <id>" |
DELETE /api/cells/:id
Delete a cell from the database.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Cell identifier |
Response (204)
Empty body on success.
Error Response
| Status | Reason |
|---|---|
| 404 | "Cell not found: <id>" |
GET /api/cells/nearby
Find cells near a geographic point.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
lat | float | Yes | -- | Latitude of search center |
lon | float | Yes | -- | Longitude of search center |
radius | float | No | 10 | Search radius in kilometers |
Response (200)
{
"status": "ok",
"data": [
{
"cell_id": "001-01-0001-01",
"latitude": 40.7128,
"longitude": -74.0060,
"pci": 100,
"earfcn": 1300,
"distance_km": 0.523
}
],
"count": 1
}
Results are sorted by distance (nearest first). Each entry includes a distance_km field.
Error Response
| Status | Reason |
|---|---|
| 400 | "lat and lon query parameters are required" |
POST /api/cells/sync
Trigger an immediate InfluxDB cell sync.
Request Body
None required.
Response (200)
{
"status": "ok",
"cells_synced": 128
}
Error Responses
| Status | Reason |
|---|---|
| 500 | "Sync failed: <reason>" |
| 503 | "Cell sync service unavailable" |
Deferred Location (GMLC)
Manage periodic and geo-fence triggered location sessions. See the GMLC & Le Interface guide for full details on session types and Diameter integration.
GET /api/deferred_location
List all active deferred location sessions.
Response (200):
{
"status": "ok",
"count": 1,
"data": [
{
"session_id": "a1b2c3d4-e5f6-...",
"type": "periodic",
"imsi": "001010000000001",
"method": "cell",
"client_name": "rest-api",
"status": "active",
"interval_ms": 60000,
"remaining_reports": 7,
"total_reports": 10,
"started_at": "2026-04-09T10:00:00Z",
"last_fix_at": "2026-04-09T10:03:00Z"
}
]
}
POST /api/deferred_location
Create a new deferred location session.
Periodic session request body:
{
"type": "periodic",
"imsi": "001010000000001",
"method": "cell",
"interval_seconds": 60,
"count": 10
}
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "periodic" |
imsi | string | Yes | Subscriber IMSI |
method | string | No | Positioning method: cell, ecid, gnss, otdoa. Default: cell |
interval_seconds | integer | Yes | Seconds between fixes |
count | integer | Yes | Total number of fixes to perform |
Triggered session request body:
{
"type": "triggered",
"imsi": "001010000000001",
"method": "cell",
"event_type": "entering",
"poll_interval_seconds": 30,
"max_reports": 0,
"areas": [
{
"type": "circle",
"center": {"lat": -33.8688, "lon": 151.2093},
"radius_meters": 500
}
]
}
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "triggered" |
imsi | string | Yes | Subscriber IMSI |
method | string | No | Positioning method. Default: cell |
event_type | string | Yes | "entering", "leaving", or "being_inside" |
poll_interval_seconds | integer | No | Seconds between position polls. Default: 30 |
max_reports | integer | No | Max trigger reports. 0 = unlimited |
areas | array | Yes | List of area definitions (circle or polygon) |
Response (201):
{"status": "ok", "message": "Periodic session created"}
GET /api/deferred_location/:session_id
Get the status of a deferred session.
Response (200):
{
"status": "ok",
"data": {
"session_id": "a1b2c3d4-...",
"type": "periodic",
"imsi": "001010000000001",
"status": "active",
"remaining_reports": 7,
"total_reports": 10
}
}
DELETE /api/deferred_location/:session_id
Cancel an active deferred session.
Response (200):
{"status": "ok", "message": "Session cancelled"}
| Status | Error |
|---|---|
| 400 | Missing or invalid parameters |
| 404 | Session not found |
CAP Alerts
POST /api/cap
Submit a CAP XML alert for processing. The alert is parsed, polygon warning areas are resolved to TACs/LACs via the cell database, and the alert is either queued for approval or auto-broadcast depending on configuration.
Request Body
{
"xml": "<alert xmlns=\"urn:oasis:names:tc:emergency:cap:1.2\">...</alert>"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
xml | string | Yes | Complete CAP v1.2 XML alert document |
Response (201)
{
"status": "ok",
"data": {
"id": "a1b2c3d4-e5f6-...",
"status": "pending",
"source": "http_post",
"received_at": "2025-01-15T10:30:00Z",
"matched_cells": 42,
"tacs": [100, 101],
"lacs": [5001],
"mcc": "001",
"mnc": "01",
"broadcast_params": {
"message_id": 4370,
"repetition_period": 30,
"num_broadcasts": 10,
"message_text": "Tornado Warning...",
"event": "Tornado Warning",
"severity": "Extreme",
"urgency": "Immediate"
}
}
}
The status field is "pending" when require_approval is true, or "sent" when auto-approved.
Error Responses
| Status | Reason |
|---|---|
| 400 | "xml field is required" |
| 422 | Parse error details |
GET /api/cap
List all alerts across all states (pending, active, history).
Response (200)
{
"status": "ok",
"data": {
"pending": [...],
"active": [...],
"history": [...]
}
}
GET /api/cap/:id
Get a single alert by ID.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Alert UUID |
Response (200)
Returns the alert object.
Error Response
| Status | Reason |
|---|---|
| 404 | "Alert not found: <id>" |
PUT /api/cap/:id
Approve or reject a pending alert.
Request Body
{
"action": "approve",
"operator": "operator1"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | "approve" or "reject" |
operator | string | No | Operator name for audit trail (defaults to "unknown") |
Response (200)
Returns the updated alert object.
Error Responses
| Status | Reason |
|---|---|
| 400 | "action must be 'approve' or 'reject'" |
| 404 | "Alert not found: <id>" |
Error Response Format
All error responses follow this structure:
{
"status": "error",
"reason": "Human-readable error description"
}
Common HTTP status codes:
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (cell creation) |
| 204 | No Content (cell deletion) |
| 400 | Bad Request (missing or invalid parameters) |
| 404 | Not Found (unknown resource) |
| 422 | Unprocessable Entity (valid request but cannot be fulfilled) |
| 500 | Internal Server Error |
| 503 | Service Unavailable |
| 504 | Gateway Timeout (positioning timeout) |