The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Add Client to 3x-ui",
"nodes": [
{
"parameters": {
"path": "add-client",
"httpMethod": "POST",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-add-client",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
250,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "check-session",
"leftValue": "={{ $json.body.sessionCookie }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "isEmpty"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-session-exists",
"name": "Check Session",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
450,
300
]
},
{
"parameters": {
"url": "={{ $json.body.protocol || 'http' }}://{{ $json.body.serverIP }}:{{ $json.body.serverPort }}/{{ $json.body.randompath || 'panel' }}/login",
"authentication": "none",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"username\": {{ $json.body.xuiUsername }},\n \"password\": {{ $json.body.xuiPassword }}\n}",
"options": {
"response": {
"response": {
"responseFormat": "json",
"fullResponse": true
}
}
}
},
"id": "login-3xui",
"name": "Login to 3x-ui",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
650,
200
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "extract-session-cookie",
"name": "sessionCookie",
"value": "={{ $json.headers['set-cookie'] ? $json.headers['set-cookie'][0] : $('Webhook').item.json.body.sessionCookie }}",
"type": "string"
}
]
},
"options": {}
},
"id": "set-session",
"name": "Set Session Cookie",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
850,
200
]
},
{
"parameters": {
"jsCode": "// \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f 3x-ui API\nconst body = $input.item.json.body;\nconst sessionCookie = $('Set Session Cookie').item.json.sessionCookie || body.sessionCookie;\n\n// \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c GB \u0432 \u0431\u0430\u0439\u0442\u044b\nconst totalGBInBytes = body.totalGB > 0 ? body.totalGB * 1024 * 1024 * 1024 : 0;\n\n// \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c email \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432\nconst cleanEmail = (body.email || '').replace(/\\s+/g, '_');\n\n// \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\nconst clientObject = {\n id: body.clientId,\n flow: 'xtls-rprx-vision',\n email: cleanEmail,\n limitIp: body.limitIp || 1,\n totalGB: totalGBInBytes,\n expiryTime: body.expiryTime || 0,\n enable: true,\n tgId: body.tgId || '',\n subId: body.subId || '',\n reset: 0,\n up: 0,\n down: 0\n};\n\n// \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c settings (JSON.stringify \u0434\u0432\u0430\u0436\u0434\u044b \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f)\nconst settings = JSON.stringify({\n clients: [clientObject]\n});\n\n// \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430\nconst requestBody = {\n id: parseInt(body.inboundId),\n settings: settings\n};\n\nreturn {\n json: {\n requestBody,\n sessionCookie,\n baseUrl: `${body.protocol || 'http'}://${body.serverIP}:${body.serverPort}/${body.randompath || 'panel'}`,\n clientId: body.clientId,\n email: body.email\n }\n};"
},
"id": "prepare-request",
"name": "Prepare Request",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
650,
400
]
},
{
"parameters": {
"url": "={{ $json.baseUrl }}/panel/api/inbounds/addClient",
"authentication": "none",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Cookie",
"value": "={{ $json.sessionCookie }}"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Accept",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ $json.requestBody }}",
"options": {
"response": {
"response": {
"responseFormat": "json",
"fullResponse": false
}
}
}
},
"id": "add-client-request",
"name": "Add Client to 3x-ui",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
850,
400
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "check-success",
"leftValue": "={{ $json.success }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "true"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "check-result",
"name": "Check Result",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1050,
400
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "response-success",
"name": "success",
"value": "=true",
"type": "boolean"
},
{
"id": "response-vpnUuid",
"name": "vpnUuid",
"value": "={{ $('Prepare Request').item.json.clientId }}",
"type": "string"
},
{
"id": "response-inboundId",
"name": "inboundId",
"value": "={{ parseInt($('Webhook').item.json.body.inboundId) }}",
"type": "number"
},
{
"id": "response-email",
"name": "email",
"value": "={{ $('Webhook').item.json.body.email }}",
"type": "string"
},
{
"id": "response-message",
"name": "message",
"value": "=\u041a\u043b\u0438\u0435\u043d\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d",
"type": "string"
},
{
"id": "response-sessionUpdated",
"name": "sessionUpdated",
"value": "={{ $('Check Session').item.json.sessionCookie ? false : true }}",
"type": "boolean"
},
{
"id": "response-sessionCookie",
"name": "sessionCookie",
"value": "={{ $('Set Session Cookie').item.json.sessionCookie || $('Webhook').item.json.body.sessionCookie }}",
"type": "string"
},
{
"id": "response-serverId",
"name": "serverId",
"value": "={{ $('Webhook').item.json.body.serverId }}",
"type": "string"
},
{
"id": "response-sessionCookieReceivedAt",
"name": "sessionCookieReceivedAt",
"value": "={{ $now.toISO() }}",
"type": "string"
}
]
},
"options": {}
},
"id": "format-success-response",
"name": "Format Success Response",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1250,
300
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "response-error",
"name": "success",
"value": "=false",
"type": "boolean"
},
{
"id": "response-error-message",
"name": "error",
"value": "={{ $json.msg || $json.message || '\u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430' }}",
"type": "string"
}
]
},
"options": {}
},
"id": "format-error-response",
"name": "Format Error Response",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1250,
500
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {}
},
"id": "respond-to-webhook",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1450,
400
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Check Session",
"type": "main",
"index": 0
}
]
]
},
"Check Session": {
"main": [
[
{
"node": "Login to 3x-ui",
"type": "main",
"index": 0
}
],
[
{
"node": "Prepare Request",
"type": "main",
"index": 0
}
]
]
},
"Login to 3x-ui": {
"main": [
[
{
"node": "Set Session Cookie",
"type": "main",
"index": 0
}
]
]
},
"Set Session Cookie": {
"main": [
[
{
"node": "Prepare Request",
"type": "main",
"index": 0
}
]
]
},
"Prepare Request": {
"main": [
[
{
"node": "Add Client to 3x-ui",
"type": "main",
"index": 0
}
]
]
},
"Add Client to 3x-ui": {
"main": [
[
{
"node": "Check Result",
"type": "main",
"index": 0
}
]
]
},
"Check Result": {
"main": [
[
{
"node": "Format Success Response",
"type": "main",
"index": 0
}
],
[
{
"node": "Format Error Response",
"type": "main",
"index": 0
}
]
]
},
"Format Success Response": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Format Error Response": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 0,
"updatedAt": "2024-01-01T00:00:00.000Z",
"versionId": "1"
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Add Client to 3x-ui. Uses httpRequest. Webhook trigger; 10 nodes.
Source: https://github.com/vlad4endev/VPN/blob/484e0b6a95ad6bbcd1e92ff8d211a17d6f69d1dd/n8n-workflows/add-client.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Portfolio Orchestrator. Uses httpRequest. Webhook trigger; 59 nodes.
jump-section: Comment Fix Pipeline. Uses httpRequest. Webhook trigger; 24 nodes.
GitHub Issues Router (Linear / Jira / ClickUp). Uses stickyNote, httpRequest, respondToWebhook. Webhook trigger; 23 nodes.
Form to CRM Lead Router (Pipedrive / HubSpot / Salesforce). Uses stickyNote, httpRequest, respondToWebhook. Webhook trigger; 22 nodes.
Calendly to CRM Sync (Pipedrive / HubSpot / Salesforce). Uses stickyNote, httpRequest, respondToWebhook. Webhook trigger; 22 nodes.