# PasarGuard API — Version-Aware Technical Documentation
## Source-based reference for Sonnet

> هدف این فایل: ارائه یک مرجع عملی برای توسعه integration با PasarGuard بدون ساختن endpoint یا schema فرضی.
>
> این سند **به یک نسخه واحد محدود نیست**. تفاوت‌های نسخه‌ای باید در جدول compatibility و بخش migration لحاظ شوند.
>
> منابع اصلی:
> - `AmirKenzo/PasarguardBot`
> - `AmirKenzo/pasarguard_api`
> - سورس و تست‌های `PasarGuard/panel`
>
> اصل مهم: هر چیزی که URL/HTTP method/schema آن مستقیماً از سورس یا OpenAPI قابل اثبات نباشد، با برچسب **UNVERIFIED** آمده و نباید توسط Sonnet حدس زده شود.

---

## 1. منابع مرجع

### 1.1 PasarguardBot

Repository:

`https://github.com/AmirKenzo/PasarguardBot`

این پروژه یک Telegram bot برای فروش و مدیریت سرویس‌های مبتنی بر PasarGuard است و دارای پوشه‌های `app/`، `docs/`، `scripts/` و فایل‌های پیکربندی است.

### 1.2 Python SDK

Repository:

`https://github.com/AmirKenzo/pasarguard_api`

SDK یک client تایپ‌شده و async برای PasarGuard Panel API است و در README خود حوزه‌های Users, Admins, Nodes, Groups, Hosts, Templates, Subscriptions, Settings, System Stats و Bulk Operations را اعلام می‌کند.

### 1.3 PasarGuard Panel

Repository:

`https://github.com/PasarGuard/panel`

این منبع برای تشخیص تغییرات واقعی API، مدل‌ها، تست‌های endpoint و migration بین نسخه‌ها مرجع اصلی است.

### 1.4 PHP client به‌عنوان منبع کمکی

`https://github.com/alirezax5/pasarguard-api-php`

این پروژه ساختارهایی مانند `userHWID`, `adminRoles`, `userTemplate`, `node`, `core`, `groups`, `host`, `clientTemplate`, `settings` و `system` را expose می‌کند.

**این پروژه منبع رسمی PasarGuard محسوب نمی‌شود و فقط برای cross-check استفاده شود.**

---

# 2. اصل Version Awareness

PasarGuard API در طول نسخه‌ها ثابت نمانده است.

بنابراین integration باید:

1. نسخه پنل را تشخیص دهد یا در configuration مشخص کند.
2. endpointهای deprecated را از endpointهای current جدا کند.
3. از APIهای ID-based برای نسخه‌هایی که آن‌ها را معرفی کرده‌اند استفاده کند.
4. compatibility layer داشته باشد.
5. هیچ endpoint جدیدی را فقط بر اساس نام یک متد SDK فرض نکند.

---

# 3. تغییر مهم API در v5

طبق اعلام رسمی PasarGuard:

### قدیمی

```http
/api/user/{username}
```

### مسیر فعلی معرفی‌شده در v5

```http
/api/user/by-id/{user_id}
```

### فرمت آینده اعلام‌شده

```http
/api/user/{id}
```

بنابراین:

```text
username-based API
    ↓
deprecated / migration path

ID-based API
    ↓
preferred for new integrations
```

**برای integration جدید، ID را به عنوان شناسه اصلی طراحی کن و username را فقط برای compatibility نگه دار.**

---

# 4. Authentication

SDK:

```python
api = PasarguardAPI(
    base_url=PASARGUARD_BASE_URL,
    verify=True,
    timeout=20.0,
)

token = await api.get_token(
    username=ADMIN_USERNAME,
    password=ADMIN_PASSWORD,
)
```

پس از login:

```http
Authorization: Bearer <access_token>
```

همچنین:

```python
admin_token()
```

alias برای `get_token()` است.

در تست‌های Panel نیز token به شکل:

```http
POST /api/admin/token
```

با فرم:

