14 KiB
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.
- You must first send a
POST
request to the/login
endpoint with your credentials. - If successful, the server will respond with a
Set-Cookie
header containing a session cookie (e.g.,session=...
). - 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.
{ "success": true, "msg": "Login successful", "obj": null }
- The response will include a
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):
{ "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):
{ "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):
{ "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:{ "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:{ "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.
{ "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.
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
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.
// --- 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. |