1. Basic information
All endpoints use this base path:
/soloip/api/v1Request headers:
Authorization: Bearer <API_TOKEN>
Content-Type: application/json- Find or reset
API_TOKENin the SoloIP API settings page. - Business endpoints accept JSON request bodies unless an endpoint says otherwise.
- HTTP
200means the request was handled; inspectmsg,data, orerrorfor the business result. - An endpoint that is not exposed to the public API returns
403 API_ENDPOINT_NOT_ALLOWED.
Common errors:
| HTTP status | Error | Meaning |
|---|---|---|
401 | API Token invalid | The token is missing, malformed, or does not match the device |
403 | API_ACCESS_REQUIRED | API access is not enabled for the license |
403 | API_TRIAL_QUOTA_EXHAUSTED | The API trial quota is exhausted |
403 | API_ENDPOINT_NOT_ALLOWED | This token cannot call the endpoint |
400 | Error text | Request parameters are invalid |
500 | Error text | Server-side execution failed |
2. Common objects and conventions
2.1 Node
{
"id": 1,
"name": "HK-01",
"protocol": "socks5",
"config_json": "{\"server\":\"1.2.3.4\",\"port\":1080}",
"group": "hong-kong",
"created_at": "2026-05-18T10:00:00Z"
}config_json is a protocol-specific JSON string. External tools should use the batch endpoint for stable field updates instead of relying on internal protocol fields.
2.2 VPNLine (L2TP/PPTP)
{
"id": 1,
"type": "l2tp",
"name": "l2tp_1",
"server": "vpn.example.com",
"port": 1701,
"username": "user",
"password": "pass",
"secret": "ipsec-secret",
"interface": "auto",
"comment": "primary line",
"dns_profile": "auto",
"dns_servers": [],
"is_enabled": true,
"is_online": true
}type is l2tp or pptp; is_enabled is the configured switch and is_online means that the system interface currently has an IPv4 address. dns_profile accepts auto, domestic, outbound, return, or custom; custom requires dns_servers.
2.3 Rule
{
"id": 1,
"ip": "192.168.50.100",
"mac": "AA:BB:CC:DD:EE:FF",
"comment": "test device",
"is_enabled": true,
"target_node": "HK-01",
"upload_limit_kbps": 5120,
"download_limit_kbps": 20480,
"created_at": "2026-05-18T10:00:00Z",
"updated_at": "2026-05-18T10:00:00Z"
}Stable target_node forms:
| Form | Example |
|---|---|
| Node name | HK-01 |
| Node group | Group_hong-kong |
| Interface or line | Interface:wan1, Interface:l2tp_1, Interface:pptp_1 |
| Direct or reject | DIRECT, REJECT |
Use the explicit Group_ and Interface: prefixes. Interface: is for routing rules, not proxy-service outbound values.
2.4 ProxyService
{
"id": 1,
"name": "wan1-http",
"outbound_interface": "wan1",
"port": 20001,
"username": "user",
"password": "pass",
"is_enabled": true,
"created_at": "2026-05-18T10:00:00Z"
}outbound_interface uses a bare interface name. The listener port must not conflict with a system-reserved port.
3. System queries
GET /system/status
Returns service state, uptime, version, API access, connections, and memory.
curl -H "Authorization: Bearer soloip_xxx" \
http://192.168.50.1/soloip/api/v1/system/statusPossible status values include running, stopped, and restoring. Automation should primarily use status, hasAPIAccess, connections, and memory.
GET /system/traffic
Returns current connections and memory. up and down are reserved fields and commonly return 0.
{ "up": 0, "down": 0, "connections": 42, "memory": 15728640 }GET /system/interfaces
Returns interfaces that can be used as node outbound paths, including enabled L2TP/PPTP line names.
{ "interfaces": ["wan1", "wan2", "pppoe_0", "l2tp_1", "pptp_1"] }GET /system/interfaces-with-ip
Returns interface names and current IPv4 addresses, useful before creating a proxy service.
{
"interfaces": [
{ "name": "wan1", "ip": "100.64.1.2" },
{ "name": "l2tp_1", "ip": "10.0.0.2" },
{ "name": "pptp_1", "ip": "" }
]
}4. Node management
Endpoint overview
| Method | Path | Purpose |
|---|---|---|
GET | /nodes | List nodes |
POST | /nodes | Add a node |
PUT | /nodes/{id} | Edit a node |
DELETE | /nodes/{id} | Delete a node |
DELETE | /nodes/batch | Delete nodes in bulk |
PATCH | /nodes/batch | Change group, egress, or dedicated DNS |
POST | /nodes/import | Import nodes in bulk |
GET | /nodes/delay | Check one node |
GET | /nodes/delay/all | Check every node |
GET /nodes
Returns { "data": [Node, ...] }.
POST /nodes
{
"name": "HK-01",
"protocol": "socks5",
"config_json": "{\"server\":\"1.2.3.4\",\"port\":1080}",
"group": "hong-kong"
}Response: { "msg": "node added", "id": 1 }.
PUT /nodes/{id}
Send the complete editable node object. The response is { "msg": "node updated", "id": 1 }.
DELETE /nodes/{id}
Response: { "msg": "node deleted", "id": 1 }.
DELETE /nodes/batch
{ "ids": [1, 2, 3] }PATCH /nodes/batch
Changes group, outbound interface, relay, or dedicated DNS for selected IDs.
{
"ids": [1, 2],
"group": "hong-kong",
"interface_name": "wan1",
"dialer_proxy": "",
"node_dns_profile": "custom",
"node_dns_servers": "1.1.1.1,8.8.8.8"
}interface_name and dialer_proxy are mutually exclusive. node_dns_profile=custom requires non-empty node_dns_servers. The response includes the number of updated nodes.
POST /nodes/import
{
"type": "socks5",
"text": "1.2.3.4,1080,user,pass,HK-01\n5.6.7.8,1080,user,pass,HK-02",
"replace": false,
"group": "hong-kong",
"autoNodeName": false,
"autoNodeNameStartIndex": 1
}Supported formats include socks5 (IP,Port,User,Pass[,Name]), ss (IP,Port,Cipher,Password[,Name]), vlessvmess share fields, and the key/value others format. replace=true clears current nodes first. The response includes imported, skipped, and error counts.
GET /nodes/delay
Use ?name=<node-name> to check one node. The response includes latency and diagnostic information when available.
GET /nodes/delay/all
Checks all nodes and returns the per-node result. Treat a saved node without a successful diagnostic as unavailable for a production rule.
Back to section index5. L2TP/PPTP line management
Endpoint overview
| Method | Path | Purpose |
|---|---|---|
GET | /vpn-lines | List lines |
POST | /vpn-lines | Add a line |
PUT | /vpn-lines/{type}/{name} | Edit a line |
PATCH | /vpn-lines/status | Enable or disable lines |
DELETE | /vpn-lines | Delete lines in bulk |
POST | /vpn-lines/import | Import lines in bulk |
GET /vpn-lines
Returns VPNLine objects with is_enabled and is_online.
POST /vpn-lines
{
"type": "l2tp",
"name": "l2tp_1",
"server": "vpn.example.com",
"port": 1701,
"username": "user",
"password": "pass",
"secret": "ipsec-secret",
"interface": "auto",
"comment": "primary line",
"dns_profile": "auto",
"dns_servers": []
}type must be l2tp or pptp; names start with l2tp_ or pptp_ and are at most 15 characters. Default ports are 1701 and 1723. New lines are enabled by default.
PUT /vpn-lines/{type}/{name}
Edits a line. The body may contain a new name, but the type cannot change. A custom DNS profile requires dns_servers.
PATCH /vpn-lines/status
{
"items": [
{ "type": "l2tp", "name": "l2tp_1" },
{ "type": "pptp", "name": "pptp_1" }
],
"is_enabled": false
}DELETE /vpn-lines
Send an items array with type and name for each line.
POST /vpn-lines/import
L2TP lines use server,port,user,pass,secret,name,comment or the form without port. PPTP uses server,port,user,pass,name,comment or the form without port. The response includes imported, skipped, and errors.
6. Routing-rule management
Endpoint overview
| Method | Path | Purpose |
|---|---|---|
GET | /rules | List rules |
POST | /rules | Add a rule |
PUT | /rules/{id} | Edit a rule |
PATCH | /rules/{id}/status | Enable or disable one rule |
DELETE | /rules/{id} | Delete one rule |
DELETE | /rules/batch | Delete rules in bulk |
PATCH | /rules/batch/status | Enable or disable rules in bulk |
PATCH | /rules/batch | Change targets or limits |
PATCH | /rules/batch/limits | Change limits in bulk |
POST | /rules/import | Import rules in bulk |
GET /rules
Returns { "data": [Rule, ...] }.
POST /rules
{
"ip": "192.168.50.100",
"mac": "AA:BB:CC:DD:EE:FF",
"comment": "test device",
"is_enabled": true,
"target_node": "Group_hong-kong",
"upload_limit_kbps": 5120,
"download_limit_kbps": 20480
}PUT /rules/{id}
Edits the address, comment, target, enabled state, and limits. Use a complete body for predictable automation.
PATCH /rules/{id}/status
{ "is_enabled": false }DELETE /rules/{id}
Deletes the rule and cleans its firewall entry.
DELETE /rules/batch
{ "ips": ["192.168.50.100", "192.168.50.101"] }PATCH /rules/batch/status
{ "ips": ["192.168.50.100", "192.168.50.101"], "is_enabled": true }PATCH /rules/batch
Set at least one update_* field to true.
{
"ips": ["192.168.50.100", "192.168.50.101"],
"update_target": true,
"target_node": "Group_hong-kong",
"update_upload": true,
"upload_limit_kbps": 5120,
"update_download": true,
"download_limit_kbps": 20480
}target_node may be a node, Group_<name>, DIRECT, REJECT, or Interface:<ifname>. A limit of 0 means unlimited.
PATCH /rules/batch/limits
Set update_upload and/or update_download with non-negative limit values. At least one update flag must be true.
POST /rules/import
{
"text": "192.168.50.100,Group_hong-kong,test device\n192.168.50.101,DIRECT,printer\n192.168.50.102,Interface:l2tp_1,vpn path",
"replace": false
}Use IP,target,comment. replace=true clears the existing rules before importing.
7. Whitelist management
Endpoint overview
| Method | Path | Purpose |
|---|---|---|
GET | /whitelist | Read whitelist settings |
PUT | /whitelist | Save whitelist settings |
GET /whitelist
{ "domains": "example.com", "ips": "1.1.1.1,2.2.2.2", "node": "DIRECT" }PUT /whitelist
Send domains, ips, and node. Domains and IPs accept comma or newline separators. Ordinary domains are matched by hostname. For a non-default port, use scheme://domain:port with http, https, or quic; both the sniffed domain and destination port must match. Use DIRECT, a node name, or Group_<name>; do not add Interface: to a whitelist destination.
8. Proxy-service management
Endpoint overview
| Method | Path | Purpose |
|---|---|---|
GET | /proxy-services/quota | Read proxy-service quota |
GET | /proxy-services | List services |
POST | /proxy-services | Create a service |
PUT | /proxy-services/{id} | Edit a service |
PATCH | /proxy-services/{id}/status | Enable or disable one service |
DELETE | /proxy-services/{id} | Delete one service |
DELETE | /proxy-services/batch | Delete services in bulk |
PATCH | /proxy-services/batch/status | Enable or disable services in bulk |
POST | /proxy-services/import | Import services in bulk |
GET /proxy-services/quota
{ "quota": 10, "used": 1 }GET /proxy-services
Returns { "data": [ProxyService, ...] }.
POST /proxy-services
{
"name": "wan1-http",
"outbound_interface": "wan1",
"port": 20001,
"username": "user",
"password": "pass",
"is_enabled": true
}PUT /proxy-services/{id}
Send the editable service fields. The response contains msg and id.
PATCH /proxy-services/{id}/status
{ "is_enabled": false }DELETE /proxy-services/{id}
Deletes one proxy service.
DELETE /proxy-services/batch
{ "ids": [1, 2, 3] }PATCH /proxy-services/batch/status
{ "ids": [1, 2, 3], "is_enabled": true }POST /proxy-services/import
Supported rows are name,outbound_interface,port,username,password, or shorter forms with the name and credentials omitted. Use replace=true only when the complete service list is intentionally being replaced.
9. Recommended call flows
9.1 Check status and interfaces
GET /system/statusGET /system/interfacesGET /system/interfaces-with-ipwhen an address is required.
9.2 Add a node and route traffic
POST /nodesGET /nodes/delay?name=<node-name>POST /ruleswith a node, group, direct, reject, or interface target.
9.3 Create or manage an L2TP/PPTP line
POST /vpn-linesGET /vpn-linesand inspectis_enabledandis_online.PATCH /vpn-lines/statusto enable or disable.PUT /vpn-lines/{type}/{name}to edit.
9.4 Bind a proxy-service egress
GET /proxy-services/quotaGET /system/interfaces-with-ipPOST /proxy-services
9.5 Import in bulk
POST /nodes/importPOST /vpn-lines/importPOST /rules/importPOST /proxy-services/import
10. Compatibility notes
- Paths in this document omit
/soloip/api/v1. Group_andInterface:are stable rule-target prefixes; include them exactly.- Proxy-service
outbound_interfaceis a bare interface name and must not useInterface:. is_onlineindicates an IPv4 address on the system interface, not detailed dial logs.- All create, edit, and batch-update endpoints use JSON request bodies.
- Example timestamps use ISO 8601.
