Skip to content

User - Subscribers ​

Base URL: https://your-domain.com

Admin endpoints for managing subscribers. All endpoints require admin/staff authentication.


Fetch All Subscribers ​

Retrieve a paginated list of subscribers with optional filters and relationship modules.

PropertyValue
EndpointFetch All Subscribers
MethodGET
URL/api/v1/subscribers
AuthenticationBearer Token

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
AuthorizationBearer your-auth-tokenYes

Query Parameters:

Required Parameters ​

ParameterTypeRequiredDescription
isp_idintegerYesISP ID
branch_idintegerYesBranch ID

Pagination Parameters ​

ParameterTypeRequiredDescription
offsetintegerNoPagination offset. Must be sent together with limit
limitintegerNoResults per page. Must be sent together with offset; without both, the first 100 rows are returned

Filter Parameters ​

ParameterTypeRequiredDescription
subscriber_idintegerNoGet single subscriber by ID
salesperson_idintegerNoFilter by salesperson ID
package_idintegerNoFilter by package ID
nas_idintegerNoFilter by NAS ID
searchstringNoSearch by username, email, phone, fullname, or identity
subscriber_typeintegerNoFilter by status (0=Inactive, 1=Pending, 2=Active, 3=Expired, 4=Disabled, 7=Online)
expiring_inintegerNoFilter expiring subscribers (1=1 day, 2=3 days, 3=1 week, 4=2 weeks)
grace_period_statusintegerNoFilter by grace period status (0=No, 1=Yes)
departmentintegerNoFilter by department ID

Location Filter Parameters ​

ParameterTypeRequiredDescription
countryintegerNoFilter by country ID
provinceintegerNoFilter by province ID
cityintegerNoFilter by city ID
areaintegerNoFilter by area ID
subareaintegerNoFilter by subarea ID

Module Loading Parameters ​

Use all_module_status=1 to load all relationships at once, or enable individual modules for optimized performance:

ParameterTypeRequiredDescription
all_module_statusintegerNoLoad ALL relationship modules at once (1=Yes)
package_moduleintegerNoLoad package data (1=Yes)
salesperson_moduleintegerNoLoad salesperson data (1=Yes)
nas_moduleintegerNoLoad NAS data (1=Yes)
radacct_moduleintegerNoLoad RADIUS accounting data (1=Yes)
radchecks_moduleintegerNoLoad RADIUS check attributes (1=Yes)
radreply_moduleintegerNoLoad RADIUS reply attributes (1=Yes)
radusergroup_moduleintegerNoLoad RADIUS user group data (1=Yes)
ip_pool_moduleintegerNoLoad IP pool and address data (1=Yes)
balance_moduleintegerNoLoad current balance data (1=Yes)
area_moduleintegerNoLoad area hierarchy data (1=Yes)
invoice_moduleintegerNoLoad invoices data (1=Yes)
ledger_moduleintegerNoLoad ledger entries (1=Yes)
payment_moduleintegerNoLoad payments data (1=Yes)

Request Body: None

Success Response (200 OK): a JSON array of subscribers (no wrapper object). To page through all subscribers, increase offset by limit until a page returns fewer than limit rows.

json
[
    {
        "id": 1,
        "username": "subscriber001",
        "fullname": "John Doe",
        "email": "[email protected]",
        "phone": "01712345678",
        "package_id": 1,
        "salesperson_id": 1,
        "nas_id": 1,
        "profile_status": 2,
        "expiration_date": "2025-12-31 23:59:59",
        "isp_id": 1,
        "branch_id": 1,
        "created_at": "2024-01-15T10:30:00.000000Z"
    }
]

Fields added by module flags (e.g. current_balance with balance_module=1, packageData with package_module=1, static_ip / ip_pool_name with ip_pool_module=1) appear on each row.

Error Response (401 Unauthorized):

json
{
    "success": false,
    "message": "Unauthenticated"
}

Error Response (403 Forbidden):

json
{
    "success": false,
    "message": "You do not have permission to view subscribers"
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscribers?isp_id=1&branch_id=1&offset=0&limit=50&search=john" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('GET', '/api/v1/subscribers', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'isp_id'    => 1,
        'branch_id' => 1,
        'offset'    => 0,
        'limit'     => 50,
        'search'    => 'john',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  isp_id: 1,
  branch_id: 1,
  offset: 0,
  limit: 50,
  search: 'john',
});