```text
username
password
grant_type=password
```

استفاده شده است.

> برای production، exact request/response schema را از OpenAPI نسخه هدف استخراج کن.

---

# 5. User API

SDK public methods:

```text
create_user()
get_user()
get_users()
modify_user()
remove_user()

bulk_delete_users()
bulk_disable_users()
bulk_enable_users()
bulk_reset_users_data_usage()

create_user_in_all_groups()
```

مدل‌های عمومی:

```text
UserCreate
UserModify
UserResponse
UsersResponse
```

نمونه SDK:

```python
users = await api.get_users(
    token=token,
    offset=0,
    limit=50,
    status=UserStatus.ACTIVE,
    load_sub=True,
)
```

فیلدهای استفاده‌شده در SDK:

```text
user.id
user.username
user.used_traffic
user.subscription_url
user.hwid_limit
```

## نکته versioning

برای خواندن user جدید، endpoint ID-based را در نسخه‌هایی که پشتیبانی می‌کنند ترجیح بده:

```http
/api/user/by-id/{user_id}
```

و compatibility برای:

```http
/api/user/{username}
```

را فقط در نسخه‌هایی نگه دار که هنوز آن endpoint را ارائه می‌کنند.

---

# 6. User Traffic

فیلد:

```text
used_traffic
```

مصرف کلی user را نشان می‌دهد.

این فیلد **به‌تنهایی مصرف دستگاه‌ها را مشخص نمی‌کند**.

پس:

```text
User total traffic ≠ Device traffic
```

Sonnet نباید مصرف هر دستگاه را از تقسیم یا تخمین `used_traffic` محاسبه کند.

---

# 7. HWID / Devices API

این بخش برای پروژه‌ای که نیاز به دستگاه‌های متصل دارد بسیار مهم است.

سورس رسمی Panel در تست‌های API صراحتاً این endpointها را نشان می‌دهد:

## List user HWIDs

```http
GET /api/user/{user_id}/hwids
```

Response مورد استفاده در تست:

```json
{
  "count": 1,
  "hwids": [
    {
      "hwid": "...",
      "device_os": "iOS",
      "os_version": "16.5",
      "device_model": "iPhone 14"
    }
  ]
}
```

## Delete one HWID

```http
DELETE /api/user/{user_id}/hwids/{hwid}
```

## Reset all HWIDs

```http
POST /api/user/{user_id}/hwids/reset
```

تست رسمی همچنین نشان می‌دهد که subscription با headerهای زیر HWID را ثبت می‌کند:

```http
X-HWID: <device-id>
X-Device-OS: <OS>
X-Ver-OS: <OS-version>
X-Device-Model: <model>
```

پس مدل داده دستگاه حداقل شامل این موارد است:

```text
hwid
device_os
os_version
device_model
```

و در source database مدل `UserHWID` همچنین:

```text
last_used_at
```

دارد.

### نتیجه مهم

اکنون می‌توان با اطمینان گفت PasarGuard برای user، اطلاعات HWID/device را نگه می‌دارد.

اما:

```text
HWID/device registration
```

با:

```text
device traffic usage
```

یکی نیست.

وجود `last_used_at` نیز به معنی وجود traffic per device نیست.

---

# 8. HWID Limit

تست رسمی Panel نشان می‌دهد:

```text
hwid_limit
```

برای user وجود دارد.

اگر limit تعیین نشده باشد، fallback limit می‌تواند توسط تنظیمات global اعمال شود.

در تست:

```text
fallback_limit = 3
```

و چهارمین device با:

```http
403 Forbidden
```

و detail:

```text
Device limit reached
```

رد می‌شود.

همچنین در حالت forced:

```text
HWID header required
```

در صورت نبود header می‌تواند خطا ایجاد شود.

**مقدار fallback پیش‌فرض را در کد application hard-code نکن؛ از تنظیمات/نسخه واقعی Panel بخوان.**

---

# 9. HWID Registration Flow

منطق تست رسمی:

