REST API

📦v1.0.0📅2026-03-10🔄Updated 2026-04-28👤Admin Team
developerapiresthttpendpoints

SMS Sender Proxy — REST API Reference

Base URL: http://<host>:8088


Authentication

JWT (Bearer Token)

Used by: /api/v1/dashboard/*, /api/v1/settings/*, /api/v1/smpp/*, /api/v1/sms/*

HeaderRequiredDescription
AuthorizationYesBearer <jwt_token>
X-App-IDYesNumeric application ID

Error responses:

StatusBodyReason
401{"error": "authorization header required"}Missing Authorization
401{"error": "X-App-ID header required"}Missing X-App-ID
400{"error": "invalid X-App-ID"}Non-numeric X-App-ID
401{"error": "unknown app_id"}App not found
401{"error": "invalid or expired token"}JWT verification failed

Admin Key

Used by: /api/v1/admin/*

HeaderRequiredDescription
X-Admin-KeyYesShared secret (ADMIN_API_KEY env)

Error responses:

StatusBodyReason
503{"error": "admin API key not configured"}Server not configured
401{"error": "invalid or missing admin key"}Wrong or missing key

Rate Limiting

  • L1 — Global rate limiter, applied to all requests before routing.
  • L2 — Per-app rate limiter, applied only to /api/v1/sms/* endpoints (after JWT).

1. Monitoring (Public)

GET /healthy

Health check / liveness probe.

Response 200:

{ "status": "ok" }  

GET /metrics

Prometheus metrics. Returns text/plain; version=0.0.4.

GET /dashboard/stats

Real-time system statistics for the dashboard (public, no auth).

Response 200:

{
  "success": true,
  "data": {
    "rps": {
      "current": 1200,
      "data": [
        {
          "time": "14:30",
          "rps": 1150.0
        }
      ]
    },
    "errors": {
      "rate": 0.5,
      "data": [
        {
          "time": "14:30",
          "errors": 3,
          "rate": 0.26
        }
      ]
    },
    "topCampaignStats": [
      {
        "index": 1,
        "name": "campaign-abc",
        "short_name": "campaign-abc",
        "messages": 54321
      }
    ],
    "system": {
      "cpu": 23.4,
      "ram": 65.0,
      "disk": 41.2
    }
  }
} 
StatusReason
200OK
500Failed to get top campaigns

2. Auth — /api/v1/user

No authentication required.

POST /api/v1/user/register

Register a new user.

Request:

{"email": "user@example.com", "password": "secret"}

Response 201:

{ "user_id": 42, "error": "" }  
StatusReason
201Created
400Missing fields / user exists
500Internal error

POST /api/v1/user/login

Authenticate and receive JWT token.

Request:

{"email": "user@example.com",  "password": "secret",  "app_id": 1}  

Response 200:

{ "token": "eyJhbGciOi...", "error": "" }  
StatusReason
200OK
400Missing fields / failed to login
401Invalid email or password

POST /api/v1/user/validate

Check if a user has admin privileges.

Request:

{ "user_id": 42 }  

Response 200:

{ "is_admin": true, "error": "" }  
StatusReason
200OK
400Invalid / zero ID
500Internal error

POST /api/v1/user/delete

Delete a non-admin user.

Request:

{ "user_id": 42 }  

Response 200:

{ "result": true, "error": "" }  
StatusReason
200Deleted
400Zero ID / user is admin
404User not found
500Failed to check admin status

3. Dashboard — /api/v1/dashboard (JWT)

GET /api/v1/dashboard/metrics

Aggregate dashboard metrics.

Response 200:

{
  "success": true,
  "data": {
    "total_messages": 1234567,
    "total_companies": 45,
    "active_connections": 12
  }
}

GET /api/v1/dashboard/stats

Same as public GET /dashboard/stats (see above), but JWT-protected.

List all SMPP links with current status.

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "smpp-link-1",
      "status": "LOADED",
      "current_tps": 100,
      "limit_tps": 100,
      "enabled": true
    }
  ]
}  

GET /api/v1/dashboard/load-balancers

List load balancer pools.

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 0,
      "name": "pool-1",
      "links": [
        "smpp-link-1",
        "smpp-link-2"
      ],
      "total_tps": 200
    }
  ]
}

All dashboard endpoints return 500 on service failure.


4. Settings — /api/v1/settings (JWT)

GET /api/v1/settings/license

Get current license information.

Response 200:

{
  "success": true,
  "data": {
    "company": "UNIQUBIC Corporation",
    "valid_until": "2025-12-31",
    "max_connections": 100,
    "max_tps": 1000,
    "status": "active"
  }
}

POST /api/v1/settings/license/upload

Upload a new license file.

Request: multipart/form-data with field license (file).

Response 200:

{
  "success": true,
  "message": "License uploaded successfully",
  "data": {
    "company": "UNIQUBIC Corporation",
    "valid_until": "2026-12-31",
    "max_connections": 100,
    "max_tps": 1000,
    "status": "active"
  }
}
StatusReason
200Uploaded
400No file / bad format

GET /api/v1/settings/smpp-config

Read-only SMPP connection configuration.

Response 200:

{
  "success": true,
  "data": [
    {
      "host": "smpp.example.com",
      "port": 2775,
      "system_id": "my_system",
      "system_type": "client",
      "interface_version": "3.4",
      "response_timeout": 5
    }
  ]
} 

5. SMPP Control — /api/v1/smpp (JWT)

PUT /api/v1/smpp/:id/toggle

Enable or disable an SMPP link.

Request:

{"enabled": false,  "reason": "maintenance window"}  

Response 200:

{"success": true,  "data": {    "id": 1,    "name": "smpp-link-1",    "enabled": false  }}  
StatusReason
200Toggled
400Invalid ID or request body
500Link not found / error

6. SMS Gateway — /api/v1/sms (JWT + L2 Rate Limit)

POST /api/v1/sms/send

Send an SMS message through the SMPP gateway.

Request:

{
  "esme": 1,
  "source": "+123456789",
  "destination": "+987654321",
  "message": "Hello world",
  "transaction_id": "tx-001"
}

Response 200:

{
  "success": true,
  "error": "",
  "esme": 1,
  "transaction_id": "tx-001",
  "message_id": "msg-uuid",
  "status": "submitted",
  "sms_ids": [
    "sms-001",
    "sms-002"
  ],
  "task_id": 12345
}
StatusReason
200Sent
400Invalid request body
403IP not allowed
500Service / SMPP error

POST /api/v1/sms/check-esme

Verify ESME connection status.

Request:

{ "esme": 1 }  

Response 200:

{"persist": true,  "system_id": "my_system",  "error": ""}  

POST /api/v1/sms/info

Get SMS delivery status.

Request:

{ "esme": 1,  "message_id": "msg-uuid"}  

Response 200:

{
  "message_id": "msg-uuid",
  "mode": "submit_sm",
  "parts": {
    "1": "delivered"
  },
  "delivered_count": 1,
  "sent_at": 1700000000,
  "updated_at": 1700000010,
  "transaction_id": "tx-001",
  "task_id": 12345,
  "status": "delivered",
  "error": ""
} 
StatusReason
200OK
400Invalid request
403IP not allowed
404Message not found
500Service error

7. Admin Panel — /api/v1/admin (Admin Key)

All admin endpoints require the X-Admin-Key header.

Dashboard (mirrors JWT-protected dashboard)

MethodPathSame as
GET/api/v1/admin/dashboard/metrics/api/v1/dashboard/metrics
GET/api/v1/admin/dashboard/smpp-links/api/v1/dashboard/smpp-links
GET/api/v1/admin/dashboard/load-balancers/api/v1/dashboard/load-balancers

Campaign Metrics

GET /api/v1/admin/metrics/campaigns

Paginated campaign metrics from Aerospike.

Query params:

ParamDefaultMaxDescription
page1Page number
limit50100Items per page

Response 200:

{
  "success": true,
  "data": [
    {
      "campaign_uuid": "abc-123",
      "messages_sent": 1000,
      "messages_failed": 5,
      "messages_total": 1005,
      "sme": 1
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 120,
    "totalPages": 3
  }
}

Settings (mirrors JWT-protected settings + server-config)

MethodPathSame as
GET/api/v1/admin/settings/license/api/v1/settings/license
POST/api/v1/admin/settings/license/upload/api/v1/settings/license/upload
GET/api/v1/admin/settings/smpp-config/api/v1/settings/smpp-config

GET /api/v1/admin/settings/server-config

Full server configuration (admin-only).

Response 200:

{
  "success": true,
  "data": {
    "env": "production",
    "server_name": "sms-proxy-01",
    "endpoint": "0.0.0.0:8088",
    "tls": false,
    "storage": {
      "db_path": "/data/sms.db"
    },
    "aerospike": {
      "hosts": "aero-1.local",
      "port": 3000,
      "namespace": "sms",
      "sweep_time": "1h0m0s",
      "ttl": "86400s"
    },
    "security": {
      "token_ttl": "24h0m0s"
    },
    "grpc": {
      "port": 50051,
      "timeout": "5s"
    },
    "smpp": {
      "rules_loaded": true
    },
    "filters": {
      "filter_name": {
        "active": true,
        "blacklist": false,
        "description": "Filter description",
        "snippet": "code snippet"
      }
    },
    "statistic_exporter": {
      "enabled": true,
      "target": "export.example.com",
      "bucket": "sms-stats",
      "tls": true
    },
    "monitoring": {
      "otel": true,
      "sampling": 0.1,
      "collector": "otel-collector:4317"
    }
  }
} 

SMPP Control (mirrors JWT-protected)

MethodPathSame as
PUT/api/v1/admin/smpp/:id/toggle/api/v1/smpp/:id/toggle

Proxy Users Management

GET /api/v1/admin/proxy-users/

List all proxy users (SQLite).

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "email": "api-user@example.com",
      "is_admin": false,
      "app_id": 10,
      "app_name": "my-app",
      "app_secret": "secret-hash"
    }
  ]
} 

POST /api/v1/admin/proxy-users/register

Create a new proxy user with application.

Request:

{
  "email": "api-user@example.com",
  "password": "strongpass",
  "app_name": "my-app",
  "app_secret": "my-secret"
} 

Response 201:

{"success": true,  "data": { "user_id": 42 }}  
StatusReason
201Created
400Missing fields / duplicate user

DELETE /api/v1/admin/proxy-users/:id

Delete a proxy user.

Response 200:

{ "success": true }  
StatusReason
200Deleted
400Invalid ID / error

PUT /api/v1/admin/proxy-users/:id/toggle-admin

Toggle admin role for a proxy user.

Response 200:

{"success": true,  "data": {    "id": 42,    "is_admin": true  }}  
StatusReason
200Toggled
400Invalid ID
500Service error

Endpoint Summary

#MethodPathAuthHandler Package
1GET/healthymonitoringhandler
2GET/metricsmonitoringhandler
3GET/dashboard/statsAdmin Keydashboardhandler
4POST/api/v1/user/registerAdmin Keyauthhandler
5POST/api/v1/user/loginauthhandler
6POST/api/v1/user/validateAdmin Keyauthhandler
7POST/api/v1/user/deleteAdmin Keyauthhandler
8GET/api/v1/dashboard/metricsJWTdashboardhandler
9GET/api/v1/dashboard/statsJWTdashboardhandler
10GET/api/v1/dashboard/smpp-linksJWTdashboardhandler
11GET/api/v1/dashboard/load-balancersJWTdashboardhandler
12GET/api/v1/settings/licenseJWTsettingshandler
13POST/api/v1/settings/license/uploadJWTsettingshandler
14GET/api/v1/settings/smpp-configJWTsettingshandler
15PUT/api/v1/smpp/:id/toggleJWTsmpphandler
16POST/api/v1/sms/check-esmeJWT + L2smshandler
17POST/api/v1/sms/sendJWT + L2smshandler
18POST/api/v1/sms/infoJWT + L2smshandler
19GET/api/v1/admin/dashboard/metricsAdmin Keydashboardhandler
20GET/api/v1/admin/dashboard/smpp-linksAdmin Keydashboardhandler
21GET/api/v1/admin/dashboard/load-balancersAdmin Keydashboardhandler
22GET/api/v1/admin/metrics/campaignsAdmin Keymetricshandler
23GET/api/v1/admin/settings/licenseAdmin Keysettingshandler
24POST/api/v1/admin/settings/license/uploadAdmin Keysettingshandler
25GET/api/v1/admin/settings/server-configAdmin Keysettingshandler
26GET/api/v1/admin/settings/smpp-configAdmin Keysettingshandler
27PUT/api/v1/admin/smpp/:id/toggleAdmin Keysmpphandler
28GET/api/v1/admin/proxy-users/Admin Keyproxyuserhandler
29POST/api/v1/admin/proxy-users/registerAdmin Keyproxyuserhandler
30DELETE/api/v1/admin/proxy-users/:idAdmin Keyproxyuserhandler
31PUT/api/v1/admin/proxy-users/:id/toggle-adminAdmin Keyproxyuserhandler