mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-08-23 03:16:52 +00:00
Added docs (small version)
This commit is contained in:
parent
7a57b31ff3
commit
cb9c1f032d
1 changed files with 366 additions and 0 deletions
366
docs/docs.md
Normal file
366
docs/docs.md
Normal file
|
@ -0,0 +1,366 @@
|
|||
# X-UI API Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides instructions for interacting with the X-UI panel API. The API allows for programmatic management of inbounds (connections), users, and server settings.
|
||||
|
||||
### Authentication
|
||||
|
||||
The API uses a **cookie-based session** for authentication.
|
||||
|
||||
1. You must first send a `POST` request to the `/login` endpoint with your credentials.
|
||||
2. If successful, the server will respond with a `Set-Cookie` header containing a session cookie (e.g., `session=...`).
|
||||
3. Your HTTP client **must** store this cookie and include it in the `Cookie` header for all subsequent API requests.
|
||||
|
||||
While many headers sent by a browser are not strictly required, including a `User-Agent` and `Referer` is good practice to better emulate a real client.
|
||||
|
||||
## Endpoints
|
||||
|
||||
### 1. Login
|
||||
|
||||
Authenticates the user and initiates a session by returning a session cookie.
|
||||
|
||||
* **Endpoint:** `POST {base_url}/login`
|
||||
* **Body:** `application/x-www-form-urlencoded`
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| :--------- | :----- | :--------------------- |
|
||||
| `username` | string | Your panel username. |
|
||||
| `password` | string | Your panel password. |
|
||||
|
||||
* **Success Response (200 OK):**
|
||||
* The response will include a `Set-Cookie` header in the HTTP response.
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"msg": "Login successful",
|
||||
"obj": null
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Get All Inbounds
|
||||
|
||||
Fetches a list of all configured inbound connections.
|
||||
|
||||
* **Endpoint:** `POST {base_url}/panel/inbound/list`
|
||||
* **Body:** None
|
||||
* **Success Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"msg": "",
|
||||
"obj": [
|
||||
{
|
||||
"id": 1,
|
||||
"up": 40912424334,
|
||||
"down": 537061968966,
|
||||
"total": 0,
|
||||
"remark": "My-First-Inbound",
|
||||
"enable": true,
|
||||
"expiryTime": 0,
|
||||
"listen": "YOUR_SERVER_IP",
|
||||
"port": 19271,
|
||||
"protocol": "vless",
|
||||
"settings": "{\"clients\":[{\"id\":\"user-uuid-goes-here\",\"email\":\"user-email-goes-here\",...}]}",
|
||||
"streamSettings": "{\"network\":\"tcp\",\"security\":\"reality\",\"realitySettings\":{\"privateKey\":\"REALITY_PRIVATE_KEY\",\"settings\":{\"publicKey\":\"REALITY_PUBLIC_KEY\"},...}}",
|
||||
"tag": "inbound-YOUR_SERVER_IP:19271",
|
||||
"sniffing": "{\"enabled\":false,...}"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Get Online Clients
|
||||
|
||||
Fetches a list of emails corresponding to currently online clients.
|
||||
|
||||
* **Endpoint:** `POST {base_url}/panel/inbound/onlines`
|
||||
* **Body:** None
|
||||
* **Success Response (200 OK):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"msg": "",
|
||||
"obj": [
|
||||
"client1-email",
|
||||
"online-user@example.com"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Get New Reality Certificate
|
||||
|
||||
Generates a new X25519 key pair for use with VLESS Reality.
|
||||
|
||||
* **Endpoint:** `POST {base_url}/server/getNewX25519Cert`
|
||||
* **Body:** None
|
||||
* **Success Response (200 OK):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"msg": "",
|
||||
"obj": {
|
||||
"privateKey": "a_very_long_private_key_string",
|
||||
"publicKey": "a_shorter_public_key_string"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Add VLESS Reality Inbound
|
||||
|
||||
Creates a new VLESS Reality inbound connection.
|
||||
|
||||
* **Endpoint:** `POST {base_url}/panel/inbound/add`
|
||||
* **Body:** `application/x-www-form-urlencoded`
|
||||
|
||||
This endpoint requires a complex body where several parameters are URL-encoded JSON strings.
|
||||
|
||||
| Parameter | Description | Example Value |
|
||||
| :--------------- | :------------------------------------------------------------------------------ | :--------------------------------------------- |
|
||||
| `remark` | A name or comment for the inbound. | `My-Test-Key` |
|
||||
| `listen` | The server IP address to listen on. Leave empty for all IPs. | `YOUR_SERVER_IP` |
|
||||
| `port` | The port to listen on. `0` for a random port. | `48673` |
|
||||
| `protocol` | The protocol type. | `vless` |
|
||||
| `expiryTime` | Expiration timestamp in milliseconds. `0` for no expiration. | `1753969593148` |
|
||||
| `total` | Data limit in bytes. `0` for unlimited. | `0` |
|
||||
| `settings` | URL-encoded JSON string with client details (UUID, email, etc.). | (See structure below) |
|
||||
| `streamSettings` | URL-encoded JSON string with transport and security settings (e.g., Reality). | (See structure below) |
|
||||
| `sniffing` | URL-encoded JSON string for traffic sniffing settings. | `{"enabled":false,...}` |
|
||||
|
||||
* **Decoded `settings` Structure:**
|
||||
```json
|
||||
{
|
||||
"clients": [
|
||||
{
|
||||
"id": "a-generated-uuid",
|
||||
"email": "a-generated-email",
|
||||
"enable": true,
|
||||
"flow": "",
|
||||
"limitIp": 0,
|
||||
"totalGB": 0,
|
||||
"expiryTime": 0,
|
||||
"subId": "a-generated-sub-id"
|
||||
}
|
||||
],
|
||||
"decryption": "none",
|
||||
"fallbacks": []
|
||||
}
|
||||
```
|
||||
* **Decoded `streamSettings` Structure:**
|
||||
```json
|
||||
{
|
||||
"network": "tcp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"dest": "example.com:443",
|
||||
"serverNames": ["example.com", "www.example.com"],
|
||||
"privateKey": "THE_PRIVATE_KEY_FROM_STEP_4",
|
||||
"publicKey": "THE_PUBLIC_KEY_FROM_STEP_4",
|
||||
"shortIds": ["generated_id1", "generated_id2"],
|
||||
"fingerprint": "chrome",
|
||||
"spiderX": "/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **Success Response (200 OK):** The response object contains the full configuration of the newly created inbound.
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"msg": "Create Successfully",
|
||||
"obj": {
|
||||
"id": 16,
|
||||
"remark": "Test test",
|
||||
"port": 48673,
|
||||
"listen": "YOUR_SERVER_IP",
|
||||
"settings": "{\"clients\":[{\"id\":\"60f3a042-7f0c-43a5-a9e6-de76f66703dd\",...}]}",
|
||||
"streamSettings": "{\"network\":\"tcp\",\"security\":\"reality\",\"realitySettings\":{...}}",
|
||||
// ... and other fields
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Code Examples
|
||||
|
||||
### Python (`requests`)
|
||||
|
||||
The `requests.Session` object is perfect for this task as it automatically handles cookies across requests.
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
# --- Configuration ---
|
||||
BASE_URL = "http://127.0.0.1:PORT/YOUR_SECRET_PATH"
|
||||
USERNAME = "your_username"
|
||||
PASSWORD = "your_password"
|
||||
|
||||
# 1. Create a session that will store cookies
|
||||
session = requests.Session()
|
||||
|
||||
# 2. Login to establish the session
|
||||
try:
|
||||
login_url = f"{BASE_URL}/login"
|
||||
login_data = {"username": USERNAME, "password": PASSWORD}
|
||||
response = session.post(login_url, data=login_data)
|
||||
response.raise_for_status()
|
||||
|
||||
if response.json().get("success"):
|
||||
print("Login successful!")
|
||||
|
||||
# 3. Now you can make other API calls with the same session
|
||||
inbounds_url = f"{BASE_URL}/panel/inbound/list"
|
||||
inbounds_response = session.post(inbounds_url)
|
||||
inbounds_data = inbounds_response.json()
|
||||
|
||||
print(f"Successfully fetched {len(inbounds_data.get('obj', []))} inbounds.")
|
||||
else:
|
||||
print(f"Login failed: {response.json().get('msg')}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"An error occurred: {e}")
|
||||
```
|
||||
|
||||
### Node.js (`axios`)
|
||||
|
||||
In Node.js, `axios` does not handle cookies by default. You need to use a cookie jar helper library like `axios-cookiejar-support` and `tough-cookie`.
|
||||
|
||||
First, install the dependencies:
|
||||
`npm install axios axios-cookiejar-support tough-cookie`
|
||||
|
||||
```javascript
|
||||
const axios = require('axios');
|
||||
const { HttpsCookieAgent } = require('http-cookie-agent/http');
|
||||
const tough = require('tough-cookie');
|
||||
|
||||
// --- Configuration ---
|
||||
const BASE_URL = 'http://127.0.0.1:PORT/YOUR_SECRET_PATH';
|
||||
const USERNAME = 'your_username';
|
||||
const PASSWORD = 'your_password';
|
||||
|
||||
async function main() {
|
||||
// 1. Create a cookie jar to store session cookies
|
||||
const cookieJar = new tough.CookieJar();
|
||||
|
||||
// 2. Create an axios instance that uses the cookie jar
|
||||
const apiClient = axios.create({
|
||||
httpAgent: new HttpsCookieAgent({ cookies: { jar: cookieJar } }),
|
||||
httpsAgent: new HttpsCookieAgent({ cookies: { jar: cookieJar } }),
|
||||
});
|
||||
|
||||
try {
|
||||
// 3. Login
|
||||
console.log('Attempting to log in...');
|
||||
const loginUrl = `${BASE_URL}/login`;
|
||||
// For x-www-form-urlencoded, use a URLSearchParams object
|
||||
const loginData = new URLSearchParams({
|
||||
username: USERNAME,
|
||||
password: PASSWORD
|
||||
});
|
||||
|
||||
const loginResponse = await apiClient.post(loginUrl, loginData);
|
||||
|
||||
if (loginResponse.data.success) {
|
||||
console.log('Login successful!');
|
||||
|
||||
// 4. Make another request. The cookie is sent automatically.
|
||||
const inboundsUrl = `${BASE_URL}/panel/inbound/list`;
|
||||
const inboundsResponse = await apiClient.post(inboundsUrl);
|
||||
|
||||
if (inboundsResponse.data.success) {
|
||||
console.log(`Successfully fetched ${inboundsResponse.data.obj.length} inbounds.`);
|
||||
} else {
|
||||
console.error('Failed to fetch inbounds:', inboundsResponse.data.msg);
|
||||
}
|
||||
} else {
|
||||
console.error('Login failed:', loginResponse.data.msg);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('An API error occurred:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
### Browser JavaScript (`fetch`)
|
||||
|
||||
In a web browser context, `fetch` can automatically handle cookies if the request is to the same origin, or if you specify `credentials: 'include'` for cross-origin requests.
|
||||
|
||||
```javascript
|
||||
// --- Configuration ---
|
||||
const BASE_URL = 'http://127.0.0.1:PORT/YOUR_SECRET_PATH';
|
||||
const USERNAME = 'your_username';
|
||||
const PASSWORD = 'your_password';
|
||||
|
||||
async function runApiFlow() {
|
||||
try {
|
||||
// 1. Login
|
||||
console.log('Logging in...');
|
||||
const loginResponse = await fetch(`${BASE_URL}/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
username: USERNAME,
|
||||
password: PASSWORD
|
||||
}),
|
||||
// This is crucial for the browser to store and send cookies
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
const loginResult = await loginResponse.json();
|
||||
if (!loginResult.success) {
|
||||
throw new Error(`Login failed: ${loginResult.msg}`);
|
||||
}
|
||||
console.log('Login successful!');
|
||||
|
||||
// 2. Fetch inbounds. The browser automatically includes the cookie.
|
||||
const inboundsResponse = await fetch(`${BASE_URL}/panel/inbound/list`, {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
const inboundsResult = await inboundsResponse.json();
|
||||
if (inboundsResult.success) {
|
||||
console.log(`Found ${inboundsResult.obj.length} inbounds.`);
|
||||
} else {
|
||||
throw new Error(`Failed to fetch inbounds: ${inboundsResult.msg}`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('API Flow Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
runApiFlow();
|
||||
```
|
||||
|
||||
## Generating the VLESS URL
|
||||
|
||||
After creating an inbound using the `/panel/inbound/add` endpoint, you can construct a standard `vless://` URL from the `obj` field in the JSON response.
|
||||
|
||||
The URL format is:
|
||||
`vless://{UUID}@{ADDRESS}:{PORT}?{PARAMETERS}#{REMARK}`
|
||||
|
||||
Here is how to map the JSON response fields to the URL components:
|
||||
|
||||
| URL Part | JSON Path from `obj` | Example |
|
||||
| :---------- | :-------------------------------------------------------------- | :---------------------------------------------- |
|
||||
| `UUID` | `settings.clients[0].id` (after JSON parsing) | `60f3a042-7f0c-43a5-a9e6-de76f66703dd` |
|
||||
| `ADDRESS` | `listen` (or your server's domain name) | `YOUR_SERVER_IP` |
|
||||
| `PORT` | `port` | `48673` |
|
||||
| `REMARK` | `remark` (URL-encoded) | `Test%20test` |
|
||||
|
||||
**Parameters (in the query string):**
|
||||
|
||||
| Parameter | JSON Path from `obj` | Description |
|
||||
| :-------- | :-------------------------------------------------------------- | :---------------------------------------------- |
|
||||
| `type` | `streamSettings.network` | Transport protocol, e.g., `tcp`. |
|
||||
| `security` | `streamSettings.security` | Security layer, e.g., `reality`. |
|
||||
| `pbk` | `streamSettings.realitySettings.settings.publicKey` | The public key for Reality. |
|
||||
| `fp` | `streamSettings.realitySettings.settings.fingerprint` | The browser fingerprint, e.g., `chrome`. |
|
||||
| `sni` | `streamSettings.realitySettings.serverNames[0]` | The Server Name Indication to use. |
|
||||
| `sid` | `streamSettings.realitySettings.shortIds[0]` | The first short ID from the list. |
|
||||
| `spx` | `streamSettings.realitySettings.settings.spiderX` | The SpiderX path. |
|
Loading…
Reference in a new issue