```text
Client
  |
  | GET subscription
  | X-HWID
  | X-Device-OS
  | X-Ver-OS
  | X-Device-Model
  v
PasarGuard
  |
  +--> register/update UserHWID
  |
  +--> check HWID limit
  |
  +--> return subscription
```

ثبت HWID موجود دوباره باعث ایجاد duplicate row نمی‌شود؛ رکورد قبلی update می‌شود و `last_used_at` به‌روزرسانی می‌شود.

---

# 10. Admin API

SDK:

```text
get_current_admin()
create_admin()
get_admins()
modify_admin()
remove_admin()
```

مدل‌ها:

```text
AdminCreate
AdminModify
AdminDetails
```

---

# 11. Admin Roles

در تست رسمی Panel، endpointهای role به شکل زیر استفاده شده‌اند:

```http
POST /api/admin-role
```

و:

```http
DELETE /api/admin-role/{role_id}
```

Role payload شامل ساختارهایی برای:

```text
permissions
limits
features
access
hwid
```

است.

ساختار `hwid` در تست:

```json
{
  "mode": "disabled | use_global | override",
  "forced": false,
  "fallback_limit": 2
}
```

مقادیر فوق از تست رسمی استخراج شده‌اند؛ آن‌ها را برای نسخه‌هایی که ساختار role متفاوت دارند تعمیم نده.

---

# 12. Nodes

SDK public methods:

```text
create_node()
get_nodes()
realtime_node_stats()
sync_node()
reconnect_node()
```

مدل‌ها:

```text
NodeCreate
NodeModify
NodeResponse
```

نمونه:

```python
stats = await api.realtime_node_stats(
    node_id=1,
    token=token,
)
```

فیلدهای نمونه:

```text
cpu_usage
mem_used
```

---

# 13. Groups

SDK:

```text
create_group()
get_all_groups()
modify_group()
remove_group()
```

مدل‌ها:

```text
GroupCreate
GroupModify
GroupResponse
```

در نسخه‌های جدید Panel تغییرات validation و role-based access برای groups نیز اعمال شده است؛ بنابراین integration باید version-aware باشد.

---

# 14. Hosts

SDK:

```text
create_host()
get_hosts()
modify_host()
remove_host()
```

مدل‌ها:

```text
CreateHost
BaseHost
```

نسخه‌های جدید ممکن است schemaهای host متفاوتی داشته باشند؛ schema دقیق باید از OpenAPI/source همان نسخه خوانده شود.

---

# 15. Core

SDK:

```text
create_core_config()
get_all_cores()
restart_core()
```

مدل‌ها:

```text
CoreCreate
CoreResponse
```

Enum:

```text
CoreType
```

---

# 16. Templates

SDK:

```text
create_user_template()
create_client_template()
```

مدل‌ها و endpointهای دقیق را از implementation نسخه هدف استخراج کن.

---

# 17. Subscription

SDK:

```text
user_subscription_info()
user_subscription_with_client_type()
```

مدل:

```text
SubscriptionUserResponse
```

Enum:

```text
ConfigFormat
```

نمونه:

```python
info = await api.user_subscription_info(
    token=subscription_token
)

links = await api.get_user_subscription_with_client_type(
    token=subscription_token,
    client_type=ConfigFormat.LINKS,
)
```

**Subscription token با admin access token یکی فرض نشود.**

---

# 18. Settings

SDK:

```text
get_settings()
modify_settings()
```

مدل:

```text
SettingsSchema
```

---

# 19. System

SDK:

```text
get_system_stats()
get_workers_health()
```

این بخش برای health و وضعیت runtime سیستم است.

---

# 20. Usage / Realtime

SDK feature list صراحتاً موارد زیر را اعلام می‌کند:

```text
Usage metrics
Realtime node stats
Inbound details
Worker health
```

اما این عبارت‌ها به‌تنهایی endpointهای REST را مشخص نمی‌کنند.

برای integration نهایی:

