12 KiB
Towerops Mobile API Documentation
Version: 1.0
Base URL: https://your-towerops-instance.com/api/v1/mobile
Table of Contents
Authentication
The Towerops Mobile API uses bearer token authentication. All authenticated requests must include an Authorization header:
Authorization: Bearer <session_token>
QR Code Login Flow
The recommended authentication method is QR code login, which allows users to authenticate without entering credentials in the mobile app.
Step 1: User Generates QR Code
User logs into the web interface at /mobile/qr-login and generates a QR code containing a temporary token.
Step 2: Verify QR Token
Endpoint: POST /api/v1/mobile/auth/qr/verify
Verifies that a scanned QR token is valid before proceeding with login.
Request Body:
{
"token": "base64-encoded-token-from-qr-code"
}
Response (200 OK):
{
"valid": true,
"user_email": "user@example.com"
}
Response (401 Unauthorized):
{
"valid": false,
"error": "Invalid or expired token"
}
Step 3: Complete QR Login
Endpoint: POST /api/v1/mobile/auth/qr/complete
Completes the QR login by creating a long-lived mobile session (90 days).
Request Body:
{
"token": "base64-encoded-token-from-qr-code",
"device_name": "iPhone 15 Pro",
"device_os": "iOS 17.2",
"app_version": "1.0.0"
}
Response (200 OK):
{
"session_token": "long-lived-bearer-token",
"expires_at": "2026-04-15T19:44:25Z",
"user": {
"id": "user-uuid",
"email": "user@example.com"
}
}
Response (401 Unauthorized):
{
"error": "Invalid or expired token"
}
Response (422 Unprocessable Entity):
{
"error": "Failed to create session",
"details": {
"device_name": ["can't be blank"]
}
}
Notes:
- QR tokens expire after 5 minutes
- QR tokens can only be used once
- Session tokens expire after 90 days
- Store the
session_tokensecurely in the device keychain/keystore
Session Management
Get Current Session
Endpoint: GET /api/v1/mobile/auth/session
Headers:
Authorization: Bearer <session_token>
Response (200 OK):
{
"id": "session-uuid",
"device_name": "iPhone 15 Pro",
"device_os": "iOS 17.2",
"app_version": "1.0.0",
"last_used_at": "2026-01-15T19:44:25Z",
"expires_at": "2026-04-15T19:44:25Z"
}
Revoke Session (Logout)
Endpoint: DELETE /api/v1/mobile/auth/session
Headers:
Authorization: Bearer <session_token>
Response (200 OK):
{
"success": true
}
Data Endpoints
All data endpoints require authentication via the Authorization: Bearer <token> header.
Organizations
List Organizations
Endpoint: GET /api/v1/mobile/organizations
Returns all organizations the authenticated user has access to.
Response (200 OK):
{
"organizations": [
{
"id": "org-uuid",
"name": "Acme Corp",
"sites_count": 3,
"equipment_count": 15,
"active_alerts_count": 2
}
]
}
Sites
List Sites
Endpoint: GET /api/v1/mobile/organizations/:organization_id/sites
Returns all sites for an organization.
Response (200 OK):
{
"sites": [
{
"id": "site-uuid",
"name": "Main Office",
"location": "New York, NY",
"equipment_count": 5,
"equipment_down_count": 1
}
]
}
Response (403 Forbidden):
{
"error": "Access denied to this organization"
}
Equipment
List Equipment
Endpoint: GET /api/v1/mobile/organizations/:organization_id/equipment
Returns all equipment for an organization with current status.
Query Parameters:
site_id(optional): Filter by specific site UUIDstatus(optional): Filter by status (up,down,unknown)
Example:
GET /api/v1/mobile/organizations/org-123/equipment?status=down&site_id=site-456
Response (200 OK):
{
"equipment": [
{
"id": "equipment-uuid",
"name": "Core Router",
"ip_address": "192.168.1.1",
"site_name": "Main Office",
"status": "up",
"uptime": "15d 4h",
"last_seen_at": "2026-01-15T19:44:25Z"
}
]
}
Get Equipment Details
Endpoint: GET /api/v1/mobile/equipment/:id
Returns detailed equipment information including interfaces and sensors.
Response (200 OK):
{
"id": "equipment-uuid",
"name": "Core Router",
"ip_address": "192.168.1.1",
"status": "up",
"uptime": "15d 4h",
"site": {
"id": "site-uuid",
"name": "Main Office"
},
"interfaces": [
{
"id": "interface-uuid",
"name": "GigabitEthernet0/0",
"alias": "WAN",
"status": "up",
"admin_status": "up",
"speed": 1000000000,
"mac_address": "00:1A:2B:3C:4D:5E"
}
],
"sensors": [
{
"id": "sensor-uuid",
"name": "CPU Usage",
"type": "cpu",
"unit": "%",
"current_value": 45.5,
"status": "ok"
}
]
}
Response (404 Not Found):
{
"error": "Equipment not found"
}
Response (403 Forbidden):
{
"error": "Access denied to this equipment"
}
Alerts
List Alerts
Endpoint: GET /api/v1/mobile/organizations/:organization_id/alerts
Returns alerts for an organization.
Query Parameters:
severity(optional): Filter by severity (critical,warning,info)status(optional): Filter by status (active,acknowledged,resolved)limit(optional): Number of alerts to return (default 50, max 200)
Example:
GET /api/v1/mobile/organizations/org-123/alerts?severity=critical&status=active&limit=100
Response (200 OK):
{
"alerts": [
{
"id": "alert-uuid",
"severity": "critical",
"status": "active",
"message": "Equipment Down: Core Router",
"equipment_name": "Core Router",
"equipment_id": "equipment-uuid",
"occurred_at": "2026-01-15T19:44:25Z"
}
]
}
Alert Severity Levels:
critical: Requires immediate attention (equipment down, critical sensor thresholds)warning: Requires attention (sensor warnings, interface changes)info: Informational (equipment up, sensor recovery)
Alert Status Values:
active: Alert is active and unacknowledgedacknowledged: Alert has been acknowledged but not resolvedresolved: Alert has been resolved
Error Handling
All API endpoints follow consistent error response formats.
HTTP Status Codes
200 OK: Request succeeded400 Bad Request: Invalid request parameters401 Unauthorized: Missing or invalid authentication token403 Forbidden: Authenticated but not authorized for this resource404 Not Found: Resource not found422 Unprocessable Entity: Validation errors500 Internal Server Error: Server error
Error Response Format
{
"error": "Human-readable error message"
}
For validation errors (422):
{
"error": "Failed to create session",
"details": {
"field_name": ["error message"]
}
}
Rate Limiting
The API does not currently implement rate limiting, but it may be added in future versions. Implement exponential backoff in your client for failed requests.
Best Practices
Token Storage
- Store session tokens securely in the device keychain (iOS) or keystore (Android)
- Never log or expose tokens in plaintext
- Clear tokens on logout
Session Management
- Check session expiration before making requests
- Implement automatic token refresh or re-authentication when sessions expire
- Handle 401 responses by prompting for re-authentication
Network Requests
- Implement timeout handling (30 seconds recommended)
- Use exponential backoff for retries
- Cache responses appropriately (organizations list, equipment details)
- Update last_used_at is automatic - no need to ping
Error Handling
- Display user-friendly error messages
- Log errors for debugging
- Handle network connectivity issues gracefully
- Implement offline mode where appropriate
Example Client Implementation
Swift (iOS)
import Foundation
class ToweropsAPI {
private let baseURL = "https://your-instance.com/api/v1/mobile"
private var sessionToken: String?
// Authenticate with QR token
func completeQRLogin(token: String, deviceInfo: DeviceInfo) async throws -> SessionToken {
let url = URL(string: "\(baseURL)/auth/qr/complete")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body = [
"token": token,
"device_name": deviceInfo.name,
"device_os": deviceInfo.os,
"app_version": deviceInfo.appVersion
]
request.httpBody = try JSONEncoder().encode(body)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw APIError.authenticationFailed
}
let result = try JSONDecoder().decode(SessionToken.self, from: data)
self.sessionToken = result.session_token
return result
}
// Fetch organizations
func fetchOrganizations() async throws -> [Organization] {
guard let token = sessionToken else {
throw APIError.notAuthenticated
}
let url = URL(string: "\(baseURL)/organizations")!
var request = URLRequest(url: url)
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw APIError.requestFailed
}
let result = try JSONDecoder().decode(OrganizationsResponse.self, from: data)
return result.organizations
}
}
Kotlin (Android)
import okhttp3.*
import kotlinx.serialization.json.Json
class ToweropsAPI(private val baseURL: String = "https://your-instance.com/api/v1/mobile") {
private val client = OkHttpClient()
private var sessionToken: String? = null
// Authenticate with QR token
suspend fun completeQRLogin(token: String, deviceInfo: DeviceInfo): SessionToken {
val json = """
{
"token": "$token",
"device_name": "${deviceInfo.name}",
"device_os": "${deviceInfo.os}",
"app_version": "${deviceInfo.appVersion}"
}
""".trimIndent()
val request = Request.Builder()
.url("$baseURL/auth/qr/complete")
.post(RequestBody.create(MediaType.parse("application/json"), json))
.build()
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
throw APIException("Authentication failed")
}
val result = Json.decodeFromString<SessionToken>(response.body()!!.string())
sessionToken = result.session_token
return result
}
// Fetch organizations
suspend fun fetchOrganizations(): List<Organization> {
val token = sessionToken ?: throw APIException("Not authenticated")
val request = Request.Builder()
.url("$baseURL/organizations")
.header("Authorization", "Bearer $token")
.build()
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
throw APIException("Request failed")
}
val result = Json.decodeFromString<OrganizationsResponse>(response.body()!!.string())
return result.organizations
}
}
Support
For API support, bug reports, or feature requests:
- GitHub Issues: https://github.com/yourusername/towerops
- Documentation: https://docs.towerops.net
Changelog
Version 1.0 (2026-01-15)
- Initial release
- QR code authentication
- Basic data endpoints (organizations, sites, equipment, alerts)
- Session management