إدارة عمليات تسجيل دخول المديرين والمشرفين، والتحقق الصارم من جداول الورديات (Shift Enforcement)، وإصدار توكن الأجهزة المتعددة (Multi-Device Bearer Token)، وإدارة الملف الشخصي وصور العرض.
التحقق من بيانات الدخول (اسم المستخدم أو رقم الهاتف المحمول محلياً أو دولياً)، التحقق من تفعيل الحساب، فحص جدول الوردية ومواعيد العمل الرسمية، وتسجيل مخالفات الدخول خارج الوردية، ثم إصدار توكن Bearer مخصص للجهاز.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| login | body | string | إلزامي | اسم المستخدم أو رقم الهاتف المحمول (يدعم 010... أو 2010...) |
| username | body | string | اختياري | بديل لحقل login للتوافق مع شاشات تسجيل الدخول القديمة |
| password | body | string | إلزامي | كلمة مرور حساب المدير |
| device_name | body | string | اختياري | اسم الجهاز أو نوع الهاتف لتتبعه في جلسات التوكن (الافتراضي Android App) |
{
"login": "admin",
"password": "SecretPassword123@",
"device_name": "Samsung Galaxy S24 Ultra (Manager App)"
}
// ApiService.kt
@POST("login")
@FormUrlEncoded
suspend fun login(
@Field("login") identifier: String,
@Field("password") pass: String,
@Field("device_name") deviceName: String? = "Android Manager App"
): Response<LoginResponse>
// ViewModel Usage
val response = apiService.login("admin", "SecretPassword123@", "Samsung S24")
if (response.isSuccessful) {
val token = response.body()?.token
val admin = response.body()?.subscriber // User model
TokenManager.saveToken(token)
}
curl -X POST "https://isp.freenet.net/api/manager/login" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"login": "admin", "password": "SecretPassword123@", "device_name": "Terminal App"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/login`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"login": "admin", "password": "SecretPassword123@", "device_name": "Samsung Galaxy S24 Ultra (Manager App)"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/login');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"login": "admin", "password": "SecretPassword123@", "device_name": "Samsung Galaxy S24 Ultra (Manager App)"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/login', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"login": "admin", "password": "SecretPassword123@", "device_name": "Samsung Galaxy S24 Ultra (Manager App)"}
]);
$data = json_decode($response->getBody(), true);
{
"token": "a1b2c3d4e5f67890123456789abcdef0123456789abcdef0123456789abcdef0",
"admin": {
"id": 1,
"name": "المدير العام للنظام",
"username": "admin",
"phone": "01012345678",
"email": "admin@freenet.local",
"is_active": true,
"balance": 15450.0,
"credit_limit": 50000.0,
"currency_symbol": "EGP",
"role": "Super Admin",
"role_names": [
"Super Admin"
],
"all_permissions": [
"*"
],
"avatar_url": "https://isp.freenet.net/storage/avatars/admin_avatar.png",
"is_within_shift": true
}
}
{
"message": "عذراً، لا يمكنك تسجيل الدخول حالياً خارج مواعيد العمل الرسمية. مواعيد عملك: من 09:00 ص إلى 05:00 م (الأحد - الخميس)",
"off_shift": true,
"shift_info": "من 09:00 ص إلى 05:00 م"
}
استرجاع بيانات المشرف المسجل حالياً، الرصيد المالي الحالي، والحد الائتماني، والصلاحيات الكاملة، والتأكد من استمرار صلاحية الوردية.
@GET("me")
suspend fun getProfile(): Response<User>
// Usage
val profile = apiService.getProfile().body()
println("مرحباً ${profile?.name} - الرصيد: ${profile?.balance} ج.م")
curl -X GET "https://isp.freenet.net/api/manager/me" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Accept: application/json"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/me`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/me');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/me', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"id": 1,
"name": "المدير العام للنظام",
"username": "admin",
"phone": "01012345678",
"email": "admin@freenet.local",
"balance": 15450.0,
"credit_limit": 50000.0,
"admin_prefix": "adm",
"is_within_shift": true,
"profile_photo": "avatars/photo_123.jpg",
"role_names": [
"Super Admin"
],
"all_permissions": [
"view all subscribers",
"renew subscriptions",
"manage vouchers"
]
}
{
"message": "Unauthenticated."
}
رابط بديل (Alias) مطابق لـ /api/manager/me لضمان التوافق مع إضافات المتصفح وتطبيقات الويب الخارجية القديمة.
@GET("profile")
suspend fun getProfileAlias(): Response<User>
curl -X GET "https://isp.freenet.net/api/manager/profile" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/profile`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/profile');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/profile', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"id": 1,
"name": "المدير العام للنظام",
"username": "admin",
"balance": 15450.0,
"is_within_shift": true
}
{
"message": "Unauthenticated."
}
رفع صورة رمزية شخصية لحساب المدير بصيغة Multipart Form Data وتحديث رابط الصورة فورياً في النظام وحساب المشرف.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| photo | body (multipart) | file (image: jpeg, png, webp) | إلزامي | ملف الصورة الشخصية بحد أقصى 5 ميجابايت |
multipart/form-data: photo=@avatar.jpg
@Multipart
@POST("profile/photo")
suspend fun uploadProfilePhoto(
@Part photo: MultipartBody.Part
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/profile/photo" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-F "photo=@/path/to/my_avatar.png"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/profile/photo`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/profile/photo');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/profile/photo', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"avatar_url": "https://isp.freenet.net/storage/avatars/admin_photo_abc.jpg",
"message": "Profile photo updated successfully."
}
{
"message": "The photo field is required.",
"errors": {
"photo": [
"الملف المرفق يجب أن يكون صورة صالحة."
]
}
}
تسجيل خروج المشرف فورياً وحذف سجل التوكن المخصص لهذا الجهاز من جدول AdminDeviceToken في قاعدة البيانات لمنع إعادة استخدامه.
@POST("logout")
suspend fun logout(): Response<Map<String, String>>
curl -X POST "https://isp.freenet.net/api/manager/logout" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/logout`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/logout');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/logout', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"message": "Successfully logged out"
}
{
"message": "Unauthenticated."
}
استعلام لوحة المؤشرات الرئيسية (Dashboard KPIs)، وإحصائيات استهلاك السيرفر، وسيرفرات FreeRADIUS و NAS، وفحص التحديثات لتطبيقات الأندرويد وإدارة الإشعارات.
جلب بطاقات الأداء اللحظية: إجمالي عدد المشتركين، المتصلين أونلاين الآن، المشتركين النشطين، المشتركين المقترب انتهاؤهم، المنتهية اشتراكاتهم، وعدد تذاكر الدعم المفتوحة.
@GET("dashboard")
suspend fun getDashboard(): Response<DashboardResponse>
curl -X GET "https://isp.freenet.net/api/manager/dashboard" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/dashboard`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/dashboard');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/dashboard', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"subscribers_count": 1420,
"online_users": 648,
"active_users": 1180,
"expiring_soon": 72,
"expired_users": 240,
"open_tickets_count": 5,
"today_sales": 12850.0,
"today_renewals_count": 42
}
{
"message": "Unauthenticated."
}
حفظ تخصيصات وتفضيلات المدير لعرض البطاقات الرسومية والودجات الإحصائية في الواجهة وتطبيق الهاتف.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| widgets | body | array of strings | إلزامي | قائمة بأسماء الودجات المفعلة وترتيب ظهورها |
| refresh_interval | body | integer | اختياري | الفاصل الزمني لتحديث البيانات بالثواني (15-300) |
{
"widgets": [
"subscribers_kpi",
"online_chart",
"sales_counter",
"nas_telemetry"
],
"refresh_interval": 30
}
@PUT("dashboard/settings")
suspend fun updateDashboardSettings(@Body data: Map<String, Any>): Response<Map<String, Any>>
curl -X PUT "https://isp.freenet.net/api/manager/dashboard/settings" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"widgets": ["subscribers_kpi", "online_chart"], "refresh_interval": 30}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/dashboard/settings`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"widgets": ["subscribers_kpi", "online_chart", "sales_counter", "nas_telemetry"], "refresh_interval": 30})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/dashboard/settings');
final response = await http.put(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"widgets": ["subscribers_kpi", "online_chart", "sales_counter", "nas_telemetry"], "refresh_interval": 30}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('PUT', 'api/manager/dashboard/settings', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"widgets": ["subscribers_kpi", "online_chart", "sales_counter", "nas_telemetry"], "refresh_interval": 30}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "Dashboard settings updated successfully"
}
{
"message": "The given data was invalid."
}
الاستعلام عن حالة ترخيص النظام، وأحدث إصدارات تطبيقات الهاتف (تطبيق المدير Manager APK، وتطبيق المشترك Consumer APK) مع روابط التنزيل المباشر وإشعار التحديث الإجباري.
@GET("system/updates")
suspend fun getSystemInfo(): Response<SystemInfoResponse>
curl -X GET "https://isp.freenet.net/api/manager/system/updates"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/system/updates`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/system/updates');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/system/updates', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"license_key": "FREENET-PRO-XXXX-XXXX",
"app_name": "FreeNet Billing & Network Master",
"status": "active",
"max_users": 5000,
"current_users": 1420,
"admin_prefix": "adm",
"logo_url": "https://isp.freenet.net/assets/logo.png",
"system_apps_updates": {
"manager": {
"version_code": 24,
"version_name": "3.8.0",
"file_url": "https://isp.freenet.net/downloads/freenet-manager-v3.8.0.apk",
"changelog": "إضافة ميزة البيع السريع للكروت POS ودعم الطابعات الحرارية وإدارة السيرفرات",
"force_update": false
},
"consumer": {
"version_code": 18,
"version_name": "2.4.1",
"file_url": "https://isp.freenet.net/downloads/freenet-subscriber-v2.4.1.apk",
"force_update": false
}
}
}
{
"message": "License validation error"
}
استعلام القياسات اللحظية للسيرفر الفيزيائي: نسبة استهلاك المعالج CPU، والذاكرة العشوائية RAM، والقرص الصلب Disk، وزمن التشغيل Uptime، وحالة خدمات النظام (FreeRADIUS, MariaDB, Nginx, Redis).
@GET("system/info")
suspend fun getServerHardwareMetrics(): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/system/info" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/system/info`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/system/info');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/system/info', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"cpu_usage_percentage": 14.5,
"cpu_cores": 8,
"ram_usage_percentage": 42.1,
"ram_used_gb": 6.7,
"ram_total_gb": 16.0,
"disk_usage_percentage": 33.8,
"disk_free_gb": 185.4,
"system_uptime": "45 days, 14 hours, 22 mins",
"services": {
"mariadb": "running",
"freeradius": "running",
"nginx": "running",
"redis": "running",
"supervisor": "running"
}
}
{
"message": "Unauthorized access."
}
جلب قائمة راوترات وسيرفرات FreeRADIUS المعرفة على النظام (MikroTik, Cisco, Accel-PPP) مع عناوين الـ IP وعدد الجلسات النشطة المتصلة بكل سيرفر.
@GET("nas")
suspend fun getNasList(): Response<List<Map<String, Any>>>
curl -X GET "https://isp.freenet.net/api/manager/nas" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/nas`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/nas');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/nas', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
[
{
"id": 1,
"nasname": "192.168.10.1",
"shortname": "Core-CCR2004-Downtown",
"type": "mikrotik",
"ports": 3799,
"secret": "SharedRadiusSecret2026",
"description": "راوتر الدمج الرئيسي - برج التحرير",
"active_subscribers_count": 412,
"status": "online",
"last_seen_ping": "2.4ms"
},
{
"id": 2,
"nasname": "10.50.0.1",
"shortname": "Tower-East-CCR1009",
"type": "mikrotik",
"active_subscribers_count": 236,
"status": "online"
}
]
{
"message": "Unauthenticated."
}
إرسال أوامر فصل جماعية عبر MikroTik CoA / Disconnect-Request إلى راوتر الـ NAS المحدد لفصل كافة الجلسات النشطة دفعة واحدة (مفيد عند الصيانة أو إعادة تشغيل الراوتر).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف سيرفر الـ NAS |
@POST("nas/{id}/close-sessions")
suspend fun closeAllNasSessions(@Path("id") id: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/nas/1/close-sessions" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/nas/{id}/close-sessions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/nas/{id}/close-sessions');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/nas/{id}/close-sessions', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إرسال حزم الفصل الجماعية بنجاح إلى الراوتر",
"sessions_terminated_count": 412
}
{
"message": "Failed to communicate with NAS device via RADIUS CoA port."
}
استرجاع الإشعارات الخاصة بالمدير: تنبيهات توقف الراوترات، اقتراب رصيد المشرف من النفاد، وتذاكر الدعم الجديدة، وتجاوز حدود الـ FUP.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| unread_only | query | boolean | اختياري | تصفية الإشعارات غير المقروءة فقط (true/false) |
@GET("notifications")
suspend fun getNotifications(@Query("unread_only") unreadOnly: Boolean? = null): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/notifications" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/notifications`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/notifications');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/notifications', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"unread_count": 3,
"data": [
{
"id": "notif_uuid_01",
"title": "تنبيه انقطاع جهاز شبكة",
"message": "تم رصد انقطاع الاتصال مع الراوتر: Tower-North بعد 3 محاولات Ping فاشلة.",
"type": "device_down",
"created_at": "2026-09-09 14:15:00",
"is_read": false
},
{
"id": "notif_uuid_02",
"title": "شحن محفظة موزع",
"message": "قام الموزع 'مكتب الأمل' بطلب شحن رصيد بمبلغ 5,000 ج.م.",
"type": "recharge_request",
"created_at": "2026-09-09 13:40:00",
"is_read": false
}
]
}
{
"message": "Unauthenticated."
}
تحديث حالة الإشعار المحدد ليصبح مقروءاً وإزالته من شارة التنبيهات النشطة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | string | إلزامي | معرف الإشعار (UUID أو ID) |
@POST("notifications/{id}/read")
suspend fun markNotificationAsRead(@Path("id") id: String): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/notifications/notif_uuid_01/read" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/notifications/{id}/read`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/notifications/{id}/read');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/notifications/{id}/read', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "Notification marked as read"
}
{
"message": "Notification not found"
}
إدارة المشتركين الشاملة: القوائم المصفاة متعددة المعايير، البحث السريع، استعراض الملف الكامل بما يطابق نماذج الأندرويد وLaravel، إضافة وتعديل وحذف المشتركين، رفع وحذف صور البطاقات الشخصية والعقود، والعمليات الجماعية وسجلات الجلسات والاستهلاك.
استعلام قائمة المشتركين بصفحات مجزأة (Pagination) مع دعم الفلترة الشاملة حسب الحالة (نشط، منتهي، متصل، محظور)، نوع الاتصال (Hotspot, PPPoE)، الباقة، المشرف، راوتر NAS، البرج/المجموعة، والبحث الشامل.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة (الافتراضي: 1) |
| per_page | query | integer | اختياري | عدد السجلات بالصفحة (الافتراضي: 20) |
| search | query | string | اختياري | البحث بالاسم، اسم المستخدم، رقم الهاتف، الآيبي، الماك أدرس، أو رقم العقد |
| filter_status | query | string | اختياري | الحالة: active_users, online_users, expired_users, expiring_soon, paused, disabled, all |
| filter_connection_type | query | string | اختياري | نوع الاتصال: pppoe, hotspot, static |
| filter_plan_id | query | integer | اختياري | معرف باقة الخدمة |
| filter_admin_id | query | integer | اختياري | معرف المشرف المسؤول |
| filter_nas_id | query | integer | اختياري | معرف راوتر الـ NAS |
| filter_group_id | query | integer | اختياري | معرف المجموعة أو البرج |
| sort_field | query | string | اختياري | حقل الترتيب: id, name, expires_at, balance |
| sort_direction | query | string | اختياري | اتجاه الترتيب: asc أو desc |
@GET("subscribers")
suspend fun getSubscribers(
@Query("page") page: Int = 1,
@Query("per_page") perPage: Int? = 20,
@Query("search") search: String? = null,
@Query("filter_status") status: String? = null,
@Query("filter_connection_type") connectionType: String? = null,
@Query("filter_plan_id") planId: Int? = null,
@Query("filter_admin_id") adminId: Int? = null,
@Query("filter_nas_id") nasId: Int? = null
): Response<SubscriberListResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers?filter_status=active_users&page=1" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"current_page": 1,
"per_page": 20,
"total": 1420,
"last_page": 71,
"data": [
{
"id": 105,
"name": "محمود أحمد حسن",
"username": "mahmoud.ahmed",
"phone": "01098765432",
"address": "شارع الجمهورية - عمارة الأمل الدور الثالث",
"avatar_url": "https://isp.freenet.net/storage/subscribers/105_photo.jpg",
"status": "active",
"online_status": true,
"active_session_type": "pppoe",
"balance": 25.0,
"currency_symbol": "EGP",
"current_plan_name": "باقة سوبر 30 ميجا - 250 جيجا",
"total_unpaid_debt": 0.0,
"days_remaining": 14,
"days_remaining_string": "متبقي 14 يوم",
"expires_at_formatted": "2026-09-23 23:59:59",
"usage": {
"used": "142.5 GB",
"total": "250.0 GB",
"remaining": "107.5 GB",
"percentage": 57
},
"status_badges": [
{
"text": "متصل أونلاين",
"text_ar": "متصل",
"color": "#10b981",
"bg_color": "#ecfdf5"
}
]
}
]
}
{
"message": "Unauthenticated."
}
استرجاع كافة خيارات الفلاتر ومساعدات الإدخال: قائمة الباقات المتاحة للمدير، المشرفين التابعين، الأبراج والمجموعات، وأجهزة الشبكة وراوترات الراديوس.
@GET("subscribers/filter-data")
suspend fun getFilterData(): Response<FilterDataResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/filter-data" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/filter-data`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/filter-data');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/filter-data', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"plans": [
{
"id": 1,
"name": "باقة سوبر 30 ميجا",
"price": 180.0,
"quota_gb": 250
},
{
"id": 2,
"name": "باقة الترا 70 ميجا",
"price": 320.0,
"quota_gb": 400
}
],
"admins": [
{
"id": 1,
"name": "المدير العام",
"username": "admin"
},
{
"id": 2,
"name": "موزع سنترال المحطة",
"username": "reseller_station"
}
],
"groups": [
{
"id": 1,
"name": "برج التحرير"
},
{
"id": 2,
"name": "برج الزهور"
}
],
"nas_devices": [
{
"id": 1,
"shortname": "CCR-Main-2004",
"nasname": "192.168.10.1"
}
],
"connection_types": [
{
"value": "pppoe",
"label": "PPPoE (المنزلي)"
},
{
"value": "hotspot",
"label": "Hotspot (الوايرلس)"
},
{
"value": "static",
"label": "Static IP (الشركات)"
}
]
}
{
"message": "Unauthenticated."
}
رابط بحث سريع فوري مخصص لأشرطة البحث المنبثقة وشاشات الإكمال التلقائي في تطبيق الأندرويد والويب.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| search | query | string | إلزامي | الكلمة المفتاحية للبحث |
@GET("subscribers/search")
suspend fun searchSubscribers(@Query("search") query: String): Response<SubscriberListResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/search?search=mahmoud" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/search`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/search');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/search', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 105,
"name": "محمود أحمد حسن",
"username": "mahmoud.ahmed",
"phone": "01098765432",
"status": "active"
}
]
}
{
"message": "Unauthenticated."
}
جلب الملف الشامل للمشترك: البيانات الشخصية، الاشتراك النشط وتفاصيل الباقة، الاستهلاك اللحظي واليومي، سجل الجلسة الحية، الماكات المقترنة، الفواتير غير المسددة، المديونيات، وصور العقد والبطاقة الشخصية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك الفريد |
@GET("subscribers/{id}")
suspend fun getSubscriberDetails(@Path("id") id: Int): Response<DetailedSubscriberResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"id": 105,
"name": "محمود أحمد حسن",
"username": "mahmoud.ahmed",
"phone": "01098765432",
"national_id": "29508120102554",
"address": "شارع الجمهورية - عمارة الأمل الدور الثالث",
"notes": "تم التوصيل على بورت 8 في سويتش الدور 3",
"avatar_url": "https://isp.freenet.net/storage/subscribers/105_photo.jpg",
"status": "active",
"is_active": true,
"online_status": true,
"active_session_type": "pppoe",
"balance": 25.0,
"total_unpaid_debt": 0.0,
"mac_limit": 1,
"simultaneous_sessions": 1,
"whatsapp_opt_in": true,
"whatsapp_status": "verified",
"is_dashboard_locked": false,
"active_subscription": {
"id": 892,
"service_plan_id": 1,
"plan_name": "باقة سوبر 30 ميجا",
"download_speed_kbps": 30720,
"upload_speed_kbps": 5120,
"starts_at": "2026-08-24 00:00:00",
"expires_at": "2026-09-23 23:59:59",
"total_quota_bytes": 268435456000,
"used_quota_bytes": 153008209920,
"remaining_quota_bytes": 115427246080
},
"active_session": {
"nas_ip": "192.168.10.1",
"framed_ip_address": "10.100.4.55",
"calling_station_id": "48:8F:5A:12:34:56",
"session_start": "2026-09-09 08:30:12",
"uptime_seconds": 21328,
"uploaded_formatted": "1.2 GB",
"downloaded_formatted": "8.4 GB"
},
"macs": [
{
"id": 44,
"mac_address": "48:8F:5A:12:34:56",
"created_at": "2026-08-01"
}
],
"admin": {
"id": 1,
"name": "المدير العام",
"phone": "01012345678"
}
}
{
"message": "المشترك غير موجود أو ليس لديك صلاحية الوصول إليه."
}
تسجيل مشترك جديد في النظام: توليد حساب الراديوس (radcheck/radreply)، تعيين الباقة، خصم تكلفة الاشتراك من رصيد المدير/الموزع داخل معاملة مالية آمنة (DB::transaction & lockForUpdate)، وتحديد نوع الاتصال والماك أدرس.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| username | body | string | إلزامي | اسم مستخدم الاتصال الفريد (حروف إنجليزية وأرقام ونقاط) |
| password | body | string | إلزامي | كلمة مرور اتصال الراديوس |
| name | body | string | إلزامي | الاسم الكامل للمشترك بالعربية |
| phone | body | string | اختياري | رقم الهاتف المحمول للتنبيهات وإشعارات الواتساب |
| national_id | body | string | اختياري | الرقم القومي / الهوية (14 رقم) |
| address | body | string | اختياري | العنوان التفصيلي ومكان التركيب |
| service_plan_id | body | integer | إلزامي | معرف باقة الخدمة المختارة |
| admin_id | body | integer | اختياري | معرف المشرف التابع له (الافتراضي: المدير المنشئ) |
| connection_type | body | string | اختياري | نوع الاتصال: pppoe (الافتراضي) أو hotspot أو static |
| mac_address | body | string | اختياري | الماك أدرس لتقييد المشترك بجهاز محدد |
| static_ip | body | string | اختياري | عنوان IP ثابت اختياري |
| initial_balance | body | number | اختياري | رصيد افتتاحي يُضاف لمحفظة المشترك |
| notes | body | string | اختياري | ملاحظات إدارية وفنية |
{
"username": "karim.tarek",
"password": "KarimPass2026@",
"name": "كريم طارق عبد الرحمن",
"phone": "01234567890",
"national_id": "29805140101993",
"address": "شارع النصر - برج الياسمين",
"service_plan_id": 1,
"connection_type": "pppoe",
"initial_balance": 0.0,
"notes": "تم التركيب عبر راوتر تي بي لينك جديد"
}
@POST("subscribers")
suspend fun createSubscriber(@Body data: RequestBody): Response<Subscriber>
// In Repository
val json = JSONObject().apply {
put("username", "karim.tarek")
put("password", "KarimPass2026@")
put("name", "كريم طارق عبد الرحمن")
put("service_plan_id", 1)
put("phone", "01234567890")
}.toString()
val body = json.toRequestBody("application/json".toMediaTypeOrNull())
val res = apiService.createSubscriber(body)
curl -X POST "https://isp.freenet.net/api/manager/subscribers" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"username":"karim.tarek","password":"Pass123@","name":"كريم طارق","service_plan_id":1}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"username": "karim.tarek", "password": "KarimPass2026@", "name": "كريم طارق عبد الرحمن", "phone": "01234567890", "national_id": "29805140101993", "address": "شارع النصر - برج الياسمين", "service_plan_id": 1, "connection_type": "pppoe", "initial_balance": 0.0, "notes": "تم التركيب عبر راوتر تي بي لينك جديد"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"username": "karim.tarek", "password": "KarimPass2026@", "name": "كريم طارق عبد الرحمن", "phone": "01234567890", "national_id": "29805140101993", "address": "شارع النصر - برج الياسمين", "service_plan_id": 1, "connection_type": "pppoe", "initial_balance": 0.0, "notes": "تم التركيب عبر راوتر تي بي لينك جديد"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"username": "karim.tarek", "password": "KarimPass2026@", "name": "كريم طارق عبد الرحمن", "phone": "01234567890", "national_id": "29805140101993", "address": "شارع النصر - برج الياسمين", "service_plan_id": 1, "connection_type": "pppoe", "initial_balance": 0.0, "notes": "تم التركيب عبر راوتر تي بي لينك جديد"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إنشاء حساب المشترك وتفعيل اشتراكه بنجاح",
"data": {
"id": 106,
"username": "karim.tarek",
"name": "كريم طارق عبد الرحمن",
"status": "active",
"expires_at": "2026-10-09 23:59:59"
}
}
{
"message": "The given data was invalid.",
"errors": {
"username": [
"اسم المستخدم هذا مسجل بالفعل لمشترك آخر."
],
"balance": [
"رصيد المشرف غير كافٍ لتغطية تكلفة تفعيل هذه الباقة."
]
}
}
تحديث بيانات المشترك الشخصية، العنوان، رقم الهاتف، وتعديل كلمة المرور أو الماك أدرس دون المساس بسجل الاشتراك التاريخي.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| name | body | string | اختياري | الاسم الكامل للمشترك |
| phone | body | string | اختياري | رقم الهاتف المحمول |
| address | body | string | اختياري | العنوان |
| password | body | string | اختياري | كلمة مرور جديدة للاتصال في حال الرغبة بتغييرها |
| notes | body | string | اختياري | ملاحظات إدارية |
{
"name": "محمود أحمد حسن الشريف",
"phone": "01098765432",
"address": "شارع الجمهورية - عمارة الأمل الدور الرابع (شقة معدلة)",
"notes": "تم نقل الروزيتا لشقة الدور الرابع"
}
@PUT("subscribers/{id}")
suspend fun updateSubscriber(
@Path("id") id: Int,
@Body data: RequestBody
): Response<Subscriber>
curl -X PUT "https://isp.freenet.net/api/manager/subscribers/105" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"name": "محمود أحمد حسن الشريف"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"name": "محمود أحمد حسن الشريف", "phone": "01098765432", "address": "شارع الجمهورية - عمارة الأمل الدور الرابع (شقة معدلة)", "notes": "تم نقل الروزيتا لشقة الدور الرابع"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}');
final response = await http.put(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"name": "محمود أحمد حسن الشريف", "phone": "01098765432", "address": "شارع الجمهورية - عمارة الأمل الدور الرابع (شقة معدلة)", "notes": "تم نقل الروزيتا لشقة الدور الرابع"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('PUT', 'api/manager/subscribers/{id}', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"name": "محمود أحمد حسن الشريف", "phone": "01098765432", "address": "شارع الجمهورية - عمارة الأمل الدور الرابع (شقة معدلة)", "notes": "تم نقل الروزيتا لشقة الدور الرابع"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث بيانات المشترك بنجاح",
"subscriber": {
"id": 105,
"name": "محمود أحمد حسن الشريف"
}
}
{
"message": "The given data was invalid."
}
حذف حساب المشترك وسجلاته، فصل جلسته النشطة فوراً من راوتر المايكروتك عبر الـ CoA، وحذف بياناته من جداول FreeRADIUS (radcheck, radreply).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك المراد حذفه |
@DELETE("subscribers/{id}")
suspend fun deleteSubscriber(@Path("id") id: Int): Response<Map<String, Any>>
curl -X DELETE "https://isp.freenet.net/api/manager/subscribers/105" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}');
final response = await http.delete(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('DELETE', 'api/manager/subscribers/{id}', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم حذف المشترك وإلغاء كافة قيوده وجلساته بنجاح"
}
{
"message": "ليس لديك صلاحية لحذف المشتركين."
}
رفع صورة للمشترك أو صورة بطاقة الرقم القومي أو العقد عبر Multipart Form Data وحفظها في التخزين السحابي الآمن مع ربطها بملف المشترك.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| photo | body (multipart) | file (jpeg, png, webp) | إلزامي | ملف الصورة المرفقة بحد أقصى 5 ميجابايت |
multipart/form-data: photo=@national_id.jpg
@Multipart
@POST("subscribers/{id}/photo")
suspend fun uploadSubscriberPhoto(
@Path("id") id: Int,
@Part photo: MultipartBody.Part
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/photo" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-F "photo=@/path/to/contract.jpg"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/photo`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/photo');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/photo', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم رفع وتحديث صورة المشترك بنجاح",
"photo_url": "https://isp.freenet.net/storage/subscribers/105_photo_xyz.jpg"
}
{
"message": "The photo field must be an image."
}
حذف الصورة المرفقة للمشترك وحذف الملف الفيزيائي من السيرفر وإعادة الصورة للافتراضي.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@DELETE("subscribers/{id}/photo")
suspend fun deleteSubscriberPhoto(@Path("id") id: Int): Response<Map<String, Any>>
curl -X DELETE "https://isp.freenet.net/api/manager/subscribers/105/photo" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/photo`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/photo');
final response = await http.delete(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('DELETE', 'api/manager/subscribers/{id}/photo', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم حذف صورة المشترك بنجاح"
}
{
"message": "لا توجد صورة مسجلة لهذا المشترك."
}
حذف مجموعة من المشتركين دفعة واحدة عبر تمرير مصفوفة المعرفات IDs مع فصل جلساتهم ومسحهم من جداول الراديوس.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| ids | body | array of integers | إلزامي | مصفوفة معرفات المشتركين المراد حذفهم |
{
"ids": [
105,
106,
107
]
}
@POST("subscribers/bulk-delete")
suspend fun bulkDeleteSubscribers(@Body data: Map<String, List<Int>>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/bulk-delete" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"ids": [105, 106, 107]}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/bulk-delete`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"ids": [105, 106, 107]})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/bulk-delete');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"ids": [105, 106, 107]}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/bulk-delete', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"ids": [105, 106, 107]}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم حذف 3 مشتركين بنجاح",
"deleted_count": 3
}
{
"message": "حقل المعرفات ids مطلوب."
}
تغيير حالة مجموعة من المشتركين (تفعيل أو تعطيل) دفعة واحدة مع فصل جلسات النشطين المعطلين فورياً.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| ids | body | array of integers | إلزامي | مصفوفة معرفات المشتركين |
| status | body | string | إلزامي | الحالة المستهدفة: active أو inactive |
{
"ids": [
105,
108
],
"status": "inactive"
}
@POST("subscribers/bulk-toggle-status")
suspend fun bulkToggleStatus(@Body data: Map<String, Any>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/bulk-toggle-status" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"ids": [105, 108], "status": "inactive"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/bulk-toggle-status`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"ids": [105, 108], "status": "inactive"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/bulk-toggle-status');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"ids": [105, 108], "status": "inactive"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/bulk-toggle-status', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"ids": [105, 108], "status": "inactive"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث حالة 2 مشترك بنجاح"
}
{
"message": "The given data was invalid."
}
إعادة إسناد مجموعة من المشتركين ونقل تبعيتهم إلى مشرف أو موزع جديد وتحديث صلاحيات إدارتهم.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| ids | body | array of integers | إلزامي | مصفوفة معرفات المشتركين |
| admin_id | body | integer | إلزامي | معرف المشرف الجديد المراد النقل إليه |
{
"ids": [
105,
106
],
"admin_id": 2
}
@POST("subscribers/bulk-transfer-admin")
suspend fun bulkTransferAdmin(@Body data: Map<String, Any>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/bulk-transfer-admin" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"ids": [105, 106], "admin_id": 2}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/bulk-transfer-admin`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"ids": [105, 106], "admin_id": 2})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/bulk-transfer-admin');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"ids": [105, 106], "admin_id": 2}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/bulk-transfer-admin', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"ids": [105, 106], "admin_id": 2}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم نقل 2 مشتركين إلى المشرف الجديد بنجاح"
}
{
"message": "المشرف المستهدف غير موجود."
}
نقل مجموعة من المشتركين إلى برج أو مجموعة شبكية جديدة (Group Transfer).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| ids | body | array of integers | إلزامي | مصفوفة معرفات المشتركين |
| group_id | body | integer | إلزامي | معرف المجموعة أو البرج الجديد |
{
"ids": [
105,
106
],
"group_id": 3
}
@POST("subscribers/bulk-transfer-group")
suspend fun bulkTransferGroup(@Body data: Map<String, Any>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/bulk-transfer-group" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"ids": [105, 106], "group_id": 3}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/bulk-transfer-group`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"ids": [105, 106], "group_id": 3})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/bulk-transfer-group');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"ids": [105, 106], "group_id": 3}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/bulk-transfer-group', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"ids": [105, 106], "group_id": 3}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم نقل المشتركين للمجموعة المحددة بنجاح"
}
{
"message": "The given data was invalid."
}
استعراض سجل الاتصالات والجلسات التاريخية للمشترك من جدول radacct / SubscriberSessions: وقت البدء، وقت الانتهاء، المدة، الآيبي المسحوب، الماك، وسبب انتهاء الجلسة (User-Request, Lost-Carrier, Admin-Reset).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| page | query | integer | اختياري | رقم الصفحة |
| start_date | query | string (YYYY-MM-DD) | اختياري | تاريخ البداية |
| end_date | query | string (YYYY-MM-DD) | اختياري | تاريخ النهاية |
@GET("subscribers/{id}/sessions")
suspend fun getSubscriberSessions(
@Path("id") id: Int,
@Query("page") page: Int = 1,
@Query("start_date") startDate: String? = null,
@Query("end_date") endDate: String? = null
): Response<SessionListResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/sessions" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/sessions`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/sessions');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/sessions', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 9012,
"framed_ip_address": "10.100.4.55",
"calling_station_id": "48:8F:5A:12:34:56",
"session_start": "2026-09-08 10:14:02",
"session_end": "2026-09-08 23:45:10",
"duration_formatted": "13 hours 31 mins",
"uploaded_formatted": "2.4 GB",
"downloaded_formatted": "14.8 GB",
"total_formatted": "17.2 GB",
"terminate_cause": "User-Request"
}
]
}
{
"message": "Unauthenticated."
}
جلب بيانات استهلاك الباندويث اليومية (الرفع والتحميل والإجمالي بالبايت) للمشترك على مدار آخر 30 يوماً لرسم المنحنيات البيانية في تطبيق الهاتف والداشبورد.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| start_date | query | string | اختياري | تاريخ البداية |
| end_date | query | string | اختياري | تاريخ النهاية |
@GET("subscribers/{id}/usage-history")
suspend fun getSubscriberUsageHistory(
@Path("id") id: Int,
@Query("start_date") startDate: String? = null,
@Query("end_date") endDate: String? = null
): Response<List<DailyUsageHistoryItem>>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/usage-history" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/usage-history`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/usage-history');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/usage-history', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
[
{
"date": "2026-09-08",
"download_bytes": 15899345920,
"upload_bytes": 2576980377,
"total_bytes": 18476326297,
"download_formatted": "14.8 GB",
"upload_formatted": "2.4 GB",
"total_formatted": "17.2 GB"
},
{
"date": "2026-09-07",
"download_bytes": 11200345920,
"upload_bytes": 1576980377,
"total_bytes": 12777326297,
"download_formatted": "10.4 GB",
"upload_formatted": "1.5 GB",
"total_formatted": "11.9 GB"
}
]
{
"message": "Unauthenticated."
}
كافة العمليات الفورية والتفاعلية على خط المشترك: فصل الجلسات اللحظي عبر حزم MikroTik CoA Disconnect، تفعيل/تعطيل، إيقاف النت المؤقت، شحن وسحب الرصيد، تسجيل المديونيات، الدفع الذكي، تجديد وتغيير الباقة، زيادة الجيجات وتعديل الصلاحية، السرعات المؤقتة، قفل ومسح الماك، الرقابة العائلية، والمستخدمين الفرعيين وقيود الراديوس.
إرسال حزمة Disconnect-Request فورية إلى راوتر المايكروتك أو سيرفر الراديوس لطرد جلسة المشترك النشطة حالياً وقطع اتصاله بالإنترنت في أجزاء من الثانية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/disconnect")
suspend fun disconnectSubscriber(@Path("id") id: Int): Response<Unit>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/disconnect" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/disconnect`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/disconnect');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/disconnect', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إرسال أمر فصل الجلسة إلى الراوتر بنجاح"
}
{
"message": "المشترك غير متصل حالياً بأي جلسة نشطة."
}
تبديل حالة المشترك بين نشط ومعطل. في حال التعطيل، يتم فصل جلسته النشطة فورياً من الراوتر ومنعه من تسجيل الدخول مجدداً حتى يتم تفعيله.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/toggle-status")
suspend fun toggleSubscriberStatus(@Path("id") id: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/toggle-status" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/toggle-status`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/toggle-status');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/toggle-status', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"is_active": false,
"message": "تم تعطيل حساب المشترك وفصل اتصاله بنجاح"
}
{
"message": "ليس لديك صلاحية لتعديل حالة المشترك."
}
إيقاف خدمة الإنترنت مؤقتاً عن المشترك (تحويله لبروفايل الحظر/صفحة الهبوط) دون المساس بفترة اشتراكه أو تاريخ انتهائه، ثم استئناف الخدمة في أي وقت.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/toggle-internet")
suspend fun toggleInternet(@Path("id") id: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/toggle-internet" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/toggle-internet`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/toggle-internet');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/toggle-internet', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"is_internet_paused": true,
"message": "تم إيقاف الإنترنت مؤقتاً عن المشترك بنجاح"
}
{
"message": "Unauthenticated."
}
إيداع مبلغ مالي في محفظة المشترك عبر WalletService داخل معاملة بنكية آمنة مع قفل القيد (DB::transaction & lockForUpdate) وخصم المبلغ المقابل من رصيد المشرف وتسجيل إيصال إيداع.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| amount | body | number | إلزامي | المبلغ المراد إيداعه (أكبر من 0) |
| description | body | string | اختياري | بيان أو سبب الإيداع |
{
"amount": 200.0,
"description": "شحن نقدي بمقر السنترال"
}
@POST("subscribers/{id}/balance/add")
suspend fun addBalance(
@Path("id") id: Int,
@Body data: Map<String, Any>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/balance/add" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"amount": 200.00, "description": "شحن كاش"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/balance/add`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"amount": 200.0, "description": "شحن نقدي بمقر السنترال"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/balance/add');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"amount": 200.0, "description": "شحن نقدي بمقر السنترال"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/balance/add', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"amount": 200.0, "description": "شحن نقدي بمقر السنترال"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"new_balance": 225.0,
"amount_added": 200.0,
"admin_balance": 15250.0,
"message": "تم إيداع مبلغ 200 ج.م في محفظة المشترك بنجاح"
}
{
"message": "رصيد المشرف غير كافٍ لتنفيذ هذه العملية."
}
سحب مبلغ مالي من رصيد المشترك وإرجاعه إلى رصيد المشرف مع التحقق من كفاية رصيد العميل وتسجيل القيد المحاسبي.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| amount | body | number | إلزامي | المبلغ المراد سحبه |
| description | body | string | اختياري | بيان أو سبب السحب |
{
"amount": 50.0,
"description": "استرجاع رصيد متبقي"
}
@POST("subscribers/{id}/balance/withdraw")
suspend fun withdrawBalance(
@Path("id") id: Int,
@Body data: Map<String, Any>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/balance/withdraw" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"amount": 50.00}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/balance/withdraw`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"amount": 50.0, "description": "استرجاع رصيد متبقي"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/balance/withdraw');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"amount": 50.0, "description": "استرجاع رصيد متبقي"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/balance/withdraw', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"amount": 50.0, "description": "استرجاع رصيد متبقي"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"new_balance": 175.0,
"message": "تم سحب مبلغ 50 ج.م من رصيد المشترك بنجاح"
}
{
"message": "رصيد المشترك غير كافٍ لإتمام عملية السحب."
}
تسجيل فاتورة أو قيد دين على المشترك مع تحديد القيمة والبيان وتاريخ الاستحقاق لتظهر في كشف حساب العميل والفواتير المستحقة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| amount | body | number | إلزامي | مبلغ المديونية |
| description | body | string | اختياري | سبب تسجيل الدين (مثال: باقي تجديد باقة الشهر) |
| due_date | body | string (YYYY-MM-DD) | اختياري | تاريخ الاستحقاق |
{
"amount": 100.0,
"description": "باقي اشتراك شهر سبتمبر",
"due_date": "2026-09-15"
}
@POST("subscribers/{id}/register-debt")
suspend fun registerDebt(
@Path("id") id: Int,
@Body data: Map<String, Any?>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/register-debt" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"amount": 100.00, "description": "آجل اشتراك"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/register-debt`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"amount": 100.0, "description": "باقي اشتراك شهر سبتمبر", "due_date": "2026-09-15"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/register-debt');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"amount": 100.0, "description": "باقي اشتراك شهر سبتمبر", "due_date": "2026-09-15"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/register-debt', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"amount": 100.0, "description": "باقي اشتراك شهر سبتمبر", "due_date": "2026-09-15"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"total_unpaid_debt": 100.0,
"invoice_id": 4012,
"message": "تم تسجيل المديونية وإنشاء فاتورة مستحقة بنجاح"
}
{
"message": "المبلغ يجب أن يكون أكبر من الصفر."
}
نظام تحصيل ذكي يقوم بفحص رصيد محفظة العميل وسداد الفاتورة تلقائياً من الرصيد المتوفر، وفي حال عدم كفاية الرصيد يتم استهلاك المتوفر وتسجيل المبلغ المتبقي كمديونية آمنة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| invoice_id | body | integer | إلزامي | معرف الفاتورة المراد سدادها |
| allow_partial | body | boolean | اختياري | السماح بالسداد الجزئي في حال نقص الرصيد (الافتراضي: true) |
{
"invoice_id": 4012,
"allow_partial": true
}
@POST("subscribers/{id}/smart-pay")
suspend fun smartPay(
@Path("id") id: Int,
@Body data: Map<String, Any>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/smart-pay" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"invoice_id": 4012}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/smart-pay`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"invoice_id": 4012, "allow_partial": true})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/smart-pay');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"invoice_id": 4012, "allow_partial": true}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/smart-pay', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"invoice_id": 4012, "allow_partial": true}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"paid_amount": 100.0,
"remaining_debt": 0.0,
"invoice_status": "paid",
"message": "تم سداد الفاتورة بنجاح عبر النظام الذكي"
}
{
"message": "الفاتورة غير موجودة."
}
تجديد اشتراك المشترك مع خيارات متقدمة: تحديد طريقة الدفع (كاش، محفظة المشترك، آجل/دين)، وتطبيق خصم مخصص (نسبة أو مبلغ ثابت)، وإمكانية إضافة أيام إضافية كهدية، وتحديث بيانات الراديوس فورياً وإرسال CoA لإعادة ضبط السرعة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| payment_method | body | string | اختياري | طريقة الدفع: cash (كاش للمدير), wallet (من رصيد المشترك), debt (آجل) |
| custom_discount | body | number | اختياري | قيمة الخصم المالي المطبق |
| extra_days | body | integer | اختياري | أيام إضافية تُضاف للصلاحية |
| notes | body | string | اختياري | ملاحظات عملية التجديد |
{
"payment_method": "cash",
"custom_discount": 20.0,
"extra_days": 2,
"notes": "تجديد اشتراك باقة سوبر كاش مع خصم العملاء المميزين"
}
// ApiService.kt
@POST("subscribers/{id}/renew")
suspend fun renewSubscriber(
@Path("id") id: Int,
@Body data: Map<String, Any?> = emptyMap()
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/renew" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"payment_method": "cash", "custom_discount": 20.00}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/renew`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"payment_method": "cash", "custom_discount": 20.0, "extra_days": 2, "notes": "تجديد اشتراك باقة سوبر كاش مع خصم العملاء المميزين"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/renew');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"payment_method": "cash", "custom_discount": 20.0, "extra_days": 2, "notes": "تجديد اشتراك باقة سوبر كاش مع خصم العملاء المميزين"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/renew', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"payment_method": "cash", "custom_discount": 20.0, "extra_days": 2, "notes": "تجديد اشتراك باقة سوبر كاش مع خصم العملاء المميزين"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تجديد اشتراك المشترك بنجاح",
"subscription": {
"id": 893,
"plan_name": "باقة سوبر 30 ميجا",
"price": 160.0,
"starts_at": "2026-09-09 14:30:00",
"expires_at": "2026-10-11 23:59:59",
"quota_gb": 250
},
"renewal_log_id": 512
}
{
"message": "رصيد المشرف غير كافٍ لتغطية تكلفة الجملة للباقة."
}
ترقية أو تخفيض باقة المشترك مع حساب فارق السعر تلقائياً بنظام الـ Prorated أو التحصيل الكامل، وتحديث سرعة المشترك لحظياً عبر MikroTik CoA مع خيار التنفيذ الفوري أو الجدولة لنهاية الفترة الحالية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| service_plan_id | body | integer | إلزامي | معرف الباقة الجديدة المراد الانتقال إليها |
| timing | body | string | اختياري | توقيت التنفيذ: immediate (فوري الآن) أو end_of_cycle (عند انتهاء الفترة الحالية) |
| calculation_method | body | string | اختياري | طريقة الحساب: prorated (حساب فرق الأيام) أو full_price (تحصيل كامل الباقة) |
| payment_method | body | string | اختياري | طريقة السداد: cash أو wallet أو debt |
{
"service_plan_id": 2,
"timing": "immediate",
"calculation_method": "prorated",
"payment_method": "cash"
}
@POST("subscribers/{id}/change-plan")
suspend fun changePlan(
@Path("id") id: Int,
@Body data: Map<String, Any>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/change-plan" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"service_plan_id": 2, "timing": "immediate"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/change-plan`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"service_plan_id": 2, "timing": "immediate", "calculation_method": "prorated", "payment_method": "cash"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/change-plan');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"service_plan_id": 2, "timing": "immediate", "calculation_method": "prorated", "payment_method": "cash"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/change-plan', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"service_plan_id": 2, "timing": "immediate", "calculation_method": "prorated", "payment_method": "cash"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم ترقية باقة المشترك وتحديث السرعة بنجاح عبر MikroTik CoA",
"new_plan_name": "باقة الترا 70 ميجا",
"price_difference": 70.0,
"expires_at": "2026-09-23 23:59:59"
}
{
"message": "الباقة المختارة غير متوافقة مع هذا المشترك."
}
إلغاء آخر عملية تجديد تمت بالخطأ للمشترك واسترداد الرصيد المخصوم من محفظة المشرف وإعادة تاريخ الانتهاء والكوتا إلى ما كانا عليه قبل التجديد بدقة متناهية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/reverse-renewal")
suspend fun reverseRenewal(
@Path("id") subscriberId: Int,
@Body data: Map<String, Any> = emptyMap()
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/reverse-renewal" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/reverse-renewal`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/reverse-renewal');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/reverse-renewal', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم التراجع عن عملية التجديد واسترجاع الرصيد وتاريخ الانتهاء بنجاح",
"refunded_amount": 160.0,
"previous_expires_at": "2026-09-09 14:00:00"
}
{
"message": "لا يمكن إلغاء التجديد؛ مرت أكثر من 24 ساعة على العملية أو تم استهلاك جزء كبير من الكوتا."
}
التحقق البرمجي المسبق مما إذا كانت الفاتورة أو عملية التجديد مؤهلة للإلغاء الآمن دون أخطاء محاسبية قبل تأكيد الإلغاء للمستخدم.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| invoiceId | path | integer | إلزامي | معرف الفاتورة |
@GET("subscribers/{id}/invoices/{invoiceId}/check-reversal")
suspend fun checkReversal(
@Path("id") subscriberId: Int,
@Path("invoiceId") invoiceId: Int
): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/invoices/4012/check-reversal" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/invoices/{invoiceId}/check-reversal`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/invoices/{invoiceId}/check-reversal');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/invoices/{invoiceId}/check-reversal', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"can_reverse": true,
"refund_amount": 180.0,
"reason": "العملية تمت اليوم ولم تتجاوز المدة المسموحة"
}
{
"message": "الفاتورة غير موجودة."
}
إضافة جيجابايت إضافية (Bonus Quota) للمشترك أو تعديل إجمالي وسعة الكوتا الحالية فورياً وتحديث عدادات الراديوس.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| quota_gb | body | number | إلزامي | عدد الجيجابايت المراد إضافتها أو ضبطها |
| mode | body | string | اختياري | الوضع: add (إضافة للكوتا الحالية) أو set (تعيين قيمة جديدة) |
{
"quota_gb": 50,
"mode": "add"
}
@POST("subscribers/{id}/quota")
suspend fun adjustQuota(
@Path("id") id: Int,
@Body data: Map<String, Any>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/quota" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"quota_gb": 50, "mode": "add"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/quota`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"quota_gb": 50, "mode": "add"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/quota');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"quota_gb": 50, "mode": "add"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/quota', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"quota_gb": 50, "mode": "add"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"new_total_quota_gb": 300,
"new_remaining_quota_gb": 157.5,
"message": "تمت إضافة 50 جيجابايت لاشتراك المشترك بنجاح"
}
{
"message": "The given data was invalid."
}
تمديد أو تقديم تاريخ انتهاء الاشتراك بعدد أيام محدد أو تحديد تاريخ ووقت انتهاء جديد بالكامل.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| days | body | integer | اختياري | عدد الأيام المراد إضافتها (أو طرحها بقيمة سالبة) |
| exact_date | body | string (YYYY-MM-DD HH:mm:ss) | اختياري | تاريخ محدد لانتهاء الاشتراك |
{
"days": 7
}
@POST("subscribers/{id}/expiry")
suspend fun adjustExpiry(
@Path("id") id: Int,
@Body data: Map<String, Any>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/expiry" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"days": 7}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/expiry`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"days": 7})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/expiry');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"days": 7}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/expiry', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"days": 7}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"new_expires_at": "2026-09-30 23:59:59",
"message": "تم تمديد فترة الاشتراك لمدة 7 أيام بنجاح"
}
{
"message": "يرجى تحديد عدد الأيام أو التاريخ المحدد."
}
تطبيق سرعة تحميل ورفع مخصصة للمشترك مع إرسال أمر MikroTik CoA فوري لتحديث سرعة الـ Queue دون فصل اتصال العميل، مع إمكانية تحديد مدة زمنية لعودة السرعة تلقائياً.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| download_speed_kbps | body | integer | إلزامي | سرعة التحميل بالكيلوبت (مثال 51200 لـ 50 ميجا) |
| upload_speed_kbps | body | integer | إلزامي | سرعة الرفع بالكيلوبت (مثال 10240 لـ 10 ميجا) |
| duration_hours | body | integer | اختياري | مدة تطبيق السرعة بالساعات (اختياري للسرعة المؤقتة) |
{
"download_speed_kbps": 51200,
"upload_speed_kbps": 10240,
"duration_hours": 24
}
@POST("subscribers/{id}/speed-limit")
suspend fun updateSpeedLimits(
@Path("id") id: Int,
@Body data: Map<String, Any?>
): Response<Unit>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/speed-limit" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"download_speed_kbps": 51200, "upload_speed_kbps": 10240}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/speed-limit`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"download_speed_kbps": 51200, "upload_speed_kbps": 10240, "duration_hours": 24})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/speed-limit');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"download_speed_kbps": 51200, "upload_speed_kbps": 10240, "duration_hours": 24}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/speed-limit', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"download_speed_kbps": 51200, "upload_speed_kbps": 10240, "duration_hours": 24}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تطبيق السرعة وإرسال حزم الـ CoA بنجاح إلى الراوتر"
}
{
"message": "فشل إرسال حزمة الـ CoA إلى الراوتر."
}
إلغاء أي سرعة استثنائية أو مؤقتة وإعادة فرض سرعة الباقة المسجلة في الاشتراك عبر الـ CoA فورياً.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/speed-limit/revoke")
suspend fun revokeTemporarySpeed(@Path("id") id: Int): Response<SimpleResponse>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/speed-limit/revoke" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/speed-limit/revoke`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/speed-limit/revoke');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/speed-limit/revoke', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إلغاء السرعة المؤقتة والعودة لسرعة الباقة بنجاح"
}
{
"message": "Unauthenticated."
}
تفعيل أو إلغاء ميزة قفل الحساب على الماك أدرس لجهاز المشترك لمنع مشاركة الحساب أو تشغيله من رواتر آخر.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/mac-lock")
suspend fun toggleMacLock(@Path("id") id: Int): Response<Unit>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/mac-lock" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/mac-lock`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/mac-lock');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/mac-lock', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"mac_lock_enabled": true,
"message": "تم تفعيل القفل على الماك أدرس بنجاح"
}
{
"message": "Unauthenticated."
}
مسح عنوان الماك المقيد بحساب العميل للسماح له بالاتصال بجهاز أو راوتر جديد، مع فصل أي جلسة عالقة قديمة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/reset-mac")
suspend fun resetMac(@Path("id") id: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/reset-mac" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/reset-mac`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/reset-mac');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/reset-mac', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم مسح الماك أدرس المقترن بنجاح وأصبح الحساب جاهزاً للاتصال بالراوتر الجديد"
}
{
"message": "Unauthenticated."
}
حذف عنوان ماك محدد من قائمة الأجهزة المقترنة بحساب المشترك عند السماح بعدة أجهزة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| macId | path | integer | إلزامي | معرف سجل الماك |
@DELETE("subscribers/{id}/macs/{macId}")
suspend fun deleteMac(@Path("id") id: Int, @Path("macId") macId: Int): Response<Unit>
curl -X DELETE "https://isp.freenet.net/api/manager/subscribers/105/macs/44" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/macs/{macId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/macs/{macId}');
final response = await http.delete(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('DELETE', 'api/manager/subscribers/{id}/macs/{macId}', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم حذف الماك المحدد بنجاح"
}
{
"message": "سجل الماك غير موجود."
}
تعديل خاصية Simultaneous-Use في الراديوس لتحديد عدد الأجهزة المسموح لها بالاتصال بالحساب في نفس اللحظة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| simultaneous_sessions | body | integer | إلزامي | العدد الأقصى للجلسات (مثال: 1 أو 2 أو 5) |
{
"simultaneous_sessions": 2
}
@POST("subscribers/{id}/sessions")
suspend fun updateSimultaneousSessions(@Path("id") id: Int, @Body data: Map<String, Any?>): Response<Unit>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/sessions" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"simultaneous_sessions": 2}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/sessions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"simultaneous_sessions": 2})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/sessions');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"simultaneous_sessions": 2}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/sessions', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"simultaneous_sessions": 2}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"simultaneous_sessions": 2,
"message": "تم تحديث حد الجلسات المتزامنة بنجاح"
}
{
"message": "القيمة يجب أن تكون 1 على الأقل."
}
تصفير عدادات الاستهلاك الشهري المسجلة في جداول الاشتراكات والراديوس ليعود الاستهلاك إلى 0 جيجابايت مع الحفاظ على فترة الاشتراك.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/usage/reset")
suspend fun resetSubscriberUsage(@Path("id") id: Int): Response<Unit>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/usage/reset" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/usage/reset`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/usage/reset');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/usage/reset', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تصفير استهلاك المشترك بنجاح"
}
{
"message": "Unauthenticated."
}
تصفير استهلاك اليوم الحالي لفك خنق السرعة الناتج عن تجاوز الحد اليومي للـ Fair Usage Policy فورياً وإرسال CoA لإعادة السرعة القصوى.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/usage/reset-daily")
suspend fun resetDailyUsage(@Path("id") id: Int): Response<Unit>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/usage/reset-daily" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/usage/reset-daily`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/usage/reset-daily');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/usage/reset-daily', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تصفير الاستهلاك اليومي بنجاح واستعادة السرعة الكاملة"
}
{
"message": "Unauthenticated."
}
إدخال كود كارت شحن وشحنه مباشرة لحساب المشترك لتجديد باقته أو إضافة رصيد أو شحن باقة إضافية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| code | body | string | إلزامي | كود كارت الشحن (PIN Code) |
{
"code": "FREE-9874-2145-6632"
}
@POST("subscribers/{id}/voucher/redeem")
suspend fun redeemVoucher(
@Path("id") id: Int,
@Body data: Map<String, Any>
): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/voucher/redeem" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"code": "FREE-9874-2145-6632"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/voucher/redeem`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"code": "FREE-9874-2145-6632"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/voucher/redeem');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"code": "FREE-9874-2145-6632"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/voucher/redeem', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"code": "FREE-9874-2145-6632"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم شحن الكارت وتجديد الاشتراك بنجاح",
"plan_name": "باقة سوبر 30 ميجا",
"new_expires_at": "2026-10-09 23:59:59"
}
{
"message": "كود الكارت غير صالح أو تم استخدامه مسبقاً."
}
استعراض باقات الجيجات الإضافية وباقات السلف والخدمات التكميلية المتوافقة مع باقة هذا المشترك لإمكانية إضافتها.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| type | query | string | اختياري | نوع الخدمة: addon, loan, speed_boost |
@GET("subscribers/{id}/services")
suspend fun getAvailableServices(@Path("id") id: Int, @Query("type") type: String): Response<AdditionalPackageListResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/services?type=addon" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/services`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/services');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/services', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"services": [
{
"id": 10,
"name": "باقة 20 جيجا إضافية",
"price": 30.0,
"quota_gb": 20
},
{
"id": 11,
"name": "باقة 50 جيجا إضافية",
"price": 60.0,
"quota_gb": 50
},
{
"id": 12,
"name": "سلفني 5 جيجا (صالحة 48 ساعة)",
"price": 10.0,
"quota_gb": 5
}
]
}
{
"message": "Unauthenticated."
}
شراء وإضافة باقة جيجات إضافية أو تفعيل خدمة سلفة للمشترك مع خصم السعر وتحديث الكوتا الحالية فورياً.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| service_id | body | integer | إلزامي | معرف الخدمة أو الباقة الإضافية |
| payment_method | body | string | اختياري | طريقة الدفع: wallet, cash, debt |
{
"service_id": 10,
"payment_method": "cash"
}
@POST("subscribers/{id}/services")
suspend fun assignService(@Path("id") id: Int, @Body data: Map<String, Any>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/services" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"service_id": 10, "payment_method": "cash"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/services`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"service_id": 10, "payment_method": "cash"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/services');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"service_id": 10, "payment_method": "cash"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/services', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"service_id": 10, "payment_method": "cash"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تفعيل باقة 20 جيجا إضافية للمشترك بنجاح",
"new_remaining_quota": "127.5 GB"
}
{
"message": "الرصيد غير كافٍ لتفعيل هذه الباقة الإضافية."
}
في حال وجود اشتراك أو باقة مجدولة للبدء عند انتهاء الفترة الحالية، تتيح هذه الدالة تفعيلها فوراً واستبدال الفترة الحالية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/scheduled/activate")
suspend fun activateScheduledSubscription(@Path("id") id: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/scheduled/activate" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/scheduled/activate`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/scheduled/activate');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/scheduled/activate', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تفعيل الاشتراك المجدول فورياً وتحديث صلاحية العميل"
}
{
"message": "لا يوجد اشتراك مجدول قيد الانتظار لهذا المشترك."
}
إلغاء الاشتراك المجدول قيد الانتظار واسترداد قيمته المدفوعة لمحفظة المشرف أو المشترك بأمان.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@DELETE("subscribers/{id}/scheduled")
suspend fun cancelScheduledSubscription(@Path("id") id: Int): Response<Map<String, Any>>
curl -X DELETE "https://isp.freenet.net/api/manager/subscribers/105/scheduled" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/scheduled`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/scheduled');
final response = await http.delete(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('DELETE', 'api/manager/subscribers/{id}/scheduled', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إلغاء الاشتراك المجدول واسترداد الرصيد بنجاح"
}
{
"message": "لا يوجد اشتراك مجدول."
}
استعلام جدول ساعات عمل الإنترنت المخصص للمشترك (ساعات السماح وساعات الحظر التلقائي لكل يوم من أيام الأسبوع).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@GET("subscribers/{id}/internet/schedule")
suspend fun getInternetSchedule(@Path("id") id: Int): Response<InternetScheduleResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/internet/schedule" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/internet/schedule`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/internet/schedule');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/internet/schedule', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"is_schedule_enabled": true,
"schedule": {
"saturday": {
"enabled": true,
"allow_from": "08:00",
"allow_to": "23:00"
},
"sunday": {
"enabled": true,
"allow_from": "08:00",
"allow_to": "22:00"
}
}
}
{
"message": "Unauthenticated."
}
حفظ وضبط جدول مواعيد إيقاف وتشغيل النت الأسبوعي الخاص بالمشترك.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| is_enabled | body | boolean | إلزامي | تفعيل أو تعطيل الجدولة |
| schedule | body | object | إلزامي | كائن الجدولة الأسبوعية |
{
"is_enabled": true,
"schedule": {
"all_days": {
"allow_from": "08:00",
"allow_to": "23:00"
}
}
}
@POST("subscribers/{id}/internet/schedule")
suspend fun updateInternetSchedule(@Path("id") id: Int, @Body payload: Map<String, Any>): Response<ResponseBody>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/internet/schedule" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"is_enabled": true, "schedule": {}}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/internet/schedule`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"is_enabled": true, "schedule": {"all_days": {"allow_from": "08:00", "allow_to": "23:00"}}})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/internet/schedule');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"is_enabled": true, "schedule": {"all_days": {"allow_from": "08:00", "allow_to": "23:00"}}}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/internet/schedule', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"is_enabled": true, "schedule": {"all_days": {"allow_from": "08:00", "allow_to": "23:00"}}}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث جدول الرقابة العائلية بنجاح"
}
{
"message": "The given data was invalid."
}
إعادة تعيين أو توليد رمز دخول سريع جديد (4 أرقام) لبوابة المشترك الذاتية وتطبيق الهاتف.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@POST("subscribers/{id}/reset-pin")
suspend fun resetAccessPin(@Path("id") id: Int): Response<SimpleResponse>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/reset-pin" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/reset-pin`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/reset-pin');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/reset-pin', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"new_pin": "4891",
"message": "تم إنشاء رمز PIN جديد للمشترك بنجاح"
}
{
"message": "Unauthenticated."
}
تعديل بيانات الدخول الخاصة بالراديوس (Username & Password) وتحديثها فورياً في جداول radcheck وفصل أي جلسة مفتوحة بالبيانات القديمة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| username | body | string | اختياري | اسم مستخدم جديد فريد |
| password | body | string | اختياري | كلمة مرور جديدة |
{
"username": "mahmoud.new",
"password": "NewSecret2026@"
}
@POST("subscribers/{id}/credentials")
suspend fun updateCredentials(@Path("id") id: Int, @Body payload: Map<String, Any?>): Response<SimpleResponse>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/credentials" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"password": "NewSecret2026@"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/credentials`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"username": "mahmoud.new", "password": "NewSecret2026@"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/credentials');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"username": "mahmoud.new", "password": "NewSecret2026@"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/credentials', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"username": "mahmoud.new", "password": "NewSecret2026@"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث بيانات تسجيل الدخول وتحديث سجلات الراديوس بنجاح"
}
{
"message": "اسم المستخدم هذا مسجل بالفعل لمشترك آخر."
}
استعراض حسابات المستخدمين الفرعيين (أفراد الأسرة أو الأجهزة المستقلة) التابعة لاشتراك العميل والتي تشارك نفس الباقة بحسابات دخول مستقلة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك الرئيسي |
@GET("subscribers/{id}/sub-users")
suspend fun getSubUsers(@Path("id") subscriberId: Int): Response<SubUsersResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/sub-users" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/sub-users`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/sub-users');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/sub-users', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"allow_sub_users": true,
"max_sub_users": 5,
"data": [
{
"id": 12,
"username": "mahmoud.ahmed_sub1",
"name": "هاتف أحمد (الابن)",
"is_active": true,
"online_status": true,
"quota_limit_gb": 30,
"used_quota_gb": 18.4
}
]
}
{
"message": "Unauthenticated."
}
إنشاء حساب دخول مستقل لمستخدم فرعي يشارك كوتا الحساب الرئيسي مع إمكانية تحديد سقف كوتا خاص به (Quota Cap).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك الرئيسي |
| username_suffix | body | string | إلزامي | اللاحقة المضافة لاسم المستخدم |
| password | body | string | إلزامي | كلمة مرور المستخدم الفرعي |
| name | body | string | إلزامي | اسم صاحب الجهاز / المستخدم |
| quota_limit_gb | body | number | اختياري | الحد الأقصى للكوتا المسموحة له بالجيجابايت |
{
"username_suffix": "child1",
"password": "ChildPass123@",
"name": "لابتوب سارة",
"quota_limit_gb": 50
}
@POST("subscribers/{id}/sub-users")
suspend fun createSubUser(@Path("id") subscriberId: Int, @Body body: Map<String, Any?>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/sub-users" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"username_suffix": "child1", "password": "Pass", "name": "لابتوب سارة"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/sub-users`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"username_suffix": "child1", "password": "ChildPass123@", "name": "لابتوب سارة", "quota_limit_gb": 50})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/sub-users');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"username_suffix": "child1", "password": "ChildPass123@", "name": "لابتوب سارة", "quota_limit_gb": 50}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/sub-users', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"username_suffix": "child1", "password": "ChildPass123@", "name": "لابتوب سارة", "quota_limit_gb": 50}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إنشاء المستخدم الفرعي بنجاح",
"sub_user": {
"id": 13,
"username": "mahmoud.ahmed_child1",
"name": "لابتوب سارة"
}
}
{
"message": "تم الوصول للحد الأقصى لعدد المستخدمين الفرعيين المسموح به."
}
إيقاف أو استئناف خدمة الإنترنت لمستخدم فرعي محدد دون التأثير على باقي أجهزة الحساب.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك الرئيسي |
| subUserId | path | integer | إلزامي | معرف المستخدم الفرعي |
@POST("subscribers/{id}/sub-users/{subUserId}/toggle-status")
suspend fun toggleSubUserStatus(@Path("id") subscriberId: Int, @Path("subUserId") subUserId: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/sub-users/12/toggle-status" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/sub-users/{subUserId}/toggle-status`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/sub-users/{subUserId}/toggle-status');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/sub-users/{subUserId}/toggle-status', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث حالة المستخدم الفرعي بنجاح"
}
{
"message": "المستخدم الفرعي غير موجود."
}
فصل اتصال المستخدم الفرعي المحدد فقط من الراوتر دون قطع باقي جلسات المشترك.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك الرئيسي |
| subUserId | path | integer | إلزامي | معرف المستخدم الفرعي |
@POST("subscribers/{id}/sub-users/{subUserId}/disconnect")
suspend fun disconnectSubUser(@Path("id") subscriberId: Int, @Path("subUserId") subUserId: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/sub-users/12/disconnect" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/sub-users/{subUserId}/disconnect`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/sub-users/{subUserId}/disconnect');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/sub-users/{subUserId}/disconnect', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إرسال أمر فصل الجلسة للمستخدم الفرعي بنجاح"
}
{
"message": "Unauthenticated."
}
حذف حساب المستخدم الفرعي وإلغاء قيوده من سيرفر الراديوس.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك الرئيسي |
| subUserId | path | integer | إلزامي | معرف المستخدم الفرعي |
@DELETE("subscribers/{id}/sub-users/{subUserId}")
suspend fun deleteSubUser(@Path("id") subscriberId: Int, @Path("subUserId") subUserId: Int): Response<Map<String, Any>>
curl -X DELETE "https://isp.freenet.net/api/manager/subscribers/105/sub-users/12" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/sub-users/{subUserId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/sub-users/{subUserId}');
final response = await http.delete(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('DELETE', 'api/manager/subscribers/{id}/sub-users/{subUserId}', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم حذف المستخدم الفرعي بنجاح"
}
{
"message": "المستخدم الفرعي غير موجود."
}
استعلام قائمة راوترات وسيرفرات الـ NAS المسموح للمشترك بالاتصال عبرها حصراً لمنع تشغيل الحساب خارج نطاق برجه الجغرافي.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
@GET("subscribers/{id}/nas-restriction")
suspend fun getNasRestriction(@Path("id") subscriberId: Int): Response<NasRestrictionResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/nas-restriction" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/nas-restriction`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/nas-restriction');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/nas-restriction', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"is_restricted": true,
"allowed_nas_ids": [
1,
2
],
"allowed_nas_names": [
"Core-Downtown",
"Tower-East"
]
}
{
"message": "Unauthenticated."
}
تحديث وحفظ قائمة راوترات الـ NAS المسموح للعميل بتسجيل الدخول منها في قاعدة بيانات الراديوس (radcheck Nas-IP-Address).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| is_restricted | body | boolean | إلزامي | تفعيل القيد الجغرافي أو إلغاؤه |
| nas_ids | body | array of integers | اختياري | مصفوفة معرفات راوترات الـ NAS المسموحة |
{
"is_restricted": true,
"nas_ids": [
1
]
}
@POST("subscribers/{id}/nas-restriction")
suspend fun updateNasRestriction(@Path("id") subscriberId: Int, @Body body: Map<String, Any?>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/subscribers/105/nas-restriction" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"is_restricted": true, "nas_ids": [1]}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/nas-restriction`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"is_restricted": true, "nas_ids": [1]})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/nas-restriction');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"is_restricted": true, "nas_ids": [1]}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/subscribers/{id}/nas-restriction', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"is_restricted": true, "nas_ids": [1]}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث قيود سيرفرات الراديوس للمشترك بنجاح"
}
{
"message": "The given data was invalid."
}
استعراض سجلات كافة عمليات التجديد وتغيير الباقات في النظام مع تفاصيل المبالغ المخصومة والمشرف المنفذ، وإمكانية التراجع عن أي عملية وإلغائها واسترداد الرصيد.
استعراض جميع عمليات التجديد وتغيير الباقات التي تمت في الشبكة مع الفلترة حسب نوع العملية (renewal, plan_change)، أو المشرف، أو الباقة، أو حالة السداد، وتاريخ البداية والنهاية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة |
| per_page | query | integer | اختياري | عدد السجلات (الافتراضي: 20) |
| search | query | string | اختياري | البحث باسم المشترك أو اسم المستخدم أو المشرف |
| action_type | query | string | اختياري | نوع العملية: renewal أو plan_change |
| service_plan_id | query | integer | اختياري | معرف الباقة |
| payment_status | query | string | اختياري | حالة السداد: paid, unpaid, debt |
| date_from | query | string (YYYY-MM-DD) | اختياري | من تاريخ |
| date_to | query | string (YYYY-MM-DD) | اختياري | إلى تاريخ |
@GET("renewal-logs")
suspend fun getRenewalLogs(
@Query("page") page: Int = 1,
@Query("per_page") perPage: Int = 20,
@Query("search") search: String? = null,
@Query("action_type") actionType: String? = null,
@Query("service_plan_id") servicePlanId: Int? = null,
@Query("payment_status") paymentStatus: String? = null
): Response<RenewalLogsResponse>
curl -X GET "https://isp.freenet.net/api/manager/renewal-logs?page=1" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/renewal-logs`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/renewal-logs');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/renewal-logs', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"current_page": 1,
"total": 384,
"data": [
{
"id": 512,
"subscriber_id": 105,
"subscriber_name": "محمود أحمد حسن",
"username": "mahmoud.ahmed",
"action_type": "renewal",
"service_plan_name": "باقة سوبر 30 ميجا",
"price": 180.0,
"discount": 20.0,
"final_amount": 160.0,
"payment_method": "cash",
"admin_name": "المدير العام",
"starts_at": "2026-09-09 14:30:00",
"expires_at": "2026-10-11 23:59:59",
"created_at": "2026-09-09 14:30:15",
"can_reverse": true
}
]
}
{
"message": "Unauthenticated."
}
استعراض السجل التاريخي لتجديدات وتغييرات باقات مشترك معين.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| page | query | integer | اختياري | رقم الصفحة |
@GET("subscribers/{id}/renewal-logs")
suspend fun getSubscriberRenewalLogs(
@Path("id") subscriberId: Int,
@Query("page") page: Int = 1
): Response<RenewalLogsResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/renewal-logs" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/renewal-logs`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/renewal-logs');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/renewal-logs', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 512,
"action_type": "renewal",
"service_plan_name": "باقة سوبر 30 ميجا",
"final_amount": 160.0,
"created_at": "2026-09-09 14:30:15"
}
]
}
{
"message": "Unauthenticated."
}
التراجع المحاسبي والفني عن عملية التجديد المحددة بواسطة معرف السجل Log ID واسترداد الرصيد وإعادة فترة الاشتراك.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف سجل التجديد |
@POST("renewal-logs/{id}/reverse")
suspend fun reverseRenewalLog(@Path("id") logId: Int, @Body body: Map<String, Any?> = emptyMap()): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/renewal-logs/512/reverse" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/renewal-logs/{id}/reverse`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/renewal-logs/{id}/reverse');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/renewal-logs/{id}/reverse', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم التراجع عن عملية التجديد بنجاح واسترداد المبلغ"
}
{
"message": "لا يمكن التراجع عن هذه العملية؛ لقد مضى وقت طويل أو تم تعديل الاشتراك لاحقاً."
}
إدارة دورة الفوترة الشاملة: استعلام فواتير النظام، إنشاء فواتير الاشتراكات، إنشاء فواتير مخصصة متعددة البنود والخدمات، سداد وإلغاء الفواتير، تعديل مواعيد الاستحقاق، واستخراج بيانات الطباعة الحرارية المجهزة لطابعات الفواتير المحمولة والـ 80mm POS Printers.
استرجاع جميع الفواتير المسجلة في النظام مع خيارات البحث والفلترة حسب الحالة (مدفوعة، غير مدفوعة، ملغاة، جزئية)، المشرف المسؤول، ونطاق التاريخ.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة |
| per_page | query | integer | اختياري | عدد الفواتير بالصفحة (الافتراضي 20) |
| search | query | string | اختياري | البحث برقم الفاتورة أو اسم المشترك أو هاتفه |
| status | query | string | اختياري | الحالة: paid, unpaid, partially_paid, cancelled |
@GET("invoices/all")
suspend fun getAllInvoices(
@Query("page") page: Int = 1,
@Query("per_page") perPage: Int = 20,
@Query("search") search: String? = null,
@Query("status") status: String? = null
): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/invoices/all?status=unpaid" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/invoices/all`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/invoices/all');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/invoices/all', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"current_page": 1,
"total": 920,
"data": [
{
"id": 4012,
"invoice_number": "INV-2026-09-0012",
"subscriber_name": "محمود أحمد حسن",
"subscriber_phone": "01098765432",
"total_amount": 180.0,
"paid_amount": 180.0,
"remaining_amount": 0.0,
"status": "paid",
"due_date": "2026-09-24",
"created_at": "2026-09-09 14:30:15"
}
]
}
{
"message": "Unauthenticated."
}
استعراض قائمة الفواتير التاريخية لمشترك معين في الشاشة المخصصة للمشترك.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف المشترك |
| page | query | integer | اختياري | رقم الصفحة |
@GET("subscribers/{id}/invoices")
suspend fun getSubscriberInvoices(
@Path("id") subscriberId: Int,
@Query("page") page: Int = 1
): Response<InvoiceListResponse>
curl -X GET "https://isp.freenet.net/api/manager/subscribers/105/invoices" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/subscribers/{id}/invoices`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/subscribers/{id}/invoices');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/subscribers/{id}/invoices', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 4012,
"invoice_number": "INV-2026-09-0012",
"total_amount": 180.0,
"status": "paid"
}
]
}
{
"message": "Unauthenticated."
}
إنشاء فاتورة يدوية مخصصة تحتوي على بنود متنوعة (مثل: تكلفة راوتر، رسوم تركيب وصيانة، كابلات، اشتراكات خاصة) مع حساب الإجمالي والضريبة والخصم.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| subscriber_id | body | integer | إلزامي | معرف المشترك |
| items | body | array of objects | إلزامي | قائمة البنود (الاسم، الكمية، سعر الوحدة) |
| notes | body | string | اختياري | ملاحظات الفاتورة |
| due_date | body | string (YYYY-MM-DD) | اختياري | تاريخ الاستحقاق |
{
"subscriber_id": 105,
"items": [
{
"description": "راوتر تي بي لينك AC1200",
"quantity": 1,
"unit_price": 850.0
},
{
"description": "كابل سلك شبكة 30 متر",
"quantity": 30,
"unit_price": 8.0
},
{
"description": "مصنعية تركيب وصيانة",
"quantity": 1,
"unit_price": 100.0
}
],
"notes": "تركيب جديد الدور الثالث",
"due_date": "2026-09-20"
}
@POST("invoices/custom")
suspend fun createCustomInvoice(@Body body: Map<String, Any?>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/invoices/custom" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"subscriber_id": 105, "items": [{"description": "راوتر", "quantity": 1, "unit_price": 850}]}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/invoices/custom`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"subscriber_id": 105, "items": [{"description": "راوتر تي بي لينك AC1200", "quantity": 1, "unit_price": 850.0}, {"description": "كابل سلك شبكة 30 متر", "quantity": 30, "unit_price": 8.0}, {"description": "مصنعية تركيب وصيانة", "quantity": 1, "unit_price": 100.0}], "notes": "تركيب جديد الدور الثالث", "due_date": "2026-09-20"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/invoices/custom');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"subscriber_id": 105, "items": [{"description": "راوتر تي بي لينك AC1200", "quantity": 1, "unit_price": 850.0}, {"description": "كابل سلك شبكة 30 متر", "quantity": 30, "unit_price": 8.0}, {"description": "مصنعية تركيب وصيانة", "quantity": 1, "unit_price": 100.0}], "notes": "تركيب جديد الدور الثالث", "due_date": "2026-09-20"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/invoices/custom', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"subscriber_id": 105, "items": [{"description": "راوتر تي بي لينك AC1200", "quantity": 1, "unit_price": 850.0}, {"description": "كابل سلك شبكة 30 متر", "quantity": 30, "unit_price": 8.0}, {"description": "مصنعية تركيب وصيانة", "quantity": 1, "unit_price": 100.0}], "notes": "تركيب جديد الدور الثالث", "due_date": "2026-09-20"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إنشاء الفاتورة المخصصة بنجاح",
"invoice": {
"id": 4013,
"invoice_number": "INV-CUSTOM-2026-0045",
"total_amount": 1190.0,
"status": "unpaid"
}
}
{
"message": "قائمة البنود items مطلوبة."
}
استعراض تفاصيل الفاتورة، البنود الفردية، المدفوعات المسجلة عليها، والمتبقي وتاريخ الاستحقاق.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| invoiceId | path | integer | إلزامي | معرف الفاتورة |
@GET("invoices/{invoiceId}")
suspend fun getInvoiceDetails(@Path("invoiceId") invoiceId: Int): Response<InvoiceDetailResponse>
curl -X GET "https://isp.freenet.net/api/manager/invoices/4013" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/invoices/{invoiceId}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/invoices/{invoiceId}');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/invoices/{invoiceId}', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"id": 4013,
"invoice_number": "INV-CUSTOM-2026-0045",
"subscriber": {
"id": 105,
"name": "محمود أحمد حسن",
"phone": "01098765432"
},
"total_amount": 1190.0,
"paid_amount": 0.0,
"remaining_amount": 1190.0,
"status": "unpaid",
"items": [
{
"description": "راوتر تي بي لينك AC1200",
"quantity": 1,
"unit_price": 850.0,
"total": 850.0
}
]
}
{
"message": "الفاتورة غير موجودة."
}
تسجيل سداد الفاتورة نقداً أو عبر محفظة المشترك أو بطرق الدفع الإلكتروني وتحديث حالة الفاتورة لـ Paid.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| invoiceId | path | integer | إلزامي | معرف الفاتورة |
| amount | body | number | اختياري | المبلغ المدفوع (الافتراضي: كامل قيمة الفاتورة) |
| payment_method | body | string | اختياري | طريقة الدفع: cash, wallet |
{
"amount": 1190.0,
"payment_method": "cash"
}
@POST("invoices/{invoiceId}/pay")
suspend fun payInvoiceDirect(
@Path("invoiceId") invoiceId: Int,
@Body payload: Map<String, Any?>
): Response<SimpleResponse>
curl -X POST "https://isp.freenet.net/api/manager/invoices/4013/pay" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"amount": 1190.00, "payment_method": "cash"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/invoices/{invoiceId}/pay`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"amount": 1190.0, "payment_method": "cash"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/invoices/{invoiceId}/pay');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"amount": 1190.0, "payment_method": "cash"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/invoices/{invoiceId}/pay', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"amount": 1190.0, "payment_method": "cash"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم سداد الفاتورة بنجاح وإصدار إيصال السداد",
"remaining_amount": 0.0,
"invoice_status": "paid"
}
{
"message": "الفاتورة مسددة بالكامل بالفعل."
}
إلغاء عملية سداد الفاتورة وإعادة فتحها كـ Unpaid واسترجاع المبالغ لحساب المشرف أو المشترك في حال الخطأ.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| invoiceId | path | integer | إلزامي | معرف الفاتورة |
@POST("invoices/{invoiceId}/reverse")
suspend fun reverseInvoice(
@Path("invoiceId") invoiceId: Int,
@Body payload: Map<String, Any?> = emptyMap()
): Response<SimpleResponse>
curl -X POST "https://isp.freenet.net/api/manager/invoices/4013/reverse" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/invoices/{invoiceId}/reverse`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/invoices/{invoiceId}/reverse');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/invoices/{invoiceId}/reverse', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم التراجع عن سداد الفاتورة وإعادة فتحها بنجاح"
}
{
"message": "لا يمكن التراجع عن هذه الفاتورة."
}
جلب بيانات الفاتورة المنسقة والمجهزة خصيصاً للإرسال المباشر لطابعات البلوتوث والـ USB والـ Network Thermal Printers (80mm / 58mm ESC/POS) مع الترويسة وQR Code والفواتير الإلكترونية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| invoiceId | path | integer | إلزامي | معرف الفاتورة |
@GET("invoices/{invoiceId}/print-data")
suspend fun getInvoicePrintData(@Path("invoiceId") invoiceId: Int): Response<InvoiceDetailResponse>
curl -X GET "https://isp.freenet.net/api/manager/invoices/4012/print-data" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/invoices/{invoiceId}/print-data`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/invoices/{invoiceId}/print-data');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/invoices/{invoiceId}/print-data', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"company_name": "شبكة فري نت لخدمات الإنترنت",
"branch_name": "فرع وسط البلد",
"company_phone": "01000000000",
"tax_number": "987-654-321",
"receipt_number": "REC-2026-09-0012",
"date": "2026-09-09 14:30:15",
"subscriber_name": "محمود أحمد حسن",
"username": "mahmoud.ahmed",
"items": [
{
"name": "تجديد باقة سوبر 30 ميجا",
"qty": 1,
"price": 180.0,
"total": 180.0
}
],
"subtotal": 180.0,
"discount": 20.0,
"total_paid": 160.0,
"cashier_name": "أحمد علي",
"qr_code_data": "https://isp.freenet.net/verify/inv/REC-2026-09-0012",
"footer_message": "شكراً لاختياركم فري نت - خدمة العملاء 24/7"
}
{
"message": "الفاتورة غير موجودة."
}
تأجيل أو تقديم تاريخ استحقاق الفاتورة للمشترك.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| invoiceId | path | integer | إلزامي | معرف الفاتورة |
| due_date | body | string (YYYY-MM-DD) | إلزامي | تاريخ الاستحقاق الجديد |
{
"due_date": "2026-10-01"
}
@PATCH("invoices/{invoiceId}/due-date")
suspend fun updateInvoiceDueDate(
@Path("invoiceId") invoiceId: Int,
@Body payload: Map<String, Any?>
): Response<SimpleResponse>
curl -X PATCH "https://isp.freenet.net/api/manager/invoices/4012/due-date" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"due_date": "2026-10-01"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/invoices/{invoiceId}/due-date`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"due_date": "2026-10-01"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/invoices/{invoiceId}/due-date');
final response = await http.patch(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"due_date": "2026-10-01"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('PATCH', 'api/manager/invoices/{invoiceId}/due-date', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"due_date": "2026-10-01"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث تاريخ استحقاق الفاتورة بنجاح"
}
{
"message": "تاريخ الاستحقاق غير صالح."
}
إدارة دفعات كروت الشحن وطباعتها وتصديرها، التحقق من صلاحية الكروت، البيع السريع عبر نقاط البيع المخصصة (POS Fast Selling) مع بيانات الطباعة الفورية للطابعات الحرارية، وإحصائيات مبيعات الكروت اللحظية.
استعراض دفعات الكروت المنشأة مع إحصائيات كل دفعة: إجمالي عدد الكروت، الكروت المباعة/المستخدمة، الكروت المتاحة، وسعر الكارت.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة |
| search | query | string | اختياري | البحث باسم الدفعة أو الباقة |
@GET("vouchers")
suspend fun getVoucherBatches(@Query("page") page: Int, @Query("search") search: String? = null): Response<VoucherBatchListResponse>
curl -X GET "https://isp.freenet.net/api/manager/vouchers?page=1" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/vouchers', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 15,
"name": "دفعة كروت كافيه 5 جنيه - سبتمبر",
"plan_name": "باقة 5 جنيه - 3 ساعات",
"total_vouchers": 500,
"used_vouchers": 312,
"unused_vouchers": 188,
"card_price": 5.0,
"status": "active",
"created_at": "2026-09-01 10:00:00"
}
]
}
{
"message": "Unauthenticated."
}
جلب قائمة الباقات المدعومة للكروت، القوالب التصميمية المتاحة، والخيارات المسبقة لإنشاء الدفعة.
@GET("vouchers/create-data")
suspend fun getVoucherCreateData(): Response<VoucherCreateData>
curl -X GET "https://isp.freenet.net/api/manager/vouchers/create-data" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers/create-data`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers/create-data');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/vouchers/create-data', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"plans": [
{
"id": 5,
"name": "كارت 5 جنيه - 500 ميجا",
"price": 5.0
},
{
"id": 6,
"name": "كارت 10 جنيه - 1.5 جيجا",
"price": 10.0
}
],
"templates": [
{
"id": 1,
"name": "قالب كروت قياسي (6 في الورقة)"
},
{
"id": 2,
"name": "قالب مصغر (10 في الورقة)"
}
]
}
{
"message": "Unauthenticated."
}
توليد دفعة جديدة من كروت الشحن العشوائية المشفرة بالكمية المحددة، واختيار طول الكود (مثال: 8 أو 12 رقم)، والبادئة (Prefix)، وتاريخ الصلاحية وتكلفة الكارت.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| name | body | string | إلزامي | اسم الدفعة التوضيحي |
| service_plan_id | body | integer | إلزامي | معرف الباقة المربوطة بالكارت |
| quantity | body | integer | إلزامي | عدد الكروت المراد توليدها (10 - 2000) |
| code_length | body | integer | اختياري | طول كود الكارت (الافتراضي: 10 أرقام) |
| prefix | body | string | اختياري | بادئة اختيارية تسبق الأرقام (مثال: FN) |
| price | body | number | اختياري | سعر البيع الافتراضي للكارت |
{
"name": "دفعة كروت الأسبوع 10ج",
"service_plan_id": 6,
"quantity": 200,
"code_length": 10,
"prefix": "F10",
"price": 10.0
}
@POST("vouchers")
@FormUrlEncoded
suspend fun createVoucherBatch(@FieldMap params: Map<String, Any>): Response<VoucherBatch>
curl -X POST "https://isp.freenet.net/api/manager/vouchers" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"name": "دفعة جديدة", "service_plan_id": 6, "quantity": 100}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"name": "دفعة كروت الأسبوع 10ج", "service_plan_id": 6, "quantity": 200, "code_length": 10, "prefix": "F10", "price": 10.0})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"name": "دفعة كروت الأسبوع 10ج", "service_plan_id": 6, "quantity": 200, "code_length": 10, "prefix": "F10", "price": 10.0}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/vouchers', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"name": "دفعة كروت الأسبوع 10ج", "service_plan_id": 6, "quantity": 200, "code_length": 10, "prefix": "F10", "price": 10.0}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم توليد 200 كارت بنجاح",
"batch": {
"id": 16,
"name": "دفعة كروت الأسبوع 10ج",
"total_vouchers": 200
}
}
{
"message": "رصيد المشرف غير كافٍ لتوليد هذه الكمية من الكروت."
}
جلب قائمة الكروت المفردة داخل الدفعة وحالة كل كارت (مباع، غير مستخدم، ملغي) وبيانات الاستخدام.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف الدفعة |
@GET("vouchers/batch/{id}")
suspend fun getBatchVouchers(@Path("id") id: Int): Response<BatchVouchersResponse>
curl -X GET "https://isp.freenet.net/api/manager/vouchers/batch/16" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers/batch/{id}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers/batch/{id}');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/vouchers/batch/{id}', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"batch_id": 16,
"batch_name": "دفعة كروت الأسبوع 10ج",
"vouchers": [
{
"id": 8410,
"code": "F1089452174",
"status": "unused",
"used_at": null,
"mac_address": null
}
]
}
{
"message": "الدفعة غير موجودة."
}
التحقق من حالة كود كارت الشحن وصلاحيته، ونوع الباقة وسعرها، وما إذا كان مستخدماً أو متاحاً للشحن.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| code | body | string | إلزامي | كود كارت الشحن |
{
"code": "F1089452174"
}
@POST("vouchers/check")
@FormUrlEncoded
suspend fun checkVoucher(@Field("code") code: String): Response<VoucherCheckResponse>
curl -X POST "https://isp.freenet.net/api/manager/vouchers/check" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"code": "F1089452174"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers/check`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"code": "F1089452174"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers/check');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"code": "F1089452174"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/vouchers/check', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"code": "F1089452174"}
]);
$data = json_decode($response->getBody(), true);
{
"is_valid": true,
"status": "unused",
"card_price": 10.0,
"plan_name": "كارت 10 جنيه - 1.5 جيجا",
"batch_name": "دفعة كروت الأسبوع 10ج"
}
{
"message": "كود الكارت غير موجود بالنظام."
}
قائمة الكروت والدفعات المجهزة لواجهات الكاشير والبيع السريع POS، مقسمة حسب الفئات والأسعار لسرعة اختيارها وبيعها بلمسة واحدة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| type | query | string | اختياري | نوع الباقة: hotspot, time, quota |
| search | query | string | اختياري | البحث السريع |
@GET("vouchers/pos/batches")
suspend fun getPosBatches(@Query("type") type: String? = null): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/vouchers/pos/batches" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers/pos/batches`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers/pos/batches');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/vouchers/pos/batches', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"categories": [
{
"category_name": "كروت الهوت سبوت",
"items": [
{
"batch_id": 15,
"name": "كارت 5ج (3 ساعات)",
"price": 5.0,
"available_count": 188
},
{
"batch_id": 16,
"name": "كارت 10ج (1.5 جيجا)",
"price": 10.0,
"available_count": 200
}
]
}
]
}
{
"message": "Unauthenticated."
}
سحب وبيع أول كارت متاح من الدفعة فورياً وتغيير حالته لـ Sold، وإرجاع بيانات الكارت المنسقة للطباعة الحرارية المباشرة (ESC/POS) متضمنة الكود وQR Code وتعليمات تسجيل الدخول.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| batch_id | body | integer | إلزامي | معرف دفعة الكروت المراد السحب منها |
| customer_phone | body | string | اختياري | رقم هاتف المشتري (اختياري لإرسال الكود له عبر الواتساب) |
{
"batch_id": 15,
"customer_phone": "01011122233"
}
@POST("vouchers/pos/sell")
suspend fun posSellVoucher(@Body data: Map<String, Any?>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/vouchers/pos/sell" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"batch_id": 15}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers/pos/sell`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"batch_id": 15, "customer_phone": "01011122233"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers/pos/sell');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"batch_id": 15, "customer_phone": "01011122233"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/vouchers/pos/sell', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"batch_id": 15, "customer_phone": "01011122233"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم بيع الكارت بنجاح",
"voucher": {
"id": 8411,
"code": "FREE-9081234",
"price": 5.0,
"plan_name": "باقة 5 جنيه - 3 ساعات",
"sold_at": "2026-09-09 14:35:00"
},
"print_payload": {
"company_name": "شبكة فري نت",
"card_code": "FREE-9081234",
"price_formatted": "5.00 ج.م",
"duration": "3 ساعات صالحة لمدة 24 ساعة",
"login_url": "http://freenet.wifi",
"support_phone": "01000000000"
}
}
{
"message": "نفدت الكروت غير المستخدمة من هذه الدفعة."
}
استرجاع بيانات طباعة آخر كارت تم بيعه عبر نقطة البيع في حال انحشار ورق الطابعة أو انقطاع البلوتوث.
@POST("vouchers/pos/reprint-last")
suspend fun posReprintLast(@Body data: Map<String, Any?> = emptyMap()): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/vouchers/pos/reprint-last" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers/pos/reprint-last`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers/pos/reprint-last');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/vouchers/pos/reprint-last', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"card_code": "FREE-9081234",
"price": 5.0,
"print_payload": {
"card_code": "FREE-9081234",
"price_formatted": "5.00 ج.م"
}
}
{
"message": "لا توجد عمليات بيع حديثة لإعادة طباعتها."
}
تقارير مبيعات الكروت اللحظية: إجمالي المبيعات بالجنيه اليوم، عدد الكروت المباعة اليوم وهذا الشهر، وأكثر الدفعات مبيعاً.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| start_date | query | string | اختياري | من تاريخ |
| end_date | query | string | اختياري | إلى تاريخ |
@GET("vouchers/statistics")
suspend fun getVoucherStatistics(@QueryMap params: Map<String, String> = emptyMap()): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/vouchers/statistics" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/vouchers/statistics`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/vouchers/statistics');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/vouchers/statistics', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"today_sales_amount": 1450.0,
"today_sold_count": 185,
"month_sales_amount": 32800.0,
"month_sold_count": 4120,
"top_batches": [
{
"name": "كارت 5 جنيه",
"count": 120,
"revenue": 600.0
},
{
"name": "كارت 10 جنيه",
"count": 65,
"revenue": 650.0
}
]
}
{
"message": "Unauthenticated."
}
إدارة كامل البنية التحتية للشبكة: السويتشات، أجهزة البث، كبائن الـ OLT، وراوترات المايكروتك MikroTik، وفحص الاتصال الحي (Ping Tests)، وإعادة التشغيل عن بُعد (Remote Reboot)، وسجلات التوقف، وحصر المشتركين المتصلين بكل جهاز وتوليد أنفاق الاتصال الآمنة (Tunnels).
استرجاع قائمة أجهزة الشبكة الموزعة بالأبراج والمواقع مع فلترة حسب النوع (سويتش، راوتر، أكسس بوينت)، الموقع، وحالة الاتصال (online / offline).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة |
| type | query | string | اختياري | نوع الجهاز: switch, router, ap, olt |
| status | query | string | اختياري | الحالة: online, offline |
| search | query | string | اختياري | البحث بالاسم أو الـ IP أو الموقع |
@GET("network-devices")
suspend fun getNetworkDevices(
@Query("page") page: Int = 1,
@Query("type") type: String? = null,
@Query("status") status: String? = null
): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/network-devices" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/network-devices`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/network-devices');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/network-devices', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 1,
"name": "Switch-Cisco-Tower1",
"ip_address": "192.168.10.15",
"type": "switch",
"location": "برج التحرير - كابينة 1",
"status": "online",
"latency_ms": 1.8,
"last_ping_at": "2026-09-09 14:34:20",
"online_subscribers_count": 64
}
]
}
{
"message": "Unauthenticated."
}
إرسال حزم ICMP فحص لحظية للجهاز وقياس زمن الاستجابة (Latency) ونسبة فقد الحزم (Packet Loss).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف الجهاز |
@POST("network-devices/{id}/ping")
suspend fun pingNetworkDevice(@Path("id") id: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/network-devices/1/ping" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/network-devices/{id}/ping`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/network-devices/{id}/ping');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/network-devices/{id}/ping', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "online",
"latency_ms": 2.4,
"packets_sent": 4,
"packets_received": 4,
"packet_loss_percentage": 0,
"message": "الجهاز متصل ويعمل بشكل سليم"
}
{
"message": "تعذر الوصول للجهاز؛ زمن الانتظار انتهى (Request Timeout)."
}
إطلاق ديمون فحص الاتصال التلقائي لكافة أجهزة الشبكة وتحديث لوحة المراقبة وإرسال تنبيهات بالأجهزة المتوقفة.
@POST("network-devices/ping-all")
suspend fun pingAllNetworkDevices(): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/network-devices/ping-all" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/network-devices/ping-all`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/network-devices/ping-all');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/network-devices/ping-all', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"total_devices_scanned": 48,
"online_count": 47,
"offline_count": 1,
"offline_devices": [
"AP-North-04"
]
}
{
"message": "Unauthenticated."
}
إرسال أمر إعادة تشغيل آمن للجهاز عبر بروتوكول SSH أو MikroTik API أو SNMP.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف الجهاز |
@POST("network-devices/{id}/reboot")
suspend fun rebootNetworkDevice(@Path("id") id: Int): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/network-devices/1/reboot" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/network-devices/{id}/reboot`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/network-devices/{id}/reboot');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/network-devices/{id}/reboot', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إرسال أمر إعادة التشغيل بنجاح؛ جاري إعادة إقلاع الجهاز"
}
{
"message": "فشل الاتصال بواجهة الجهاز لإرسال أمر إعادة التشغيل."
}
استعراض قائمة المشتركين المتصلين بالإنترنت حالياً والتي تمر حركة بياناتهم عبر هذا السويتش أو الراوتر المحدد.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف الجهاز |
@GET("network-devices/{id}/online-subscribers")
suspend fun getDeviceOnlineSubscribers(@Path("id") id: Int): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/network-devices/1/online-subscribers" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/network-devices/{id}/online-subscribers`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/network-devices/{id}/online-subscribers');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/network-devices/{id}/online-subscribers', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"device_name": "Switch-Cisco-Tower1",
"total_online": 64,
"subscribers": [
{
"id": 105,
"name": "محمود أحمد",
"username": "mahmoud.ahmed",
"ip": "10.100.4.55"
}
]
}
{
"message": "الجهاز غير موجود."
}
إدارة شبكة المشرفين والموزعين، شحن وتعديل الأرصدة، تحويل الرصيد بين الحسابات، إدارة الحدود الائتمانية والديون، وتتبع السجل المالي للحركات المحاسبية.
استعراض المشرفين والموزعين التابعين للنظام مع أرصدتهم الحالية، ديونهم، وحدودهم الائتمانية، وحالة حساباتهم.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| search | query | string | اختياري | البحث بالاسم أو اسم المستخدم أو الهاتف |
@GET("admins")
suspend fun getAdmins(@Query("search") search: String? = null): Response<AdminListResponse>
curl -X GET "https://isp.freenet.net/api/manager/admins" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/admins`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/admins');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/admins', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 2,
"name": "موزع سنترال المحطة",
"username": "reseller_station",
"phone": "01099887766",
"balance": 4500.0,
"credit_limit": 10000.0,
"total_debt": 2500.0,
"is_active": true,
"subscribers_count": 184
}
]
}
{
"message": "Unauthenticated."
}
شحن أو تحويل رصيد من حساب المدير العام إلى موزع أو بين المشرفين، مع تسجيل القيد المزدوج في دفتر اليومية داخل معاملة مالية آمنة ومقفلة (DB Transaction).
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| admin_id | body | integer | إلزامي | معرف المشرف أو الموزع المستهدف |
| amount | body | number | إلزامي | المبلغ المراد تحويله أو شحنه |
| type | body | string | إلزامي | نوع العملية: credit (إيداع/شحن) أو debit (خصم) |
| notes | body | string | اختياري | بيان الحركة المالية |
{
"admin_id": 2,
"amount": 5000.0,
"type": "credit",
"notes": "شحن رصيد كروت واشتراكات سبتمبر"
}
@POST("admins/transaction")
suspend fun adminTransaction(@Body payload: Map<String, Any?>): Response<Unit>
curl -X POST "https://isp.freenet.net/api/manager/admins/transaction" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"admin_id": 2, "amount": 5000, "type": "credit"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/admins/transaction`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"admin_id": 2, "amount": 5000.0, "type": "credit", "notes": "شحن رصيد كروت واشتراكات سبتمبر"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/admins/transaction');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"admin_id": 2, "amount": 5000.0, "type": "credit", "notes": "شحن رصيد كروت واشتراكات سبتمبر"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/admins/transaction', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"admin_id": 2, "amount": 5000.0, "type": "credit", "notes": "شحن رصيد كروت واشتراكات سبتمبر"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحويل المبلغ بنجاح وتحديث أرصدة المشرفين",
"new_balance": 9500.0
}
{
"message": "رصيد المحفظة المصدر غير كافٍ لإتمام التحويل."
}
تسجيل سداد نقدي لمديونيات المشرف وتصفية حسابه الآجل.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| admin_id | body | integer | إلزامي | معرف المشرف |
| amount | body | number | إلزامي | المبلغ المسدد |
{
"admin_id": 2,
"amount": 2500.0
}
@POST("admins/pay-debts")
suspend fun payDebts(@Body data: Map<String, Any>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/admins/pay-debts" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"admin_id": 2, "amount": 2500}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/admins/pay-debts`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"admin_id": 2, "amount": 2500.0})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/admins/pay-debts');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"admin_id": 2, "amount": 2500.0}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/admins/pay-debts', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"admin_id": 2, "amount": 2500.0}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تسجيل سداد الدين بنجاح وتصفية المديونية",
"remaining_debt": 0.0
}
{
"message": "المبلغ المسدد أكبر من إجمالي المديونية المستحقة."
}
سجل الحركات المالية المكتملة في النظام: الشحن، التحويل، سداد الاشتراكات، والفواتير مع تاريخ ووقت كل حركة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة |
@GET("transactions")
suspend fun getTransactions(): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/transactions" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/transactions`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/transactions');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/transactions', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"data": [
{
"id": 182,
"type": "credit",
"amount": 5000.0,
"balance_before": 4500.0,
"balance_after": 9500.0,
"description": "شحن رصيد كروت واشتراكات سبتمبر",
"created_at": "2026-09-09 14:38:00"
}
]
}
{
"message": "Unauthenticated."
}
تقارير الأعمال والتحليلات: ملخص الإيرادات والمبيعات، منحنيات المبيعات البيانية، نسب توزيع المشتركين على الباقات، كشف الحساب المالي المفصل للمدير الحالي، وقائمة أكثر المشتركين استهلاكاً للباندويث.
إحصائيات الإيرادات والمتحصلات الإجمالية: مبيعات الاشتراكات، مبيعات الكروت، إجمالي الديون، وصافي الأرباح.
@GET("reports/sales-summary")
suspend fun getSalesSummary(): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/reports/sales-summary" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/reports/sales-summary`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/reports/sales-summary');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/reports/sales-summary', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"total_revenue": 142850.0,
"subscriptions_revenue": 110050.0,
"vouchers_revenue": 32800.0,
"total_unpaid_debts": 8450.0,
"net_cash": 134400.0
}
{
"message": "Unauthenticated."
}
نقاط الرسم البياني للمبيعات اليومية والشهرية لرسم منحنيات الإيرادات في تطبيق الهاتف ولوحة التحكم.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| period | query | string | اختياري | الفترة: week, month, year (الافتراضي: month) |
@GET("reports/sales-chart")
suspend fun getSalesChart(@Query("period") period: String? = "month"): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/reports/sales-chart?period=month" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/reports/sales-chart`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/reports/sales-chart');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/reports/sales-chart', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"labels": [
"2026-09-01",
"2026-09-02",
"2026-09-03",
"2026-09-04",
"2026-09-05"
],
"data": [
4500.0,
6200.0,
3800.0,
8900.0,
7100.0
]
}
{
"message": "Unauthenticated."
}
نسبة المشتركين في كل باقة لرسم المخطط الدائري (Pie Chart) وتحليل الإقبال على السرعات.
@GET("reports/plans-distribution")
suspend fun getPlansDistribution(): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/reports/plans-distribution" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/reports/plans-distribution`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/reports/plans-distribution');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/reports/plans-distribution', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
[
{
"plan_name": "باقة سوبر 30 ميجا",
"subscribers_count": 820,
"percentage": 57.7
},
{
"plan_name": "باقة الترا 70 ميجا",
"subscribers_count": 420,
"percentage": 29.6
},
{
"plan_name": "باقات أخرى",
"subscribers_count": 180,
"percentage": 12.7
}
]
{
"message": "Unauthenticated."
}
كشف حساب مالي لحظي للمدير المسجل حالياً: المبالغ المحصلة كاش في عهدته، التحويلات الصادرة والواردة، وقيمة المبيعات المحققة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| start_date | query | string | اختياري | من تاريخ |
| end_date | query | string | اختياري | إلى تاريخ |
@GET("reports/my-financial")
suspend fun getMyFinancialReport(
@Query("start_date") startDate: String? = null,
@Query("end_date") endDate: String? = null
): Response<FinancialReportResponse>
curl -X GET "https://isp.freenet.net/api/manager/reports/my-financial" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/reports/my-financial`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/reports/my-financial');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/reports/my-financial', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"admin_id": 1,
"admin_name": "المدير العام",
"cash_in_hand": 12450.0,
"wallet_balance": 15450.0,
"renewals_collected": 11200.0,
"vouchers_sold": 1250.0
}
{
"message": "Unauthenticated."
}
قائمة بأكثر المشتركين استهلاكاً للجيجابايت خلال الفترة المحددة لمراقبة الأحمال واكتشاف السلوكيات غير العادية.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| period | query | string | اختياري | الفترة: month أو week (الافتراضي: month) |
| limit | query | integer | اختياري | عدد المشتركين (الافتراضي: 10) |
@GET("reports/top-consumers")
suspend fun getTopConsumers(
@Query("period") period: String? = "month",
@Query("limit") limit: Int? = 10
): Response<TopConsumersResponse>
curl -X GET "https://isp.freenet.net/api/manager/reports/top-consumers?limit=10" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/reports/top-consumers`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/reports/top-consumers');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/reports/top-consumers', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
[
{
"subscriber_id": 105,
"name": "محمود أحمد حسن",
"username": "mahmoud.ahmed",
"total_usage_gb": 485.6,
"plan_name": "باقة سوبر 30 ميجا"
}
]
{
"message": "Unauthenticated."
}
تسجيل ومتابعة مصروفات الشبكة والتشغيل: الصيانة، فواتير الكهرباء، إيجارات الأبراج، السيرفرات، ومشتريات الأجهزة وتصنيفها ضمن فئات المصروفات.
استعراض المصروفات المسجلة مع إمكانية التصفية بنطاق التاريخ وتصنيف المصروف.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة |
| start_date | query | string | اختياري | تاريخ البداية |
| end_date | query | string | اختياري | تاريخ النهاية |
@GET("expenses")
suspend fun getExpenses(
@Query("page") page: Int = 1,
@Query("start_date") startDate: String? = null,
@Query("end_date") endDate: String? = null
): Response<ExpenseListResponse>
curl -X GET "https://isp.freenet.net/api/manager/expenses" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/expenses`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/expenses');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/expenses', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"current_page": 1,
"total": 45,
"data": [
{
"id": 1,
"title": "إيجار برج التحرير - شهر سبتمبر",
"amount": 2500.0,
"date": "2026-09-01",
"description": "سداد إيجار موقع البرج",
"category": {
"id": 2,
"name": "إيجار أبراج ومواقع"
}
}
]
}
{
"message": "Unauthenticated."
}
إضافة قيد مصروف مالي جديد وتحديد البند والمبلغ وخصمه من رصيد الخزينة.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| title | body | string | إلزامي | عنوان المصروف |
| amount | body | number | إلزامي | المبلغ المنصرف |
| category_id | body | integer | اختياري | معرف فئة المصروف |
| date | body | string (YYYY-MM-DD) | إلزامي | تاريخ الصرف |
| description | body | string | اختياري | شرح وتفاصيل إضافية |
{
"title": "شراء بنشات وسويتش 8 بورت",
"amount": 650.0,
"date": "2026-09-09",
"description": "توصيل كابينة شارع المحطة"
}
@POST("expenses")
suspend fun createExpense(@Body data: Map<String, Any?>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/expenses" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"title": "شراء معدات", "amount": 650, "date": "2026-09-09"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/expenses`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"title": "شراء بنشات وسويتش 8 بورت", "amount": 650.0, "date": "2026-09-09", "description": "توصيل كابينة شارع المحطة"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/expenses');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"title": "شراء بنشات وسويتش 8 بورت", "amount": 650.0, "date": "2026-09-09", "description": "توصيل كابينة شارع المحطة"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/expenses', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"title": "شراء بنشات وسويتش 8 بورت", "amount": 650.0, "date": "2026-09-09", "description": "توصيل كابينة شارع المحطة"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تسجيل المصروف بنجاح",
"expense": {
"id": 2,
"title": "شراء بنشات وسويتش 8 بورت",
"amount": 650.0
}
}
{
"message": "The given data was invalid."
}
متابعة تذاكر الدعم الفني وبلاغات الأعطال الواردة من المشتركين عبر تطبيق الهاتف، والرد عليها، وتغيير حالات التذاكر، وإسنادها لفنيي الصيانة.
استعراض تذاكر الدعم الفني مع الفلترة حسب الحالة (مفتوحة، قيد المعالجة، مغلقة) والبحث السريع.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| page | query | integer | اختياري | رقم الصفحة |
| status | query | string | اختياري | الحالة: open, in_progress, closed |
| search | query | string | اختياري | البحث برقم التذكرة أو اسم المشترك |
@GET("support/tickets")
suspend fun getSupportTickets(
@Query("page") page: Int = 1,
@Query("status") status: String? = null
): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/support/tickets?status=open" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/support/tickets`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/support/tickets');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/support/tickets', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"current_page": 1,
"data": [
{
"id": 88,
"ticket_number": "TCK-88",
"subscriber_name": "محمود أحمد حسن",
"subject": "بطء تصفح في ساعات المساء",
"priority": "medium",
"status": "open",
"created_at": "2026-09-09 11:20:00"
}
]
}
{
"message": "Unauthenticated."
}
إرسال رد رسمي من الدعم الفني على التذكرة مع إشعار المشترك بالرد فورياً عبر تطبيق الهاتف والواتساب.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف التذكرة |
| message | body | string | إلزامي | نص الرد الفني |
{
"message": "أهلاً بك يا فندم، تم فحص البورت وإعادة ضبط إشارات الروتر ويرجى التجربة الآن."
}
@POST("support/tickets/{id}/reply")
suspend fun replySupportTicket(@Path("id") id: Int, @Body body: Map<String, String>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/support/tickets/88/reply" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"message": "تم فحص المشكلة بنجاح"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/support/tickets/{id}/reply`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"message": "أهلاً بك يا فندم، تم فحص البورت وإعادة ضبط إشارات الروتر ويرجى التجربة الآن."})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/support/tickets/{id}/reply');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"message": "أهلاً بك يا فندم، تم فحص البورت وإعادة ضبط إشارات الروتر ويرجى التجربة الآن."}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/support/tickets/{id}/reply', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"message": "أهلاً بك يا فندم، تم فحص البورت وإعادة ضبط إشارات الروتر ويرجى التجربة الآن."}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم إرسال الرد وإشعار المشترك بنجاح"
}
{
"message": "نص الرد message مطلوب."
}
تحديث حالة التذكرة ليصبح closed أو in_progress.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| id | path | integer | إلزامي | معرف التذكرة |
| status | body | string | إلزامي | الحالة الجديدة: open, in_progress, closed |
{
"status": "closed"
}
@PATCH("support/tickets/{id}/status")
suspend fun updateSupportTicketStatus(@Path("id") id: Int, @Body body: Map<String, String>): Response<Map<String, Any>>
curl -X PATCH "https://isp.freenet.net/api/manager/support/tickets/88/status" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"status": "closed"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/support/tickets/{id}/status`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"status": "closed"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/support/tickets/{id}/status');
final response = await http.patch(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"status": "closed"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('PATCH', 'api/manager/support/tickets/{id}/status', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"status": "closed"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث حالة التذكرة بنجاح"
}
{
"message": "التذكرة غير موجودة."
}
استعراض وتحديث إعدادات النظام المخصصة للمدير، استعراض قائمة الأدوار والصلاحيات (Spatie Permissions)، وقائمة باقات الخدمة العامة النشطة.
استرجاع الإعدادات المخصصة للمدير: اسم الشركة، بادئة الفواتير، العملة الافتراضية، وخيارات التنبيهات.
@GET("settings")
suspend fun getSettings(): Response<Map<String, Any>>
curl -X GET "https://isp.freenet.net/api/manager/settings" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/settings`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/settings');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/settings', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
{
"company_name": "شبكة فري نت لخدمات الإنترنت",
"currency_symbol": "EGP",
"admin_prefix": "adm",
"invoice_footer": "شكراً لاختياركم فري نت",
"enable_whatsapp_alerts": true
}
{
"message": "Unauthenticated."
}
تحديث وحفظ الإعدادات المخصصة للمشرف في النظام.
| اسم الحقل | الموضع | النوع | الحالة | الوصف |
|---|---|---|---|---|
| company_name | body | string | اختياري | اسم الشبكة أو الشركة |
| invoice_footer | body | string | اختياري | رسالة ذيل الفاتورة |
{
"company_name": "شبكة فري نت - المنصورة",
"invoice_footer": "خدمة العملاء: 01000000000"
}
@POST("settings")
suspend fun updateSettings(@Body data: Map<String, Any>): Response<Map<String, Any>>
curl -X POST "https://isp.freenet.net/api/manager/settings" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"company_name": "فري نت"}'
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/settings`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"company_name": "شبكة فري نت - المنصورة", "invoice_footer": "خدمة العملاء: 01000000000"})
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/settings');
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: jsonEncode({"company_name": "شبكة فري نت - المنصورة", "invoice_footer": "خدمة العملاء: 01000000000"}),
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('POST', 'api/manager/settings', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'json' => {"company_name": "شبكة فري نت - المنصورة", "invoice_footer": "خدمة العملاء: 01000000000"}
]);
$data = json_decode($response->getBody(), true);
{
"status": "success",
"message": "تم تحديث الإعدادات بنجاح"
}
{
"message": "The given data was invalid."
}
استعراض قائمة الأدوار الوظيفية (Super Admin, Reseller, Technician) والصلاحيات المعرفة في النظام لاستخدامها في نماذج إنشاء وتعديل المشرفين.
@GET("roles")
suspend fun getRoles(): Response<List<Map<String, Any>>>
curl -X GET "https://isp.freenet.net/api/manager/roles" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/roles`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/roles');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/roles', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
[
{
"id": 1,
"name": "Super Admin",
"display_name": "المدير العام",
"permissions_count": 48
},
{
"id": 2,
"name": "Reseller",
"display_name": "موزع كروت واشتراكات",
"permissions_count": 14
}
]
{
"message": "Unauthenticated."
}
استعراض جميع باقات الإنترنت النشطة مع السرعات (الرفع والتحميل بالكيلوبت)، سعة الكوتا بالجيجابايت، الأسعار، وفترات الصلاحية.
@GET("plans")
suspend fun getPlans(): Response<List<ServicePlan>>
curl -X GET "https://isp.freenet.net/api/manager/plans" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
// JavaScript (Fetch)
async function request() {
const token = localStorage.getItem('freenet_token') || 'YOUR_TOKEN_HERE';
const baseUrl = localStorage.getItem('freenet_base_url') || 'https://isp.freenet.net/api/manager';
const response = await fetch(`${baseUrl}/api/manager/plans`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
console.log(data);
}
// Dart (Flutter)
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> sendRequest() async {
final url = Uri.parse('$baseUrl/api/manager/plans');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json'
},
);
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
}
// PHP (GuzzleHttp)
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://isp.freenet.net/api/manager/']);
$response = $client->request('GET', 'api/manager/plans', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
[
{
"id": 1,
"name": "باقة سوبر 30 ميجا",
"price": 180.0,
"download_speed": 30720,
"upload_speed": 5120,
"quota_gb": 250,
"duration_days": 30,
"type": "limited"
},
{
"id": 2,
"name": "باقة الترا 70 ميجا",
"price": 320.0,
"download_speed": 71680,
"upload_speed": 10240,
"quota_gb": 400,
"duration_days": 30,
"type": "limited"
}
]
{
"message": "Unauthenticated."
}