```text
OpenAPI
+
SDK implementation
+
Panel source
```

باید با هم تطبیق داده شوند.

---

# 21. Device Usage — نتیجه دقیق

### قابل تأیید

PasarGuard دارای:

```text
UserHWID
hwid
device_os
os_version
device_model
last_used_at
hwid_limit
```

است.

همچنین:

```http
GET /api/user/{user_id}/hwids
DELETE /api/user/{user_id}/hwids/{hwid}
POST /api/user/{user_id}/hwids/reset
```

در تست رسمی وجود دارند.

### قابل تأیید نیست

این موارد را نباید بدون source/OpenAPI فرض کرد:

```text
GET /api/user/{id}/hwids/{hwid}/traffic
GET /api/user/{id}/device-usage
GET /api/user/{id}/hwids/stats
```

همچنین:

```text
last_used_at
```

نباید به عنوان حجم مصرف تلقی شود.

### نتیجه عملی

برای نمایش:

```text
دستگاه‌های متصل به کانفیگ
```

می‌توان از HWID API استفاده کرد.

برای:

```text
مصرف هر دستگاه
```

باید یک منبع traffic با mapping به HWID پیدا شود. اگر Panel چنین mappingی را ارائه نکند، API معمولی user traffic برای محاسبه دقیق per-device کافی نیست.

---

# 22. Pagination

SDK نشان می‌دهد endpointهای list معمولاً از:

```text
offset
limit
```

استفاده می‌کنند.

نمونه:

```python
page = await api.get_users(
    token=token,
    offset=0,
    limit=100,
)
```

Response دارای:

```text
users
total
```

است.

برای endpointهای دیگر، فقط زمانی pagination اضافه کن که schema همان endpoint آن را تأیید کند.

---

# 23. Error Handling

SDK از `httpx` استفاده می‌کند.

HTTP error:

```python
httpx.HTTPStatusError
```

Network error:

```python
httpx.RequestError
```

نمونه:

```python
try:
    user = await api.get_user(
        "customer-1001",
        token=token,
    )
except httpx.HTTPStatusError as exc:
    print(exc.response.status_code)
    print(exc.response.text)
except httpx.RequestError as exc:
    print(exc)
```

Status codeهایی که مستقیماً در HWID tests تأیید شده‌اند:

```text
200 OK
201 Created
403 Forbidden
```

برای جدول کامل status codeها باید OpenAPI نسخه هدف بررسی شود.

---

# 24. Version Compatibility Matrix

| قابلیت | v4 | v5 | وضعیت فعلی |
|---|---|---|---|
| Username-based user API | قدیمی | deprecated/migration | برای integration جدید توصیه نمی‌شود |
| ID-based user API | بسته به نسخه | `/api/user/by-id/{user_id}` | مسیر فعلی معرفی‌شده |
| Future ID route | — | اعلام شده | `/api/user/{id}` |
| HWID | نسخه‌محور | توسعه‌یافته | source رسمی تأیید می‌کند |
| User HWID list | version-dependent | موجود در source فعلی | `/api/user/{id}/hwids` |
| HWID delete | version-dependent | موجود در source فعلی | `/api/user/{id}/hwids/{hwid}` |
| HWID reset | version-dependent | موجود در source فعلی | `/api/user/{id}/hwids/reset` |
| User list `no_group` filter | — | در v5.3.0 اضافه شده | version-specific |
| Bulk group `has_no_group` filter | — | در v5.3.0 اضافه شده | version-specific |

---

# 25. نمونه تغییرات v5.3.0

طبق release رسمی v5.3.0:

```text
users:
    no_group filter added to users list endpoint

bulk-groups:
    has_no_group filter added

groups:
    validation/role access improvements

subscription:
    dynamic URL formatting for announcements

xray:
    cipherSuites for unsafe fingerprint
```

بنابراین integration نباید فرض کند همه فیلترهای UI/API در نسخه‌های قدیمی وجود دارند.

---

# 26. VLESS Flow Migration

