n8n-nodes-virtualsms 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # n8n-nodes-virtualsms
2
+
3
+ Community n8n nodes for [VirtualSMS](https://virtualsms.io) — real-SIM SMS verification across 145+ countries and 2,500+ services. Buy disposable phone numbers, receive OTP codes via polling, manage orders.
4
+
5
+ [![npm](https://img.shields.io/npm/v/n8n-nodes-virtualsms.svg)](https://www.npmjs.com/package/n8n-nodes-virtualsms)
6
+
7
+ ## Install
8
+
9
+ In **n8n desktop / cloud / self-hosted** → Settings → Community Nodes → Install:
10
+
11
+ ```
12
+ n8n-nodes-virtualsms
13
+ ```
14
+
15
+ ## Credentials
16
+
17
+ Create a key at [virtualsms.io](https://virtualsms.io) → Settings → API Keys, then in n8n add a **VirtualSMS API** credential with that key.
18
+
19
+ ## Nodes
20
+
21
+ ### `VirtualSMS` (action)
22
+
23
+ | Resource | Operations |
24
+ |---|---|
25
+ | Order | Buy Number, Get Status, Cancel, List, Check Price |
26
+ | Service | List |
27
+ | Country | List |
28
+ | Account | Get Balance |
29
+
30
+ `Check Price` is unauthenticated and reports back `success`/`error` along with the current cost for a service/country combination — useful as a pre-flight before `Buy Number`.
31
+
32
+ ### `VirtualSMS Trigger`
33
+
34
+ Three polling triggers:
35
+
36
+ - **Order Received SMS** — fires once per order that newly transitions to `received`
37
+ - **Order Expired** — fires once per order that newly transitions to `expired`
38
+ - **Low Balance** — fires once when balance crosses below configurable USD threshold (debounced)
39
+
40
+ > Triggers are polling-based because VirtualSMS does not currently expose a customer-facing outbound webhook subscription endpoint. The trigger node tracks seen-order IDs in workflow state to dedupe across poll intervals.
41
+
42
+ ## Service codes
43
+
44
+ VirtualSMS services use **short codes**, not slugs. Examples:
45
+
46
+ | Service | Code |
47
+ |---|---|
48
+ | WhatsApp | `wa` |
49
+ | Telegram | `tg` |
50
+ | 7-Eleven | `aws` |
51
+ | Caffe Nero | `bqo` |
52
+
53
+ Use the `Service: List` operation to discover the full catalog.
54
+
55
+ ## Example flow
56
+
57
+ `Schedule Trigger → VirtualSMS (Buy Number wa/GB) → Wait 30s → VirtualSMS Trigger (Order Received SMS) → ...`
58
+
59
+ Or `VirtualSMS Trigger (Order Received SMS) → IF sms_code present → Slack message`.
60
+
61
+ ## Develop locally
62
+
63
+ ```bash
64
+ git clone https://github.com/virtualsms-io/automation-integrations
65
+ cd automation-integrations
66
+ npm install
67
+ npm run build --workspace=n8n-nodes-virtualsms
68
+ ```
69
+
70
+ Link into a local n8n instance per [n8n community node docs](https://docs.n8n.io/integrations/creating-nodes/test/run-node-locally/).
71
+
72
+ ## License
73
+
74
+ MIT
@@ -0,0 +1,10 @@
1
+ import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from "n8n-workflow";
2
+ export declare class VirtualSmsApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest;
9
+ }
10
+ //# sourceMappingURL=VirtualSmsApi.credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualSmsApi.credentials.d.ts","sourceRoot":"","sources":["../../src/credentials/VirtualSmsApi.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,eAAe,EAChB,MAAM,cAAc,CAAC;AAEtB,qBAAa,aAAc,YAAW,eAAe;IACnD,IAAI,SAAmB;IACvB,WAAW,SAAoB;IAC/B,gBAAgB,SAA+B;IAE/C,UAAU,EAAE,eAAe,EAAE,CAkB3B;IAEF,YAAY,EAAE,oBAAoB,CAOhC;IAEF,IAAI,EAAE,sBAAsB,CAM1B;CACH"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VirtualSmsApi = void 0;
4
+ class VirtualSmsApi {
5
+ constructor() {
6
+ this.name = "virtualSmsApi";
7
+ this.displayName = "VirtualSMS API";
8
+ this.documentationUrl = "https://api.virtualsms.io";
9
+ this.properties = [
10
+ {
11
+ displayName: "API Key",
12
+ name: "apiKey",
13
+ type: "string",
14
+ typeOptions: { password: true },
15
+ default: "",
16
+ required: true,
17
+ description: "Your VirtualSMS API key. Find it at https://virtualsms.io → Settings → API Keys.",
18
+ },
19
+ {
20
+ displayName: "Base URL",
21
+ name: "baseUrl",
22
+ type: "string",
23
+ default: "https://virtualsms.io",
24
+ description: "Override only for self-hosted/staging deployments.",
25
+ },
26
+ ];
27
+ this.authenticate = {
28
+ type: "generic",
29
+ properties: {
30
+ headers: {
31
+ "X-API-Key": "={{$credentials.apiKey}}",
32
+ },
33
+ },
34
+ };
35
+ this.test = {
36
+ request: {
37
+ baseURL: "={{$credentials.baseUrl}}",
38
+ url: "/api/v1/balance",
39
+ method: "GET",
40
+ },
41
+ };
42
+ }
43
+ }
44
+ exports.VirtualSmsApi = VirtualSmsApi;
45
+ //# sourceMappingURL=VirtualSmsApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualSmsApi.credentials.js","sourceRoot":"","sources":["../../src/credentials/VirtualSmsApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,aAAa;IAA1B;QACE,SAAI,GAAG,eAAe,CAAC;QACvB,gBAAW,GAAG,gBAAgB,CAAC;QAC/B,qBAAgB,GAAG,2BAA2B,CAAC;QAE/C,eAAU,GAAsB;YAC9B;gBACE,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EACT,kFAAkF;aACrF;YACD;gBACE,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,uBAAuB;gBAChC,WAAW,EAAE,oDAAoD;aAClE;SACF,CAAC;QAEF,iBAAY,GAAyB;YACnC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACV,OAAO,EAAE;oBACP,WAAW,EAAE,0BAA0B;iBACxC;aACF;SACF,CAAC;QAEF,SAAI,GAA2B;YAC7B,OAAO,EAAE;gBACP,OAAO,EAAE,2BAA2B;gBACpC,GAAG,EAAE,iBAAiB;gBACtB,MAAM,EAAE,KAAK;aACd;SACF,CAAC;IACJ,CAAC;CAAA;AAzCD,sCAyCC"}
@@ -0,0 +1,4 @@
1
+ export { VirtualSms } from "./nodes/VirtualSms/VirtualSms.node";
2
+ export { VirtualSmsTrigger } from "./nodes/VirtualSmsTrigger/VirtualSmsTrigger.node";
3
+ export { VirtualSmsApi } from "./credentials/VirtualSmsApi.credentials";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VirtualSmsApi = exports.VirtualSmsTrigger = exports.VirtualSms = void 0;
4
+ var VirtualSms_node_1 = require("./nodes/VirtualSms/VirtualSms.node");
5
+ Object.defineProperty(exports, "VirtualSms", { enumerable: true, get: function () { return VirtualSms_node_1.VirtualSms; } });
6
+ var VirtualSmsTrigger_node_1 = require("./nodes/VirtualSmsTrigger/VirtualSmsTrigger.node");
7
+ Object.defineProperty(exports, "VirtualSmsTrigger", { enumerable: true, get: function () { return VirtualSmsTrigger_node_1.VirtualSmsTrigger; } });
8
+ var VirtualSmsApi_credentials_1 = require("./credentials/VirtualSmsApi.credentials");
9
+ Object.defineProperty(exports, "VirtualSmsApi", { enumerable: true, get: function () { return VirtualSmsApi_credentials_1.VirtualSmsApi; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,sEAAgE;AAAvD,6GAAA,UAAU,OAAA;AACnB,2FAAqF;AAA5E,2HAAA,iBAAiB,OAAA;AAC1B,qFAAwE;AAA/D,0HAAA,aAAa,OAAA"}
@@ -0,0 +1,6 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from "n8n-workflow";
2
+ export declare class VirtualSms implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
6
+ //# sourceMappingURL=VirtualSms.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualSms.node.d.ts","sourceRoot":"","sources":["../../../src/nodes/VirtualSms/VirtualSms.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EAEjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAErB,MAAM,cAAc,CAAC;AAoCtB,qBAAa,UAAW,YAAW,SAAS;IAC1C,WAAW,EAAE,oBAAoB,CA2L/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAiGxE"}
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VirtualSms = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ // n8n-workflow exports NodeConnectionType as type-only across many versions;
6
+ // the runtime value n8n actually expects is the string literal "main".
7
+ const MAIN = "main";
8
+ async function vsmsRequest(ctx, method, path, body, qs) {
9
+ const credentials = await ctx.getCredentials("virtualSmsApi");
10
+ const baseUrl = credentials.baseUrl?.replace(/\/+$/, "") ||
11
+ "https://virtualsms.io";
12
+ return ctx.helpers.httpRequestWithAuthentication.call(ctx, "virtualSmsApi", {
13
+ method,
14
+ url: `${baseUrl}${path}`,
15
+ json: true,
16
+ body,
17
+ qs: qs
18
+ ? Object.fromEntries(Object.entries(qs).filter(([, v]) => v !== undefined && v !== null && v !== ""))
19
+ : undefined,
20
+ headers: { Accept: "application/json" },
21
+ });
22
+ }
23
+ class VirtualSms {
24
+ constructor() {
25
+ this.description = {
26
+ displayName: "VirtualSMS",
27
+ name: "virtualSms",
28
+ icon: "file:virtualsms.svg",
29
+ group: ["transform"],
30
+ version: 1,
31
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
32
+ description: "Buy real-SIM phone numbers for SMS verification (2,500+ services, 145+ countries), check status, cancel orders.",
33
+ defaults: { name: "VirtualSMS" },
34
+ inputs: [MAIN],
35
+ outputs: [MAIN],
36
+ credentials: [
37
+ {
38
+ name: "virtualSmsApi",
39
+ required: true,
40
+ },
41
+ ],
42
+ requestDefaults: {
43
+ baseURL: "https://virtualsms.io",
44
+ },
45
+ properties: [
46
+ {
47
+ displayName: "Resource",
48
+ name: "resource",
49
+ type: "options",
50
+ noDataExpression: true,
51
+ options: [
52
+ { name: "Order", value: "order" },
53
+ { name: "Service", value: "service" },
54
+ { name: "Country", value: "country" },
55
+ { name: "Account", value: "account" },
56
+ ],
57
+ default: "order",
58
+ },
59
+ // ── Order operations ──
60
+ {
61
+ displayName: "Operation",
62
+ name: "operation",
63
+ type: "options",
64
+ noDataExpression: true,
65
+ displayOptions: { show: { resource: ["order"] } },
66
+ options: [
67
+ {
68
+ name: "Buy Number",
69
+ value: "buyNumber",
70
+ action: "Buy a phone number",
71
+ description: "Purchase a phone number for a given service code and ISO country code",
72
+ },
73
+ {
74
+ name: "Get Status",
75
+ value: "getStatus",
76
+ action: "Get order status",
77
+ description: "Read the current status and any received SMS code for an order UUID",
78
+ },
79
+ {
80
+ name: "Cancel",
81
+ value: "cancel",
82
+ action: "Cancel an order",
83
+ description: "Cancel an order and trigger refund. Returns HTTP 425 inside the 120-second cooldown.",
84
+ },
85
+ {
86
+ name: "List",
87
+ value: "list",
88
+ action: "List recent orders",
89
+ },
90
+ {
91
+ name: "Check Price",
92
+ value: "checkPrice",
93
+ action: "Look up price for a service/country combo",
94
+ description: "No auth required. Returns 'estimated' price + 'success' flag.",
95
+ },
96
+ ],
97
+ default: "buyNumber",
98
+ },
99
+ // Buy Number inputs
100
+ {
101
+ displayName: "Service Code",
102
+ name: "service",
103
+ type: "string",
104
+ required: true,
105
+ default: "",
106
+ placeholder: "wa",
107
+ description: "Short service code (e.g. 'wa' for WhatsApp, 'tg' for Telegram, 'aws' for 7-Eleven). Use 'Service: List' to discover codes — they are NOT slugs.",
108
+ displayOptions: {
109
+ show: { resource: ["order"], operation: ["buyNumber", "checkPrice"] },
110
+ },
111
+ },
112
+ {
113
+ displayName: "Country",
114
+ name: "country",
115
+ type: "string",
116
+ required: true,
117
+ default: "",
118
+ placeholder: "US",
119
+ description: "ISO 2-letter country code (e.g. US, GB, DE, AR).",
120
+ displayOptions: {
121
+ show: { resource: ["order"], operation: ["buyNumber", "checkPrice"] },
122
+ },
123
+ },
124
+ // Status / Cancel inputs
125
+ {
126
+ displayName: "Order ID",
127
+ name: "orderId",
128
+ type: "string",
129
+ required: true,
130
+ default: "",
131
+ placeholder: "7e44ebb5-9a55-4bd8-a4e9-7f226f9d5ebd",
132
+ description: "Order UUID returned by 'Buy Number'",
133
+ displayOptions: {
134
+ show: {
135
+ resource: ["order"],
136
+ operation: ["getStatus", "cancel"],
137
+ },
138
+ },
139
+ },
140
+ // List inputs
141
+ {
142
+ displayName: "Limit",
143
+ name: "limit",
144
+ type: "number",
145
+ typeOptions: { minValue: 1, maxValue: 500 },
146
+ default: 50,
147
+ displayOptions: {
148
+ show: { resource: ["order"], operation: ["list"] },
149
+ },
150
+ },
151
+ // ── Service operations ──
152
+ {
153
+ displayName: "Operation",
154
+ name: "operation",
155
+ type: "options",
156
+ noDataExpression: true,
157
+ displayOptions: { show: { resource: ["service"] } },
158
+ options: [
159
+ {
160
+ name: "List",
161
+ value: "list",
162
+ action: "List available services",
163
+ },
164
+ ],
165
+ default: "list",
166
+ },
167
+ // ── Country operations ──
168
+ {
169
+ displayName: "Operation",
170
+ name: "operation",
171
+ type: "options",
172
+ noDataExpression: true,
173
+ displayOptions: { show: { resource: ["country"] } },
174
+ options: [
175
+ {
176
+ name: "List",
177
+ value: "list",
178
+ action: "List available countries",
179
+ },
180
+ ],
181
+ default: "list",
182
+ },
183
+ // ── Account operations ──
184
+ {
185
+ displayName: "Operation",
186
+ name: "operation",
187
+ type: "options",
188
+ noDataExpression: true,
189
+ displayOptions: { show: { resource: ["account"] } },
190
+ options: [
191
+ {
192
+ name: "Get Balance",
193
+ value: "getBalance",
194
+ action: "Get account balance",
195
+ },
196
+ ],
197
+ default: "getBalance",
198
+ },
199
+ ],
200
+ };
201
+ }
202
+ async execute() {
203
+ const items = this.getInputData();
204
+ const out = [];
205
+ for (let i = 0; i < items.length; i++) {
206
+ const resource = this.getNodeParameter("resource", i);
207
+ const operation = this.getNodeParameter("operation", i);
208
+ try {
209
+ let result;
210
+ if (resource === "order") {
211
+ if (operation === "buyNumber") {
212
+ const service = this.getNodeParameter("service", i);
213
+ const country = this.getNodeParameter("country", i);
214
+ result = await vsmsRequest(this, "POST", "/api/v1/customer/purchase", { service, country });
215
+ }
216
+ else if (operation === "getStatus") {
217
+ const orderId = this.getNodeParameter("orderId", i);
218
+ result = await vsmsRequest(this, "GET", `/api/v1/customer/order/${encodeURIComponent(orderId)}`);
219
+ }
220
+ else if (operation === "cancel") {
221
+ const orderId = this.getNodeParameter("orderId", i);
222
+ result = await vsmsRequest(this, "POST", `/api/v1/customer/cancel/${encodeURIComponent(orderId)}`);
223
+ }
224
+ else if (operation === "list") {
225
+ const limit = this.getNodeParameter("limit", i);
226
+ result = await vsmsRequest(this, "GET", "/api/v1/customer/orders", undefined, { limit });
227
+ }
228
+ else if (operation === "checkPrice") {
229
+ const service = this.getNodeParameter("service", i);
230
+ const country = this.getNodeParameter("country", i);
231
+ result = await vsmsRequest(this, "GET", "/api/v1/price", undefined, { service, country });
232
+ }
233
+ else {
234
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown order operation: ${operation}`);
235
+ }
236
+ }
237
+ else if (resource === "service" && operation === "list") {
238
+ result = await vsmsRequest(this, "GET", "/api/v1/customer/services");
239
+ }
240
+ else if (resource === "country" && operation === "list") {
241
+ result = await vsmsRequest(this, "GET", "/api/v1/customer/countries");
242
+ }
243
+ else if (resource === "account" && operation === "getBalance") {
244
+ result = await vsmsRequest(this, "GET", "/api/v1/customer/balance");
245
+ }
246
+ else {
247
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unsupported ${resource}/${operation}`);
248
+ }
249
+ if (Array.isArray(result)) {
250
+ for (const row of result)
251
+ out.push({ json: row });
252
+ }
253
+ else {
254
+ out.push({ json: result });
255
+ }
256
+ }
257
+ catch (err) {
258
+ if (this.continueOnFail()) {
259
+ out.push({ json: { error: err.message }, pairedItem: i });
260
+ continue;
261
+ }
262
+ throw err;
263
+ }
264
+ }
265
+ return [out];
266
+ }
267
+ }
268
+ exports.VirtualSms = VirtualSms;
269
+ //# sourceMappingURL=VirtualSms.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualSms.node.js","sourceRoot":"","sources":["../../../src/nodes/VirtualSms/VirtualSms.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <rect width="64" height="64" rx="14" fill="#5046E5"/>
3
+ <path d="M18 22h28v4H18zM18 30h28v4H18zM18 38h20v4H18z" fill="#fff"/>
4
+ <circle cx="46" cy="42" r="4" fill="#22D3A6"/>
5
+ </svg>
@@ -0,0 +1,8 @@
1
+ import { IDataObject, IPollFunctions, INodeType, INodeTypeDescription } from "n8n-workflow";
2
+ export declare class VirtualSmsTrigger implements INodeType {
3
+ description: INodeTypeDescription;
4
+ poll(this: IPollFunctions): Promise<{
5
+ json: IDataObject;
6
+ }[][] | null>;
7
+ }
8
+ //# sourceMappingURL=VirtualSmsTrigger.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualSmsTrigger.node.d.ts","sourceRoot":"","sources":["../../../src/nodes/VirtualSmsTrigger/VirtualSmsTrigger.node.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAkCtB,qBAAa,iBAAkB,YAAW,SAAS;IACjD,WAAW,EAAE,oBAAoB,CAmE/B;IAEI,IAAI,CAAC,IAAI,EAAE,cAAc;cA4BoB,WAAW;;CAkC/D"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VirtualSmsTrigger = void 0;
4
+ const MAIN = "main";
5
+ async function callApi(ctx, method, path, qs) {
6
+ const credentials = await ctx.getCredentials("virtualSmsApi");
7
+ const baseUrl = credentials.baseUrl?.replace(/\/+$/, "") ||
8
+ "https://virtualsms.io";
9
+ return ctx.helpers.httpRequestWithAuthentication.call(ctx, "virtualSmsApi", {
10
+ method,
11
+ url: `${baseUrl}${path}`,
12
+ qs,
13
+ json: true,
14
+ headers: { Accept: "application/json" },
15
+ });
16
+ }
17
+ class VirtualSmsTrigger {
18
+ constructor() {
19
+ this.description = {
20
+ displayName: "VirtualSMS Trigger",
21
+ name: "virtualSmsTrigger",
22
+ icon: "file:virtualsms.svg",
23
+ group: ["trigger"],
24
+ version: 1,
25
+ subtitle: '={{$parameter["event"]}}',
26
+ description: "Polling triggers for VirtualSMS: new SMS received, rental expired, low balance.",
27
+ defaults: { name: "VirtualSMS Trigger" },
28
+ inputs: [],
29
+ outputs: [MAIN],
30
+ credentials: [
31
+ {
32
+ name: "virtualSmsApi",
33
+ required: true,
34
+ },
35
+ ],
36
+ polling: true,
37
+ properties: [
38
+ {
39
+ displayName: "Event",
40
+ name: "event",
41
+ type: "options",
42
+ noDataExpression: true,
43
+ options: [
44
+ {
45
+ name: "Order Received SMS",
46
+ value: "smsReceived",
47
+ description: "Fires once per order that newly transitions to status='completed' (the SMS-received terminal state on VirtualSMS)",
48
+ },
49
+ {
50
+ name: "Order Expired",
51
+ value: "orderExpired",
52
+ description: "Fires once per order that newly transitions to status='expired'",
53
+ },
54
+ {
55
+ name: "Low Balance",
56
+ value: "lowBalance",
57
+ description: "Fires once when account balance crosses below threshold (debounced)",
58
+ },
59
+ ],
60
+ default: "smsReceived",
61
+ },
62
+ {
63
+ displayName: "List Page Size",
64
+ name: "limit",
65
+ type: "number",
66
+ typeOptions: { minValue: 10, maxValue: 500 },
67
+ default: 100,
68
+ description: "How many recent orders to scan on each poll. Default 100 covers most use cases.",
69
+ displayOptions: { show: { event: ["smsReceived", "orderExpired"] } },
70
+ },
71
+ {
72
+ displayName: "Balance Threshold (USD)",
73
+ name: "balanceThreshold",
74
+ type: "number",
75
+ typeOptions: { numberPrecision: 2 },
76
+ default: 5,
77
+ description: "Trigger fires when balance drops below this value.",
78
+ displayOptions: { show: { event: ["lowBalance"] } },
79
+ },
80
+ ],
81
+ };
82
+ }
83
+ async poll() {
84
+ const event = this.getNodeParameter("event");
85
+ const data = this.getWorkflowStaticData("node");
86
+ if (event === "smsReceived" || event === "orderExpired") {
87
+ // VirtualSMS uses "completed" as the terminal state when SMS arrives —
88
+ // there is no "received" status in the production API. Verified live
89
+ // 2026-05-24 via /api/v1/customer/orders inspection.
90
+ const wantStatus = event === "smsReceived" ? "completed" : "expired";
91
+ const limit = this.getNodeParameter("limit");
92
+ const seenKey = `${event}Seen`;
93
+ const seen = data[seenKey] || [];
94
+ const seenSet = new Set(seen);
95
+ const resp = (await callApi(this, "GET", "/api/v1/customer/orders", { limit }));
96
+ const fresh = (resp.orders || []).filter((o) => o.status === wantStatus && !seenSet.has(o.id));
97
+ data[seenKey] = [...seen, ...fresh.map((o) => o.id)].slice(-1000);
98
+ return fresh.length
99
+ ? [fresh.map((o) => ({ json: o }))]
100
+ : null;
101
+ }
102
+ if (event === "lowBalance") {
103
+ const threshold = this.getNodeParameter("balanceThreshold");
104
+ const resp = (await callApi(this, "GET", "/api/v1/customer/balance"));
105
+ const balance = Number(resp.balance);
106
+ const wasBelow = Boolean(data.lowBalanceFired);
107
+ if (balance < threshold && !wasBelow) {
108
+ data.lowBalanceFired = true;
109
+ return [
110
+ [
111
+ {
112
+ json: {
113
+ balance,
114
+ threshold,
115
+ currency: "USD",
116
+ crossed_at: new Date().toISOString(),
117
+ },
118
+ },
119
+ ],
120
+ ];
121
+ }
122
+ if (balance >= threshold && wasBelow) {
123
+ data.lowBalanceFired = false;
124
+ }
125
+ return null;
126
+ }
127
+ return null;
128
+ }
129
+ }
130
+ exports.VirtualSmsTrigger = VirtualSmsTrigger;
131
+ //# sourceMappingURL=VirtualSmsTrigger.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualSmsTrigger.node.js","sourceRoot":"","sources":["../../../src/nodes/VirtualSmsTrigger/VirtualSmsTrigger.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <rect width="64" height="64" rx="14" fill="#5046E5"/>
3
+ <path d="M18 22h28v4H18zM18 30h28v4H18zM18 38h20v4H18z" fill="#fff"/>
4
+ <circle cx="46" cy="42" r="4" fill="#22D3A6"/>
5
+ </svg>
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "n8n-nodes-virtualsms",
3
+ "version": "0.1.0",
4
+ "description": "n8n community node for VirtualSMS — real-SIM SMS verification across 145+ countries and 2,500+ services. Buy numbers, receive OTP codes via webhook or polling, manage rentals.",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "n8n",
8
+ "sms",
9
+ "verification",
10
+ "otp",
11
+ "virtual-number",
12
+ "phone-verification",
13
+ "whatsapp",
14
+ "telegram",
15
+ "2fa",
16
+ "sim-card",
17
+ "virtualsms"
18
+ ],
19
+ "license": "MIT",
20
+ "homepage": "https://virtualsms.io",
21
+ "author": {
22
+ "name": "VirtualSMS",
23
+ "email": "dev@virtualsms.io"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/virtualsms-io/automation-integrations.git",
28
+ "directory": "packages/n8n-node"
29
+ },
30
+ "main": "dist/index.js",
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.json && node ./scripts/copy-assets.js",
33
+ "dev": "tsc --watch",
34
+ "lint": "echo \"(eslint optional)\" && exit 0",
35
+ "clean": "rimraf dist",
36
+ "test": "echo \"(no tests yet)\" && exit 0"
37
+ },
38
+ "files": [
39
+ "dist"
40
+ ],
41
+ "n8n": {
42
+ "n8nNodesApiVersion": 1,
43
+ "credentials": [
44
+ "dist/credentials/VirtualSmsApi.credentials.js"
45
+ ],
46
+ "nodes": [
47
+ "dist/nodes/VirtualSms/VirtualSms.node.js",
48
+ "dist/nodes/VirtualSmsTrigger/VirtualSmsTrigger.node.js"
49
+ ]
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.11.30",
53
+ "n8n-workflow": "*",
54
+ "rimraf": "^5.0.5",
55
+ "typescript": "^5.4.5"
56
+ },
57
+ "peerDependencies": {
58
+ "n8n-workflow": "*"
59
+ },
60
+ "engines": {
61
+ "node": ">=18.10.0"
62
+ }
63
+ }