const response = await fetch(`${BASE_URL}/api/v1/subscribers?${params}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.get(
    f"{BASE_URL}/api/v1/subscribers",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "isp_id": 1,
        "branch_id": 1,
        "offset": 0,
        "limit": 50,
        "search": "john",
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers"

	q := url.Values{}
	q.Set("isp_id", "1")
	q.Set("branch_id", "1")
	q.Set("offset", "0")
	q.Set("limit", "50")
	q.Set("search", "john")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscribers"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("isp_id", "1"),
            ("branch_id", "1"),
            ("offset", "0"),
            ("limit", "50"),
            ("search", "john"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Get Subscriber Details ​

Retrieve detailed profile information for a single subscriber.

PropertyValue
EndpointGet Subscriber Details
MethodGET
URL/api/v1/subscribers/details
AuthenticationBearer Token

Query Parameters:

ParameterTypeRequiredDescription
idintegerYesSubscriber ID
isp_idintegerYesISP ID
branch_idintegerYesBranch ID

Request Body: None

Success Response (200 OK):

json
{
    "success": true,
    "data": {
        "id": 1,
        "username": "subscriber001",
        "fullname": "John Doe",
        "email": "[email protected]",
        "phone": "01712345678",
        "address": "123 Main Street",
        "identity": "1234567890",
        "package_id": 1,
        "package_name": "10MB Package",
        "nas_id": 1,
        "static_ip": "192.168.1.100",
        "mac_address": "AA:BB:CC:DD:EE:FF",
        "status": "active",
        "expiration_date": "2025-12-31 23:59:59",
        "balance": 500.00,
        "salesperson_id": 1,
        "salesperson_name": "Sales User",
        "created_at": "2024-01-15 10:30:00"
    }
}

Error Response (404 Not Found):

json
{
    "success": false,
    "message": "Subscriber not found"
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscribers/details?id=1&isp_id=1&branch_id=1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('GET', '/api/v1/subscribers/details', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'id'        => 1,
        'isp_id'    => 1,
        'branch_id' => 1,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  id: 1,
  isp_id: 1,
  branch_id: 1,
});

const response = await fetch(`${BASE_URL}/api/v1/subscribers/details?${params}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.get(
    f"{BASE_URL}/api/v1/subscribers/details",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "id": 1,
        "isp_id": 1,
        "branch_id": 1,
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/details"

	q := url.Values{}
	q.Set("id", "1")
	q.Set("isp_id", "1")
	q.Set("branch_id", "1")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscribers/details"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("id", "1"),
            ("isp_id", "1"),
            ("branch_id", "1"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Create Subscriber ​

Create a new subscriber account.

PropertyValue
EndpointCreate Subscriber
MethodPOST
URL/api/v1/subscribers/create
AuthenticationBearer Token

Request Headers:

HeaderValueRequired
Content-Typeapplication/jsonYes
Acceptapplication/jsonYes
AuthorizationBearer your-auth-tokenYes

Request Body:

json
{
    "isp_id": 1,
    "branch_id": 1,
    "username": "subscriber001",
    "fullname": "John Doe",
    "password": "pass123",
    "package_id": 1,
    "salesperson_id": 1,
    "connection_password": "conn123",
    "static_ip": "192.168.1.100",
    "mac_address": "AA:BB:CC:DD:EE:FF",
    "expiration_date": "2025-12-31 23:59:59",
    "previous_balance": 0,
    "email": "[email protected]",
    "phone": "01712345678",
    "identity": "1234567890",
    "address": "123 Main Street",
    "nas_id": 1,
    "connection_type": 0,
    "profile_status": 0,
    "country": 1,
    "province": 1,
    "city": 1,
    "area": 1,
    "subarea": 1,
    "department": 1,
    "latitude": "23.8103",
    "longitude": "90.4125",
    "auto_renew_status": 1,
    "discount": 0,
    "discount_type": 0,
    "sms_status": 1,
    "email_status": 1,
    "mac_lock_status": 0,
    "total_data_quota": 0,
    "total_session_quota": 0,
    "join_date": "2025-01-01",
    "onu_note": "ONU installed",
    "box_number": "BOX-001",
    "box_address": "Building A",
    "switch_board": "SW-01",
    "switch_port": "Port 1",
    "electric_socket": "Socket A",
    "cable_type": "Fiber",
    "uplink_port": "UP-01",
    "fiber_code": "FC-001",
    "fiber_color": "Blue"
}

Required Parameters ​

ParameterTypeRequiredDescription
isp_idintegerYesISP ID
branch_idintegerYesBranch ID
usernamestringYesUnique username for login
fullnamestringYesSubscriber's full name
passwordstringYesLogin password
package_idintegerYesPackage ID to assign

Connection Parameters ​

ParameterTypeRequiredDescription
salesperson_idintegerNoAssigned salesperson ID
connection_passwordstringNoPPPoE/RADIUS connection password
static_ipstringNoStatic IP address
mac_addressstringNoMAC address for binding
nas_idintegerNoNAS ID for RADIUS
connection_typeintegerNoConnection type (0=PPPoE, 1=Hotspot, etc.)
mac_lock_statusintegerNoMAC lock status (0=Disabled, 1=Enabled)

Profile Parameters ​

ParameterTypeRequiredDescription
expiration_datedatetimeNoAccount expiration date (format: YYYY-MM-DD HH:mm:ss)
previous_balancedecimalNoOpening balance amount
profile_statusintegerNoInitial status (0=Inactive, 1=Pending, 2=Active)
auto_renew_statusintegerNoAuto-renewal (0=Disabled, 1=Enabled)
discountdecimalNoDiscount amount
discount_typeintegerNoDiscount type (0=Fixed, 1=Percentage)
join_datedateNoJoin date (format: YYYY-MM-DD)

Contact Parameters ​

ParameterTypeRequiredDescription
emailstringNoEmail address
phonestringNoPhone number
identitystringNoNational ID / Passport number
addressstringNoFull address
sms_statusintegerNoSMS notifications (0=Disabled, 1=Enabled)
email_statusintegerNoEmail notifications (0=Disabled, 1=Enabled)

Location Parameters ​

ParameterTypeRequiredDescription
countryintegerNoCountry ID
provinceintegerNoProvince ID
cityintegerNoCity ID
areaintegerNoArea ID
subareaintegerNoSubarea ID
departmentintegerNoDepartment ID
latitudestringNoGPS latitude coordinate
longitudestringNoGPS longitude coordinate

Quota Parameters ​

ParameterTypeRequiredDescription
total_data_quotaintegerNoTotal data quota in MB (0=Unlimited)
total_session_quotaintegerNoTotal session quota in minutes (0=Unlimited)

Infrastructure Parameters (ONU/Fiber) ​

ParameterTypeRequiredDescription
onu_notestringNoONU installation notes
box_numberstringNoDistribution box number
box_addressstringNoDistribution box location
switch_boardstringNoSwitch board identifier
switch_portstringNoSwitch port number
electric_socketstringNoElectric socket identifier
cable_typestringNoCable type (Fiber, UTP, etc.)
uplink_portstringNoUplink port identifier
fiber_codestringNoFiber cable code
fiber_colorstringNoFiber cable color

Success Response (201 Created):

data is the full subscriber record that was created.

json
{
    "status": "success",
    "message": "Subscriber created successfully.",
    "data": {
        "id": 151,
        "username": "subscriber001",
        "fullname": "John Doe",
        "package_id": 1,
        "salesperson_id": 1,
        "profile_status": 0,
        "isp_id": 1,
        "branch_id": 1,
        "created_at": "2025-01-01T10:30:00.000000Z"
    }
}

Error Response (422 Validation Error):

json
{
    "success": false,
    "message": "Validation failed",
    "errors": {
        "username": ["The username has already been taken."]
    }
}

Code Examples:

bash
curl -X POST "https://your-domain.com/api/v1/subscribers/create" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "isp_id": 1,
    "branch_id": 1,
    "username": "subscriber001",
    "fullname": "John Doe",
    "password": "pass123",
    "package_id": 1,
    "salesperson_id": 1,
    "connection_password": "conn123",
    "static_ip": "192.168.1.100",
    "mac_address": "AA:BB:CC:DD:EE:FF",
    "expiration_date": "2025-12-31 23:59:59",
    "previous_balance": 0,
    "email": "[email protected]",
    "phone": "01712345678",
    "identity": "1234567890",
    "address": "123 Main Street",
    "nas_id": 1,
    "connection_type": 0,
    "profile_status": 0,
    "country": 1,
    "province": 1,
    "city": 1,
    "area": 1,
    "subarea": 1,
    "department": 1,
    "latitude": "23.8103",
    "longitude": "90.4125",
    "auto_renew_status": 1,
    "discount": 0,
    "discount_type": 0,
    "sms_status": 1,
    "email_status": 1,
    "mac_lock_status": 0,
    "total_data_quota": 0,
    "total_session_quota": 0,
    "join_date": "2025-01-01",
    "onu_note": "ONU installed",
    "box_number": "BOX-001",
    "box_address": "Building A",
    "switch_board": "SW-01",
    "switch_port": "Port 1",
    "electric_socket": "Socket A",
    "cable_type": "Fiber",
    "uplink_port": "UP-01",
    "fiber_code": "FC-001",
    "fiber_color": "Blue"
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('POST', '/api/v1/subscribers/create', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'isp_id'              => 1,
        'branch_id'           => 1,
        'username'            => 'subscriber001',
        'fullname'            => 'John Doe',
        'password'            => 'pass123',
        'package_id'          => 1,
        'salesperson_id'      => 1,
        'connection_password' => 'conn123',
        'static_ip'           => '192.168.1.100',
        'mac_address'         => 'AA:BB:CC:DD:EE:FF',
        'expiration_date'     => '2025-12-31 23:59:59',
        'previous_balance'    => 0,
        'email'               => '[email protected]',
        'phone'               => '01712345678',
        'identity'            => '1234567890',
        'address'             => '123 Main Street',
        'nas_id'              => 1,
        'connection_type'     => 0,
        'profile_status'      => 0,
        'country'             => 1,
        'province'            => 1,
        'city'                => 1,
        'area'                => 1,
        'subarea'             => 1,
        'department'          => 1,
        'latitude'            => '23.8103',
        'longitude'           => '90.4125',
        'auto_renew_status'   => 1,
        'discount'            => 0,
        'discount_type'       => 0,
        'sms_status'          => 1,
        'email_status'        => 1,
        'mac_lock_status'     => 0,
        'total_data_quota'    => 0,
        'total_session_quota' => 0,
        'join_date'           => '2025-01-01',
        'onu_note'            => 'ONU installed',
        'box_number'          => 'BOX-001',
        'box_address'         => 'Building A',
        'switch_board'        => 'SW-01',
        'switch_port'         => 'Port 1',
        'electric_socket'     => 'Socket A',
        'cable_type'          => 'Fiber',
        'uplink_port'         => 'UP-01',
        'fiber_code'          => 'FC-001',
        'fiber_color'         => 'Blue',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/create`, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    isp_id: 1,
    branch_id: 1,
    username: 'subscriber001',
    fullname: 'John Doe',
    password: 'pass123',
    package_id: 1,
    salesperson_id: 1,
    connection_password: 'conn123',
    static_ip: '192.168.1.100',
    mac_address: 'AA:BB:CC:DD:EE:FF',
    expiration_date: '2025-12-31 23:59:59',
    previous_balance: 0,
    email: '[email protected]',
    phone: '01712345678',
    identity: '1234567890',
    address: '123 Main Street',
    nas_id: 1,
    connection_type: 0,
    profile_status: 0,
    country: 1,
    province: 1,
    city: 1,
    area: 1,
    subarea: 1,
    department: 1,
    latitude: '23.8103',
    longitude: '90.4125',
    auto_renew_status: 1,
    discount: 0,
    discount_type: 0,
    sms_status: 1,
    email_status: 1,
    mac_lock_status: 0,
    total_data_quota: 0,
    total_session_quota: 0,
    join_date: '2025-01-01',
    onu_note: 'ONU installed',
    box_number: 'BOX-001',
    box_address: 'Building A',
    switch_board: 'SW-01',
    switch_port: 'Port 1',
    electric_socket: 'Socket A',
    cable_type: 'Fiber',
    uplink_port: 'UP-01',
    fiber_code: 'FC-001',
    fiber_color: 'Blue',
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.post(
    f"{BASE_URL}/api/v1/subscribers/create",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "isp_id": 1,
        "branch_id": 1,
        "username": "subscriber001",
        "fullname": "John Doe",
        "password": "pass123",
        "package_id": 1,
        "salesperson_id": 1,
        "connection_password": "conn123",
        "static_ip": "192.168.1.100",
        "mac_address": "AA:BB:CC:DD:EE:FF",
        "expiration_date": "2025-12-31 23:59:59",
        "previous_balance": 0,
        "email": "[email protected]",
        "phone": "01712345678",
        "identity": "1234567890",
        "address": "123 Main Street",
        "nas_id": 1,
        "connection_type": 0,
        "profile_status": 0,
        "country": 1,
        "province": 1,
        "city": 1,
        "area": 1,
        "subarea": 1,
        "department": 1,
        "latitude": "23.8103",
        "longitude": "90.4125",
        "auto_renew_status": 1,
        "discount": 0,
        "discount_type": 0,
        "sms_status": 1,
        "email_status": 1,
        "mac_lock_status": 0,
        "total_data_quota": 0,
        "total_session_quota": 0,
        "join_date": "2025-01-01",
        "onu_note": "ONU installed",
        "box_number": "BOX-001",
        "box_address": "Building A",
        "switch_board": "SW-01",
        "switch_port": "Port 1",
        "electric_socket": "Socket A",
        "cable_type": "Fiber",
        "uplink_port": "UP-01",
        "fiber_code": "FC-001",
        "fiber_color": "Blue",
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/create"

	payload, _ := json.Marshal(map[string]any{
		"isp_id":              1,
		"branch_id":           1,
		"username":            "subscriber001",
		"fullname":            "John Doe",
		"password":            "pass123",
		"package_id":          1,
		"salesperson_id":      1,
		"connection_password": "conn123",
		"static_ip":           "192.168.1.100",
		"mac_address":         "AA:BB:CC:DD:EE:FF",
		"expiration_date":     "2025-12-31 23:59:59",
		"previous_balance":    0,
		"email":               "[email protected]",
		"phone":               "01712345678",
		"identity":            "1234567890",
		"address":             "123 Main Street",
		"nas_id":              1,
		"connection_type":     0,
		"profile_status":      0,
		"country":             1,
		"province":            1,
		"city":                1,
		"area":                1,
		"subarea":             1,
		"department":          1,
		"latitude":            "23.8103",
		"longitude":           "90.4125",
		"auto_renew_status":   1,
		"discount":            0,
		"discount_type":       0,
		"sms_status":          1,
		"email_status":        1,
		"mac_lock_status":     0,
		"total_data_quota":    0,
		"total_session_quota": 0,
		"join_date":           "2025-01-01",
		"onu_note":            "ONU installed",
		"box_number":          "BOX-001",
		"box_address":         "Building A",
		"switch_board":        "SW-01",
		"switch_port":         "Port 1",
		"electric_socket":     "Socket A",
		"cable_type":          "Fiber",
		"uplink_port":         "UP-01",
		"fiber_code":          "FC-001",
		"fiber_color":         "Blue",
	})
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .post(format!("{BASE_URL}/api/v1/subscribers/create"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "isp_id": 1,
            "branch_id": 1,
            "username": "subscriber001",
            "fullname": "John Doe",
            "password": "pass123",
            "package_id": 1,
            "salesperson_id": 1,
            "connection_password": "conn123",
            "static_ip": "192.168.1.100",
            "mac_address": "AA:BB:CC:DD:EE:FF",
            "expiration_date": "2025-12-31 23:59:59",
            "previous_balance": 0,
            "email": "[email protected]",
            "phone": "01712345678",
            "identity": "1234567890",
            "address": "123 Main Street",
            "nas_id": 1,
            "connection_type": 0,
            "profile_status": 0,
            "country": 1,
            "province": 1,
            "city": 1,
            "area": 1,
            "subarea": 1,
            "department": 1,
            "latitude": "23.8103",
            "longitude": "90.4125",
            "auto_renew_status": 1,
            "discount": 0,
            "discount_type": 0,
            "sms_status": 1,
            "email_status": 1,
            "mac_lock_status": 0,
            "total_data_quota": 0,
            "total_session_quota": 0,
            "join_date": "2025-01-01",
            "onu_note": "ONU installed",
            "box_number": "BOX-001",
            "box_address": "Building A",
            "switch_board": "SW-01",
            "switch_port": "Port 1",
            "electric_socket": "Socket A",
            "cable_type": "Fiber",
            "uplink_port": "UP-01",
            "fiber_code": "FC-001",
            "fiber_color": "Blue"
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Update Subscriber ​

Update an existing subscriber's information.

PropertyValue
EndpointUpdate Subscriber
MethodPUT
URL/api/v1/subscribers/update
AuthenticationBearer Token

Request Body:

json
{
    "id": 1,
    "isp_id": 1,
    "branch_id": 1,
    "fullname": "John Doe Updated",
    "phone": "01712345679"
}
ParameterTypeRequiredDescription
idintegerYesSubscriber ID
isp_idintegerYesISP ID
branch_idintegerYesBranch ID
Other fieldsvariousNoAny subscriber field to update

Success Response (200 OK):

json
{
    "success": true,
    "message": "Subscriber updated successfully"
}

Error Response (404 Not Found):

json
{
    "success": false,
    "message": "Subscriber not found"
}

Code Examples:

bash
curl -X PUT "https://your-domain.com/api/v1/subscribers/update" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "id": 1,
    "isp_id": 1,
    "branch_id": 1,
    "fullname": "John Doe Updated",
    "phone": "01712345679"
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('PUT', '/api/v1/subscribers/update', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'id'        => 1,
        'isp_id'    => 1,
        'branch_id' => 1,
        'fullname'  => 'John Doe Updated',
        'phone'     => '01712345679',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/update`, {
  method: 'PUT',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    id: 1,
    isp_id: 1,
    branch_id: 1,
    fullname: 'John Doe Updated',
    phone: '01712345679',
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.put(
    f"{BASE_URL}/api/v1/subscribers/update",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "id": 1,
        "isp_id": 1,
        "branch_id": 1,
        "fullname": "John Doe Updated",
        "phone": "01712345679",
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/update"

	payload, _ := json.Marshal(map[string]any{
		"id":        1,
		"isp_id":    1,
		"branch_id": 1,
		"fullname":  "John Doe Updated",
		"phone":     "01712345679",
	})
	req, _ := http.NewRequest("PUT", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .put(format!("{BASE_URL}/api/v1/subscribers/update"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "id": 1,
            "isp_id": 1,
            "branch_id": 1,
            "fullname": "John Doe Updated",
            "phone": "01712345679"
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Delete Subscriber ​

Permanently delete a subscriber account.

PropertyValue
EndpointDelete Subscriber
MethodDELETE
URL/api/v1/subscribers/delete
AuthenticationBearer Token

Query Parameters:

ParameterTypeRequiredDescription
idintegerYesSubscriber ID
isp_idintegerYesISP ID
branch_idintegerYesBranch ID
user_idintegerYesAdmin user ID performing deletion

Request Body: None

Success Response (200 OK):

json
{
    "success": true,
    "message": "Subscriber deleted successfully"
}

Error Response (404 Not Found):

json
{
    "success": false,
    "message": "Subscriber not found"
}

Code Examples:

bash
curl -X DELETE "https://your-domain.com/api/v1/subscribers/delete?id=1&isp_id=1&branch_id=1&user_id=1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('DELETE', '/api/v1/subscribers/delete', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'id'        => 1,
        'isp_id'    => 1,
        'branch_id' => 1,
        'user_id'   => 1,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  id: 1,
  isp_id: 1,
  branch_id: 1,
  user_id: 1,
});

const response = await fetch(`${BASE_URL}/api/v1/subscribers/delete?${params}`, {
  method: 'DELETE',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.delete(
    f"{BASE_URL}/api/v1/subscribers/delete",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "id": 1,
        "isp_id": 1,
        "branch_id": 1,
        "user_id": 1,
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/delete"

	q := url.Values{}
	q.Set("id", "1")
	q.Set("isp_id", "1")
	q.Set("branch_id", "1")
	q.Set("user_id", "1")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("DELETE", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .delete(format!("{BASE_URL}/api/v1/subscribers/delete"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("id", "1"),
            ("isp_id", "1"),
            ("branch_id", "1"),
            ("user_id", "1"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Activate/Invoice Subscriber ​

Activate a subscriber and generate an invoice with optional custom expiry date. Supports package change during activation - pass a different package_id to activate with a new package.

PropertyValue
EndpointActivate Subscriber
MethodPOST
URL/api/v1/subscribers/activation
AuthenticationBearer Token

Request Body:

json
{
    "subscriber_id": 1,
    "package_id": 5,
    "payment_amount": 1000,
    "payment_method": 1,
    "cut_subscriber_balance": 1,
    "custom_expiry_datetime": "2026-12-31 23:59:59",
    "preview_only": 0
}

Required Parameters ​

ParameterTypeRequiredDescription
subscriber_idintegerYesSubscriber ID to activate

Optional Parameters ​

ParameterTypeRequiredDescription
package_idintegerNoNew package ID for package change during activation. If not provided, uses subscriber's current package. Must be assigned to the subscriber's salesperson.
payment_amountdecimalNoPayment amount to add to subscriber balance before activation. For free packages (0 fee), pass payment_amount=0 or use cut_subscriber_balance=1.
payment_methodintegerNoPayment method ID (default: 1=Cash). Common values: 1=Cash, 4=Subscriber Balance, 6=Bkash, etc.
cut_subscriber_balanceintegerNoSet to 1 to pay from subscriber balance. This overrides payment_method to 4. Requires sufficient balance.
custom_expiry_datetimedatetimeNoCustom expiry date (format: YYYY-MM-DD HH:MM:SS). Must be a future date.
preview_onlyintegerNoSet to 1 to get activation cost preview without actually activating. Returns calculated fees and balance information.

Payment Required

For paid packages, you MUST provide one of the following:

  • payment_amount >= invoice total amount
  • cut_subscriber_balance=1 with sufficient subscriber balance

For free packages (0 fee), you can:

  • Pass payment_amount=0
  • Or pass cut_subscriber_balance=1
  • Or the system will automatically activate (no payment needed)

Security: The API will return HTTP 402 (Payment Required) if a paid package activation is attempted without proper payment.

Package Change

To change a subscriber's package during activation:

  1. Pass the new package_id in the request
  2. The system will validate the package exists and belongs to the same ISP/Branch
  3. The system will validate the salesperson has this package assigned
  4. All billing and accounting will be calculated based on the new package
  5. On successful activation, the subscriber's package will be updated

Activation Preview Mode ​

Use preview_only=1 to fetch the activation cost before actually activating. This is useful for:

  • Displaying the total amount to the user before payment
  • Checking if subscriber has sufficient balance
  • Calculating required payment amount

Preview Request:

json
{
    "subscriber_id": 1,
    "package_id": 5,
    "preview_only": 1
}

Preview Response (200 OK):

json
{
    "status": "success",
    "preview": true,
    "subscriber_id": 1,
    "subscriber_username": "john_doe",
    "subscriber_fullname": "John Doe",
    "package_id": 5,
    "package_name": "Premium 10Mbps",
    "calculation": {
        "package_fee": 1000.00,
        "package_extra_fee": 50.00,
        "subscriber_discount": 100.00,
        "subscriber_extra_services_total": 0.00,
        "subscriber_activation_fee": 950.00,
        "salesperson_activation_fee": 1050.00,
        "salesperson_profit": 200.00
    },
    "expiration_data": {
        "new_expiration": "2026-04-13 21:48:00",
        "total_hours": 720,
        "total_days": 30
    },
    "subscriber_current_balance": 500.00,
    "balance_sufficient": false,
    "required_payment": 450.00
}

Preview Response Fields:

FieldDescription
calculation.subscriber_activation_feeTotal amount subscriber needs to pay (after discount)
calculation.salesperson_activation_feeFull price without subscriber discount
calculation.subscriber_discountDiscount applied to subscriber
subscriber_current_balanceSubscriber's current balance
balance_sufficienttrue if balance >= activation fee
required_paymentAdditional payment needed if using balance

Two-Step Activation Flow:

  1. Step 1: Get Preview
bash
curl -X POST "https://your-domain.com/api/v1/subscribers/activation" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{"subscriber_id": 1, "preview_only": 1}'
  1. Step 2: Activate with Payment
bash
curl -X POST "https://your-domain.com/api/v1/subscribers/activation" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{"subscriber_id": 1, "payment_amount": 950}'

Success Response (200 OK):

json
{
    "status": "success",
    "message": "Subscriber Activated Successfully.",
    "subscriber_id": 1,
    "subscriber_username": "john_doe",
    "invoice_data": {
        "id": 123,
        "billing_total_amount": 1000,
        "billing_due_amount": 0,
        "invoice_status": 1
    },
    "subscriber_data": {
        "id": 1,
        "username": "john_doe",
        "package_id": 5,
        "profile_status": 2,
        "expiration_date": "2026-12-31 23:59:59"
    }
}

Error Responses:

json
// Subscriber not found
{
    "status": "error",
    "message": "Subscriber Not Found"
}

// Package not found (when package_id provided)
{
    "status": "error",
    "message": "Package Not Found"
}

// Package ISP/Branch mismatch
{
    "status": "error",
    "message": "Package Does Not Belong To Subscriber ISP/Branch"
}

// Salesperson doesn't have package assigned
{
    "status": "error",
    "message": "Invalid Salesperson or Package Data"
}

// Insufficient subscriber balance
{
    "status": "error",
    "message": "Insufficient Subscriber Balance Required (1000)"
}

// Invalid custom expiry date
{
    "status": "error",
    "message": "Custom Expiration Date/Time Invalid! Must Be A Future Date."
}

// Due invoice exists
{
    "status": "error",
    "message": "Due Invoice Already Exist (Wait 1 Hour to Generate New One Or Pay On Due Invoice)",
    "invoice_id": 122,
    "due_amount": 500,
    "subscriber_id": 1
}

// Payment required (402) - Paid package without payment
{
    "status": "error",
    "message": "Payment Required. Invoice Amount: 1000. Provide payment_amount or set cut_subscriber_balance=1 with sufficient balance.",
    "invoice_id": 123,
    "invoice_amount": 1000,
    "subscriber_balance": 0
}

Code Examples:

bash
curl -X POST "https://your-domain.com/api/v1/subscribers/activation" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "subscriber_id": 1,
    "package_id": 5,
    "payment_amount": 1000,
    "payment_method": 1,
    "cut_subscriber_balance": 1,
    "custom_expiry_datetime": "2026-12-31 23:59:59",
    "preview_only": 0
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('POST', '/api/v1/subscribers/activation', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'subscriber_id'          => 1,
        'package_id'             => 5,
        'payment_amount'         => 1000,
        'payment_method'         => 1,
        'cut_subscriber_balance' => 1,
        'custom_expiry_datetime' => '2026-12-31 23:59:59',
        'preview_only'           => 0,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/activation`, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    subscriber_id: 1,
    package_id: 5,
    payment_amount: 1000,
    payment_method: 1,
    cut_subscriber_balance: 1,
    custom_expiry_datetime: '2026-12-31 23:59:59',
    preview_only: 0,
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.post(
    f"{BASE_URL}/api/v1/subscribers/activation",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "subscriber_id": 1,
        "package_id": 5,
        "payment_amount": 1000,
        "payment_method": 1,
        "cut_subscriber_balance": 1,
        "custom_expiry_datetime": "2026-12-31 23:59:59",
        "preview_only": 0,
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/activation"

	payload, _ := json.Marshal(map[string]any{
		"subscriber_id":          1,
		"package_id":             5,
		"payment_amount":         1000,
		"payment_method":         1,
		"cut_subscriber_balance": 1,
		"custom_expiry_datetime": "2026-12-31 23:59:59",
		"preview_only":           0,
	})
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .post(format!("{BASE_URL}/api/v1/subscribers/activation"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "subscriber_id": 1,
            "package_id": 5,
            "payment_amount": 1000,
            "payment_method": 1,
            "cut_subscriber_balance": 1,
            "custom_expiry_datetime": "2026-12-31 23:59:59",
            "preview_only": 0
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Mass Activation ​

Bulk activate multiple subscribers in a single request. This endpoint replicates the exact logic from MassActivationController for 95%+ compatibility with web view functionality.

PropertyValue
EndpointMass Activation
MethodPOST
URL/api/v1/subscribers/mass-activation
AuthenticationBearer Token

Request Body:

json
{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 1,
    "selected_subscribers": "1,2,3",
    "package_id": "current_package",
    "payment_type": 1,
    "custom_expiry_datetime": "2025-12-31 23:59:59"
}
ParameterTypeRequiredDescription
isp_idintegerYesISP ID
branch_idintegerYesBranch ID
user_idintegerYesAdmin user ID
selected_subscribersstringYesComma-separated subscriber IDs
package_idmixedYesPackage ID or "current_package"
payment_typeintegerYes1=Subscriber Balance, 2=Salesperson Balance, 3=Smart
custom_expiry_datetimedatetimeNoCustom expiry date for all

Success Response (200 OK):

json
{
    "success": true,
    "message": "3 subscribers activated successfully",
    "data": {
        "activated": 3,
        "failed": 0
    }
}

Code Examples:

bash
curl -X POST "https://your-domain.com/api/v1/subscribers/mass-activation" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 1,
    "selected_subscribers": "1,2,3",
    "package_id": "current_package",
    "payment_type": 1,
    "custom_expiry_datetime": "2025-12-31 23:59:59"
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('POST', '/api/v1/subscribers/mass-activation', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'isp_id'                 => 1,
        'branch_id'              => 1,
        'user_id'                => 1,
        'selected_subscribers'   => '1,2,3',
        'package_id'             => 'current_package',
        'payment_type'           => 1,
        'custom_expiry_datetime' => '2025-12-31 23:59:59',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/mass-activation`, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    isp_id: 1,
    branch_id: 1,
    user_id: 1,
    selected_subscribers: '1,2,3',
    package_id: 'current_package',
    payment_type: 1,
    custom_expiry_datetime: '2025-12-31 23:59:59',
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.post(
    f"{BASE_URL}/api/v1/subscribers/mass-activation",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "isp_id": 1,
        "branch_id": 1,
        "user_id": 1,
        "selected_subscribers": "1,2,3",
        "package_id": "current_package",
        "payment_type": 1,
        "custom_expiry_datetime": "2025-12-31 23:59:59",
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/mass-activation"

	payload, _ := json.Marshal(map[string]any{
		"isp_id":                 1,
		"branch_id":              1,
		"user_id":                1,
		"selected_subscribers":   "1,2,3",
		"package_id":             "current_package",
		"payment_type":           1,
		"custom_expiry_datetime": "2025-12-31 23:59:59",
	})
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .post(format!("{BASE_URL}/api/v1/subscribers/mass-activation"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "isp_id": 1,
            "branch_id": 1,
            "user_id": 1,
            "selected_subscribers": "1,2,3",
            "package_id": "current_package",
            "payment_type": 1,
            "custom_expiry_datetime": "2025-12-31 23:59:59"
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Package Migration ​

Migrate a subscriber to a new package.

PropertyValue
EndpointPackage Migration
MethodPOST
URL/api/v1/subscribers/migration
AuthenticationBearer Token

Request Body:

json
{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 1,
    "subscriber_id": 1,
    "package_id": 2,
    "action": "preview"
}
FieldTypeRequiredDescription
isp_idintegerYesISP ID
branch_idintegerYesBranch ID
user_idintegerYesActing user (staff/reseller) ID
subscriber_idintegerYesSubscriber to migrate
package_idintegerYesThe package to migrate the subscriber to
actionstring | integerYespreview (or 1) to calculate cost/credit with no changes; migrate (or 2) to execute the migration
payment_methodintegerNo1 = Cash, 2 = Bank, 3 = Mobile, 4 = Subscriber Balance
payment_amountnumericNoAmount paid when the net charge is greater than 0
payment_notestringNoOptional payment note
transaction_idstringNoOptional external transaction reference
skip_paymentbooleanNoSkip payment handling

Two modes (the action field)

  • preview (or 1) — returns the pro-rated cost/credit breakdown; no changes are made. Use it to show the customer what they need to pay.
  • migrate (or 2) — executes the migration (creates the invoice, updates the subscriber, processes payment).

Success Response (200 OK):

json
{
    "success": true,
    "message": "Package migrated successfully",
    "data": {
        "old_package": "10MB Package",
        "new_package": "20MB Package"
    }
}

Code Examples:

bash
curl -X POST "https://your-domain.com/api/v1/subscribers/migration" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 1,
    "subscriber_id": 1,
    "package_id": 2,
    "action": "preview"
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('POST', '/api/v1/subscribers/migration', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'isp_id'        => 1,
        'branch_id'     => 1,
        'user_id'       => 1,
        'subscriber_id' => 1,
        'package_id'    => 2,
        'action'        => 'preview',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/migration`, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    isp_id: 1,
    branch_id: 1,
    user_id: 1,
    subscriber_id: 1,
    package_id: 2,
    action: 'preview',
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.post(
    f"{BASE_URL}/api/v1/subscribers/migration",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "isp_id": 1,
        "branch_id": 1,
        "user_id": 1,
        "subscriber_id": 1,
        "package_id": 2,
        "action": "preview",
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/migration"

	payload, _ := json.Marshal(map[string]any{
		"isp_id":        1,
		"branch_id":     1,
		"user_id":       1,
		"subscriber_id": 1,
		"package_id":    2,
		"action":        "preview",
	})
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .post(format!("{BASE_URL}/api/v1/subscribers/migration"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "isp_id": 1,
            "branch_id": 1,
            "user_id": 1,
            "subscriber_id": 1,
            "package_id": 2,
            "action": "preview"
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Disable Internet ​

Disable a subscriber's internet access without deleting the profile. Sets connection_status = 2 and force-disconnects any live session via CoA. Does NOT touch profile_status.

Added in v2.22.26

Distinct from subscriberProfileDisable (which flips profile_status). Use this one when you want to block net access while keeping the subscriber's profile "active".

PropertyValue
EndpointDisable Internet
MethodPOST
URL/api/v1/subscribers/disable-net
AuthenticationBearer Token

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
Content-Typeapplication/jsonYes
AuthorizationBearer your-auth-tokenYes

Request Body:

json
{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 5,
    "subscriber_id": 42
}
ParameterTypeRequiredDescription
isp_idintegerYesISP ID
branch_idintegerYesBranch ID
user_idintegerYesAction-by user ID (admin/staff)
subscriber_idintegerYesSubscriber ID

Success Response (200 OK):

json
{
    "status": "success",
    "message": "Internet disabled and session disconnected.",
    "data": {
        "subscriber_id": 42,
        "username": "subscriber001",
        "connection_status": 2
    }
}

When the subscriber is offline, the message becomes "Internet disabled. Subscriber was not online." and the operation still succeeds.

Error Response (404 Not Found):

json
{
    "status": "error",
    "message": "Subscriber not found."
}

Code Examples:

bash
curl -X POST "https://your-domain.com/api/v1/subscribers/disable-net" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 5,
    "subscriber_id": 42
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('POST', '/api/v1/subscribers/disable-net', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'isp_id'        => 1,
        'branch_id'     => 1,
        'user_id'       => 5,
        'subscriber_id' => 42,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/disable-net`, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    isp_id: 1,
    branch_id: 1,
    user_id: 5,
    subscriber_id: 42,
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.post(
    f"{BASE_URL}/api/v1/subscribers/disable-net",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "isp_id": 1,
        "branch_id": 1,
        "user_id": 5,
        "subscriber_id": 42,
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/disable-net"

	payload, _ := json.Marshal(map[string]any{
		"isp_id":        1,
		"branch_id":     1,
		"user_id":       5,
		"subscriber_id": 42,
	})
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .post(format!("{BASE_URL}/api/v1/subscribers/disable-net"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "isp_id": 1,
            "branch_id": 1,
            "user_id": 5,
            "subscriber_id": 42
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Enable Internet ​

Re-enable a subscriber's internet access. Sets connection_status = 1. Does NOT touch profile_status.

PropertyValue
EndpointEnable Internet
MethodPOST
URL/api/v1/subscribers/enable-net
AuthenticationBearer Token

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
Content-Typeapplication/jsonYes
AuthorizationBearer your-auth-tokenYes

Request Body:

json
{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 5,
    "subscriber_id": 42
}
ParameterTypeRequiredDescription
isp_idintegerYesISP ID
branch_idintegerYesBranch ID
user_idintegerYesAction-by user ID (admin/staff)
subscriber_idintegerYesSubscriber ID

Success Response (200 OK):

json
{
    "status": "success",
    "message": "Internet enabled successfully.",
    "data": {
        "subscriber_id": 42,
        "username": "subscriber001",
        "connection_status": 1
    }
}

Error Response (404 Not Found):

json
{
    "status": "error",
    "message": "Subscriber not found."
}

Attributes ​

Subscriber attribute management for RADIUS (radcheck/radreply).

Code Examples:

bash
curl -X POST "https://your-domain.com/api/v1/subscribers/enable-net" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "isp_id": 1,
    "branch_id": 1,
    "user_id": 5,
    "subscriber_id": 42
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('POST', '/api/v1/subscribers/enable-net', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'isp_id'        => 1,
        'branch_id'     => 1,
        'user_id'       => 5,
        'subscriber_id' => 42,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/enable-net`, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    isp_id: 1,
    branch_id: 1,
    user_id: 5,
    subscriber_id: 42,
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.post(
    f"{BASE_URL}/api/v1/subscribers/enable-net",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "isp_id": 1,
        "branch_id": 1,
        "user_id": 5,
        "subscriber_id": 42,
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/enable-net"

	payload, _ := json.Marshal(map[string]any{
		"isp_id":        1,
		"branch_id":     1,
		"user_id":       5,
		"subscriber_id": 42,
	})
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .post(format!("{BASE_URL}/api/v1/subscribers/enable-net"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "isp_id": 1,
            "branch_id": 1,
            "user_id": 5,
            "subscriber_id": 42
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Get Subscriber Attributes ​

Retrieve all RADIUS attributes for a subscriber.

PropertyValue
EndpointGet Subscriber Attributes
MethodGET
URL/api/v1/subscribers/attributes
AuthenticationBearer Token

Query Parameters:

ParameterTypeRequiredDescription
subscriber_idintegerYesSubscriber ID
isp_idintegerYesISP ID
branch_idintegerYesBranch ID

Success Response (200 OK):

json
{
    "success": true,
    "data": [
        {
            "id": 1,
            "attribute": "Framed-IP-Address",
            "op": ":=",
            "value": "192.168.1.100"
        }
    ]
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscribers/attributes?subscriber_id=1&isp_id=1&branch_id=1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('GET', '/api/v1/subscribers/attributes', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'subscriber_id' => 1,
        'isp_id'        => 1,
        'branch_id'     => 1,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  subscriber_id: 1,
  isp_id: 1,
  branch_id: 1,
});

const response = await fetch(`${BASE_URL}/api/v1/subscribers/attributes?${params}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.get(
    f"{BASE_URL}/api/v1/subscribers/attributes",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "subscriber_id": 1,
        "isp_id": 1,
        "branch_id": 1,
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/attributes"

	q := url.Values{}
	q.Set("subscriber_id", "1")
	q.Set("isp_id", "1")
	q.Set("branch_id", "1")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscribers/attributes"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("subscriber_id", "1"),
            ("isp_id", "1"),
            ("branch_id", "1"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Add Subscriber Attribute ​

Add a new RADIUS attribute to a subscriber.

PropertyValue
EndpointAdd Subscriber Attribute
MethodPOST
URL/api/v1/subscribers/attributes
AuthenticationBearer Token

Request Body:

json
{
    "subscriber_id": 1,
    "attribute": "Framed-IP-Address",
    "value": "192.168.1.100",
    "op": ":="
}

Success Response (201 Created):

json
{
    "success": true,
    "message": "Attribute added successfully",
    "data": {
        "id": 1
    }
}

Code Examples:

bash
curl -X POST "https://your-domain.com/api/v1/subscribers/attributes" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "subscriber_id": 1,
    "attribute": "Framed-IP-Address",
    "value": "192.168.1.100",
    "op": ":="
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('POST', '/api/v1/subscribers/attributes', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'subscriber_id' => 1,
        'attribute'     => 'Framed-IP-Address',
        'value'         => '192.168.1.100',
        'op'            => ':=',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/attributes`, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    subscriber_id: 1,
    attribute: 'Framed-IP-Address',
    value: '192.168.1.100',
    op: ':=',
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.post(
    f"{BASE_URL}/api/v1/subscribers/attributes",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "subscriber_id": 1,
        "attribute": "Framed-IP-Address",
        "value": "192.168.1.100",
        "op": ":=",
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/attributes"

	payload, _ := json.Marshal(map[string]any{
		"subscriber_id": 1,
		"attribute":     "Framed-IP-Address",
		"value":         "192.168.1.100",
		"op":            ":=",
	})
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .post(format!("{BASE_URL}/api/v1/subscribers/attributes"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "subscriber_id": 1,
            "attribute": "Framed-IP-Address",
            "value": "192.168.1.100",
            "op": ":="
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Update Subscriber Attribute ​

Update an existing RADIUS attribute.

PropertyValue
EndpointUpdate Subscriber Attribute
MethodPUT
URL/api/v1/subscribers/attributes
AuthenticationBearer Token

Request Body:

json
{
    "id": 1,
    "value": "192.168.1.101"
}

Success Response (200 OK):

json
{
    "success": true,
    "message": "Attribute updated successfully"
}

Code Examples:

bash
curl -X PUT "https://your-domain.com/api/v1/subscribers/attributes" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-auth-token" \
  -d '{
    "id": 1,
    "value": "192.168.1.101"
  }'
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('PUT', '/api/v1/subscribers/attributes', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'json' => [
        'id'    => 1,
        'value' => '192.168.1.101',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const response = await fetch(`${BASE_URL}/api/v1/subscribers/attributes`, {
  method: 'PUT',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
  body: JSON.stringify({
    id: 1,
    value: '192.168.1.101',
  }),
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.put(
    f"{BASE_URL}/api/v1/subscribers/attributes",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    json={
        "id": 1,
        "value": "192.168.1.101",
    },
)

data = response.json()
print(data)
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/attributes"

	payload, _ := json.Marshal(map[string]any{
		"id":    1,
		"value": "192.168.1.101",
	})
	req, _ := http.NewRequest("PUT", endpoint, bytes.NewBuffer(payload))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;
use serde_json::json;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .put(format!("{BASE_URL}/api/v1/subscribers/attributes"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .json(&json!({
            "id": 1,
            "value": "192.168.1.101"
        }))
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Delete Subscriber Attribute ​

Delete a RADIUS attribute from a subscriber.

PropertyValue
EndpointDelete Subscriber Attribute
MethodDELETE
URL/api/v1/subscribers/attributes
AuthenticationBearer Token

Query Parameters:

ParameterTypeRequiredDescription
idintegerYesAttribute ID

Success Response (200 OK):

json
{
    "success": true,
    "message": "Attribute deleted successfully"
}

Code Examples:

bash
curl -X DELETE "https://your-domain.com/api/v1/subscribers/attributes?id=1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('DELETE', '/api/v1/subscribers/attributes', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'id' => 1,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  id: 1,
});

const response = await fetch(`${BASE_URL}/api/v1/subscribers/attributes?${params}`, {
  method: 'DELETE',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.delete(
    f"{BASE_URL}/api/v1/subscribers/attributes",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "id": 1,
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscribers/attributes"

	q := url.Values{}
	q.Set("id", "1")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("DELETE", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .delete(format!("{BASE_URL}/api/v1/subscribers/attributes"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("id", "1"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

www.onezeroart.com