طبق اعلام رسمی migration:

### قدیمی

```text
vless.flow
```

### جدید

```text
core_config.inbound.settings.flow
```

در نسخه‌های جدید باید از ساختار جدید استفاده شود.

---

# 27. Public SDK API

SDK متدهای اصلی زیر را اعلام می‌کند:

```text
Authentication
- get_token()
- admin_token()

Users
- create_user()
- get_user()
- get_users()
- modify_user()
- remove_user()

User bulk
- bulk_delete_users()
- bulk_disable_users()
- bulk_enable_users()
- bulk_reset_users_data_usage()

Admins
- get_current_admin()
- create_admin()
- get_admins()
- modify_admin()
- remove_admin()

Nodes
- create_node()
- get_nodes()
- realtime_node_stats()
- sync_node()
- reconnect_node()

Groups
- create_group()
- get_all_groups()
- modify_group()
- remove_group()

Hosts
- create_host()
- get_hosts()
- modify_host()
- remove_host()

Core
- create_core_config()
- get_all_cores()
- restart_core()

Templates
- create_user_template()
- create_client_template()

Subscriptions
- user_subscription_info()
- user_subscription_with_client_type()

Settings/System
- get_settings()
- modify_settings()
- get_system_stats()
- get_workers_health()
```

---

# 28. Models

مدل‌های عمومی SDK:

```text
UserCreate
UserModify
UserResponse
UsersResponse

AdminCreate
AdminModify
AdminDetails

NodeCreate
NodeModify
NodeResponse

GroupCreate
GroupModify
GroupResponse

CreateHost
BaseHost

CoreCreate
CoreResponse

SettingsSchema
SubscriptionUserResponse
```

Enums:

```text
UserStatus
Period
ConfigFormat
DataLimitResetStrategy
NodeStatus
NodeConnectionType
CoreType
```

---

# 29. Helpers

SDK:

```text
Tools.mb()
Tools.gb()
Tools.tb()

Tools.minutes()
Tools.hours()
Tools.days()
Tools.to_timestamp()

Tools.to_bytes()
Tools.random_username()
```

نمونه:

```python
Tools.gb(20)
Tools.days(30)
Tools.to_bytes("500MB")
Tools.to_timestamp("12h")
```

---

# 30. Implementation Rules for Sonnet

Sonnet باید این قوانین را رعایت کند:

1. API client را با architecture جدا از business logic پیاده‌سازی کن.
2. Base URL از configuration خوانده شود.
3. Token در configuration ثابت ذخیره نشود.
4. Bearer token برای Panel API استفاده شود.
5. User identity را ترجیحاً با numeric ID نگه دار.
6. username را فقط برای compatibility نگه دار.
7. نسخه API را در adapter/version layer مدیریت کن.
8. endpointهای deprecated را با current endpointها قاطی نکن.
9. HWID را از traffic جدا نگه دار.
10. `last_used_at` را traffic فرض نکن.
11. برای per-device traffic هیچ محاسبه تخمینی انجام نده.
12. اگر endpoint یا field در source/OpenAPI تأیید نشده، `UNVERIFIED` علامت بزن.
13. schemaهای request/response را از Pydantic/OpenAPI استخراج کن.
14. برای endpointهای list فقط در صورت وجود contract از pagination استفاده کن.
15. status codeها را حدس نزن.
16. برای نسخه‌های مختلف compatibility adapter ایجاد کن.
17. migrationهای رسمی PasarGuard را در adapter لحاظ کن.
18. APIهای ID-based را برای integration جدید ترجیح بده.
19. هیچ API داخلی database را جایگزین REST API نکن مگر اینکه صراحتاً درخواست شده باشد.
20. اگر API رسمی قابلیت موردنظر را ندارد، به‌جای ساختن endpoint جعلی، محدودیت را گزارش کن.

---

# 31. ساختار پیشنهادی Adapter

