Local configuration HTTP API
Trusted local tools can reuse the desktop app’s configuration parser, compiler, installed GeoData, and libXray validation. No separate CLI is required. The API does not import or save assets, change settings, download dependencies, or start and stop VPN.
Enable and authenticate
Open Advanced → Xray → Local API, enable it, and save. It is off by default and available only on desktop. The app must remain running and finish service preparation; hiding its window is fine, but quitting the app stops the API even if VPN stays connected.
The default address is http://127.0.0.1:18587. Choose a port from 1024 to 65535. It listens only on IPv4 loopback, never a LAN address. Automatic Xray SOCKS/metrics ports avoid the saved API port even while the API is disabled. User-written inbound ports are not rewritten.
Copy the Token from the app into a trusted local tool’s protected credential storage. Every request requires Authorization: Bearer <token>. The Token survives restarts; resetting it immediately revokes the old value. Disabling the API retains it. Clearing app data removes it, and connection backups do not contain it.
Do not put the Token in an AI prompt, URL, command-line argument, source repository, or log. Configure credentials separately from the text you ask an AI to generate. Connect directly to the displayed loopback address, bypass environment proxies, and disable redirects. Browser-origin requests and cross-origin access are not supported. Authentication is not protection against malware already controlling your account.
API version 1
| Method and path | Result |
|---|---|
GET /api/v1/info |
API, app, and Core versions; host platform and supported configuration kinds |
POST /api/v1/config/validate |
App parsing and validation projection, followed by libXray configuration validation |
POST /api/v1/config/compile |
Generated runtime configuration preview, without kernel validation or execution |
POST bodies use Content-Type: application/json and are limited to 16 MiB. Supply the original configuration as a text string, not a parsed/re-encoded object, so diagnostic positions refer to the original input.
{
"kind": "raw",
"text": "{\n \"name\": \"Direct example\",\n \"outbounds\": [{\"protocol\": \"freedom\", \"tag\": \"direct\"}]\n}"
}This example has no proxy credentials and uses direct access; it is not a supplied VPN server.
kind |
Meaning of text |
|---|---|
outbound |
One outbound object, as in the node editor; not a document wrapping outbounds |
routing |
Ordinary Custom Routing with empty entry slots |
advanced-routing |
Advanced Custom JSON within that template’s field boundaries |
raw |
A complete Raw JSON configuration |
An optional name follows the selected input type’s naming rules; do not confuse a configuration name with an outbound tag. validate rejects options and extra outbounds. Routing validation uses placeholder outbounds, not your actual selected nodes.
Compile a preview
For compile, include kind, text, and an explicit options object:
{
"platform": "macos",
"sessionDirectory": "/explicit/preview-directory",
"metricsPort": 19001,
"socksPort": 19002,
"ipv6": true
}platform:ios,macos,android,windows, orlinux. This is a configuration target, not a request to run remotely.- Windows also needs
windowsMode: "exe"or"msix". Windows/Linux requireinterfaceName. routingandadvanced-routingalso need a top-leveloutboundsarray containing actual nodes, one per empty entry slot.outboundandrawuse their own nodes and reject an extra array.- Optional
tunDnsIpv4Address,tunDnsIpv6Address,logEnabled,logFilesSupported,logLevel,dnsLog, andmaskAddressfollow the compiler’s defaults when omitted; they do not inherit the user’s current connection settings. - GeoData paths refer to this app’s installed directory. Cross-platform output does not make those paths available on another device. Compilation does not check free ports or existing interfaces, create the session directory, or write the active configuration.
Read the result correctly
Check both status (passed, failed, notRun) and stage (input, compile, kernel). HTTP 200 does not mean validation passed, and passed at compile means only that a preview was generated.
Diagnostics contain a code and message, with path, offset, line, or column only when reliable. Offsets start at 0; lines and columns start at 1. Offsets and columns count UTF-16 code units. A path is an array such as ["routing", "rules", 0, "domain"]. Do not infer a source position from an unlocated Core error or from generated JSON.
validationConfig and compiledConfig are JSON text and may contain credentials. Protect saved results. Read limitations before claiming success. A busy request returns 409, an oversized request 413, and unavailable service 503; none means the configuration passed.
Validation constructs and closes a Core instance without starting VPN. It can have process-level side effects and is not a sandbox for untrusted configurations. It does not download missing GeoData, check database name/quantity constraints, prove the actual node combination, or guarantee startup and connectivity. A client timeout does not cancel native validation: do not automatically retry it.