```text
PasarGuardClient
│
├── AuthenticationService
├── UserService
├── HwidService
├── SubscriptionService
├── NodeService
├── GroupService
├── HostService
├── AdminService
├── CoreService
├── TemplateService
├── SettingsService
└── SystemService
```

و برای version-specific behavior:

```text
PasarGuardApiAdapter
├── V4Adapter
├── V5Adapter
└── FutureAdapter
```

یا بهتر:

```text
PasarGuardCapabilities
├── supports_id_user_endpoint
├── supports_hwid
├── supports_no_group_filter
├── supports_bulk_group_no_group
└── ...
```

---

# 32. ممنوع برای Sonnet

هرگز این کارها انجام نشود:

```text
حدس زدن URL از روی نام متد
حدس زدن HTTP method
حدس زدن JSON schema
حدس زدن status code
حدس زدن traffic per device
فرض کردن همه نسخه‌ها API یکسان دارند
استفاده از username به عنوان تنها identity
hard-code کردن endpointهای deprecated
```

---

# 33. Verification Levels

در implementation هر API را با یکی از این وضعیت‌ها علامت بزن:

```text
VERIFIED_OFFICIAL_SOURCE
```

یعنی مستقیماً در source رسمی Panel/test تأیید شده.

```text
VERIFIED_SDK
```

یعنی در SDK قابل استفاده است ولی exact REST contract هنوز باید با OpenAPI تطبیق داده شود.

```text
VERSION_SPECIFIC
```

یعنی فقط برای نسخه یا بازه مشخصی تأیید شده.

```text
DEPRECATED
```

یعنی منسوخ شده یا در مسیر حذف است.

```text
UNVERIFIED
```

یعنی نباید در production implementation استفاده شود تا source/OpenAPI آن بررسی شود.

---

# 34. نکته نهایی درباره Device Usage

اگر پروژه مقصد نیاز دارد:

```text
User
  └── Config
       ├── Device A → traffic
       ├── Device B → traffic
       └── Device C → traffic
```

دو مرحله جدا وجود دارد:

### مرحله A — Devices

از HWID:

```http
GET /api/user/{user_id}/hwids
```

اطلاعات دستگاه‌ها قابل دریافت است.

### مرحله B — Traffic per Device

باید مشخص شود که Panel/Node آیا traffic را با HWID قابل ارتباط می‌کند یا خیر.

اگر فقط user-level traffic موجود باشد:

```text
user.used_traffic
```

نمی‌توان مصرف Device A/B/C را دقیق محاسبه کرد.

**هیچ نسبت یا تخمینی نباید ساخته شود.**

---

# 35. نتیجه

این سند برای integration چندنسخه‌ای طراحی شده است، نه یک نسخه خاص.

منابع فعلی نشان می‌دهند SDK اصلی حوزه‌های گسترده‌ای از API را پوشش می‌دهد، و سورس رسمی Panel نیز تغییرات version-specific، APIهای ID-based و HWID workflow را قابل مشاهده می‌کند.

برای استخراج **100٪ کامل تمام REST endpointها با METHOD + PATH + REQUEST + RESPONSE**، مرحله بعدی باید استخراج OpenAPI/source هر نسخه هدف باشد؛ این اطلاعات نباید از نام متدهای SDK حدس زده شوند.

## منابع

- `https://github.com/AmirKenzo/PasarguardBot`
- `https://github.com/AmirKenzo/pasarguard_api`
- `https://github.com/PasarGuard/panel`
- `https://github.com/PasarGuard/panel/discussions/457`
- `https://github.com/PasarGuard/panel/releases`
- `https://github.com/PasarGuard/panel/blob/main/tests/api/test_hwid.py`
- `https://github.com/alirezax5/pasarguard-api-php`

## وضعیت اعتبار

این فایل عمدتاً بر مبنای source و تست‌های قابل مشاهده تنظیم شده است. مواردی که exact REST contract آن‌ها از منبع مستقیم قابل اثبات نبوده‌اند عمداً به‌عنوان endpoint قطعی ارائه نشده‌اند.
