@wesell/n8n-nodes-confirmx 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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/credentials/ConfirmXApi.credentials.d.ts +18 -0
  4. package/credentials/ConfirmXApi.credentials.js +31 -0
  5. package/credentials/ConfirmXApi.credentials.js.map +1 -0
  6. package/credentials/ConfirmXApi.credentials.ts +40 -0
  7. package/index.d.ts +14 -0
  8. package/index.js +26 -0
  9. package/nodes/ConfirmX/ConfirmXAccount.node.d.ts +5 -0
  10. package/nodes/ConfirmX/ConfirmXAccount.node.js +81 -0
  11. package/nodes/ConfirmX/ConfirmXAccount.node.js.map +1 -0
  12. package/nodes/ConfirmX/ConfirmXAccount.node.ts +81 -0
  13. package/nodes/ConfirmX/ConfirmXConversation.node.d.ts +13 -0
  14. package/nodes/ConfirmX/ConfirmXConversation.node.js +266 -0
  15. package/nodes/ConfirmX/ConfirmXConversation.node.js.map +1 -0
  16. package/nodes/ConfirmX/ConfirmXConversation.node.ts +263 -0
  17. package/nodes/ConfirmX/ConfirmXMessage.node.d.ts +13 -0
  18. package/nodes/ConfirmX/ConfirmXMessage.node.js +364 -0
  19. package/nodes/ConfirmX/ConfirmXMessage.node.js.map +1 -0
  20. package/nodes/ConfirmX/ConfirmXMessage.node.ts +361 -0
  21. package/nodes/ConfirmX/ConfirmXShippingZone.node.d.ts +5 -0
  22. package/nodes/ConfirmX/ConfirmXShippingZone.node.js +100 -0
  23. package/nodes/ConfirmX/ConfirmXShippingZone.node.js.map +1 -0
  24. package/nodes/ConfirmX/ConfirmXShippingZone.node.ts +103 -0
  25. package/nodes/ConfirmX/ConfirmXTemplate.node.d.ts +13 -0
  26. package/nodes/ConfirmX/ConfirmXTemplate.node.js +310 -0
  27. package/nodes/ConfirmX/ConfirmXTemplate.node.js.map +1 -0
  28. package/nodes/ConfirmX/ConfirmXTemplate.node.ts +310 -0
  29. package/nodes/ConfirmX/ConfirmXTrigger.node.d.ts +29 -0
  30. package/nodes/ConfirmX/ConfirmXTrigger.node.js +190 -0
  31. package/nodes/ConfirmX/ConfirmXTrigger.node.js.map +1 -0
  32. package/nodes/ConfirmX/ConfirmXTrigger.node.ts +245 -0
  33. package/nodes/ConfirmX/ConfirmXWebhook.node.d.ts +5 -0
  34. package/nodes/ConfirmX/ConfirmXWebhook.node.js +169 -0
  35. package/nodes/ConfirmX/ConfirmXWebhook.node.js.map +1 -0
  36. package/nodes/ConfirmX/ConfirmXWebhook.node.ts +163 -0
  37. package/nodes/ConfirmX/confirmx.svg +4 -0
  38. package/package.json +69 -0
  39. package/transports/http.d.ts +43 -0
  40. package/transports/http.js +117 -0
  41. package/transports/http.js.map +1 -0
  42. package/transports/http.ts +170 -0
  43. package/transports/signature.d.ts +21 -0
  44. package/transports/signature.js +50 -0
  45. package/transports/signature.js.map +1 -0
  46. package/transports/signature.ts +55 -0
  47. package/types/api.d.ts +199 -0
  48. package/types/api.js +21 -0
  49. package/types/api.js.map +1 -0
  50. package/types/api.ts +238 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ConfirmX
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @wesell/n8n-nodes-confirmx
2
+
3
+ n8n community nodes for the [ConfirmX](https://confirmx.app) WhatsApp Business Platform. Wraps the public REST API at `/api/v1/*` and exposes every operation as both a regular n8n action and an **AI-callable tool** for n8n's AI Agent node.
4
+
5
+ ## What's included
6
+
7
+ | Node | Operations | AI tool? |
8
+ | --- | --- | --- |
9
+ | **ConfirmX Trigger** | webhook receive (5 event types) | — |
10
+ | **ConfirmX Account** | List | ✅ |
11
+ | **ConfirmX Template** | List, Get, Create, Delete | List + Get |
12
+ | **ConfirmX Conversation** | List, Get, Mark Read, Update Status, Assign | all 5 |
13
+ | **ConfirmX Message** | Send Text, Send Media, Start Conversation, List Messages, Retry | all 5 |
14
+ | **ConfirmX Webhook** | List, Create, Update, Delete | — (admin) |
15
+ | **ConfirmX ShippingZone** | Match (Egyptian governorate + area fuzzy match), List Governorates | Match |
16
+
17
+ ## Setup
18
+
19
+ 1. In ConfirmX: **Settings → API Keys → Create**. Copy the key (`cfx_live_…` for production, `cfx_test_…` for local).
20
+ 2. In n8n: **Settings → Community Nodes → Install** → pick `@confirmx/n8n-nodes-confirmx`.
21
+ 3. Add the **ConfirmX API** credential: paste your key + the base URL (`https://app.confirmx.com/api/v1` or `http://localhost:3001/api/v1`).
22
+ 4. Drop any ConfirmX node into your flow.
23
+
24
+ ### Local install (for development)
25
+
26
+ ```bash
27
+ git clone https://github.com/ConfirmX/n8n-nodes-confirmx
28
+ cd n8n-nodes-confirmx
29
+ npm install
30
+ npm run build
31
+ npm link
32
+ # in your n8n home:
33
+ npm link @wesell/n8n-nodes-confirmx
34
+ # restart n8n
35
+ ```
36
+
37
+ ## How the trigger works
38
+
39
+ The **ConfirmX Trigger** registers itself. When you add it to a flow and pick which events to subscribe to (default `message.received`), the trigger:
40
+
41
+ 1. Reads the per-flow webhook URL that n8n provides.
42
+ 2. `POST /api/v1/webhooks` with `{ url, events, description: "n8n integration" }`.
43
+ 3. Persists the returned `secret` in workflow staticData (this is required — `GET /webhooks/:id` does **not** return the secret).
44
+ 4. On every incoming delivery, verifies the `X-ConfirmX-Signature` HMAC against `${timestamp}.${body}`, rejects timestamps > 300s old, and emits the envelope's `data` field as the n8n item.
45
+ 5. On flow deletion/deactivation, `DELETE /webhooks/:id` cleans up.
46
+
47
+ ## Using as AI Agent tools
48
+
49
+ Every node with `usableAsTool: true` shows up in n8n's AI Agent "Tools" picker. The descriptions are written in-house to be LLM-friendly — they tell the model when to use the tool, what params it needs, and what it returns. Examples:
50
+
51
+ - **Send Text**: *"Send a free-form text message in an existing conversation. Use ONLY when the conversation is open (within 24h of the customer's last inbound message); otherwise use `startConversation` with a template."*
52
+ - **Match (ShippingZone)**: *"Fuzzy-match an Egyptian governorate and (optionally) area from free-text customer input (Arabic or English, with typos / aliases tolerated). … On ambiguous area returns `options[]` — present those options to the user and call again with the chosen governorate."*
53
+
54
+ ## Scopes
55
+
56
+ The ConfirmX API key you paste must have the appropriate scope(s). The scope picker in ConfirmX exposes `templates:read|write`, `conversations:read|write`, `messages:read|write`, `webhooks:read|write`, `shipping_zones:read`, plus `*` (full org access). The shipping-zone matcher is gated by `shipping_zones:read` (included in `*` for backwards compatibility).
57
+
58
+ ## Billing
59
+
60
+ The ConfirmX API metered every v1 call against the org's wallet:
61
+
62
+ - Reads (GET): cheap (default $0.0001)
63
+ - Writes (POST/PUT/PATCH/DELETE): metered (default $0.0005)
64
+ - Webhook deliveries to your n8n instance: $0.0002 on 2xx
65
+
66
+ When the wallet runs low, the API returns **402 Payment Required**. The n8n node surfaces this as a `NodeOperationError` with the balance figures and the topup URL inline. Webhook CRUD endpoints are free.
67
+
68
+ ## What this package does NOT include
69
+
70
+ - The ConfirmX internal `ai_agent` workflow node (separate runtime, internal billing model).
71
+ - Outbound webhooks from the ConfirmX admin side.
72
+ - Polling trigger mode (webhook-only).
73
+ - E-commerce platform integrations — separate concern.
74
+
75
+ ## License
76
+
77
+ MIT © ConfirmX
@@ -0,0 +1,18 @@
1
+ /**
2
+ * ConfirmX API credentials — a single API key + base URL is all that's
3
+ * needed to authenticate every ConfirmX node in this package.
4
+ *
5
+ * - `apiKey`: the plaintext key from Settings → API Keys. Format
6
+ * `cfx_live_...` for production, `cfx_test_...` for local dev. The
7
+ * server hashes with a pepper before lookup, so we never log or store
8
+ * the plaintext ourselves.
9
+ * - `baseUrl`: full base URL of the v1 API including the `/api/v1` suffix.
10
+ * Defaults are provided for hosted production and local dev.
11
+ */
12
+ import type { ICredentialType, INodeProperties } from 'n8n-workflow';
13
+ export declare class ConfirmXApi implements ICredentialType {
14
+ name: string;
15
+ displayName: string;
16
+ documentationUrl: string;
17
+ properties: INodeProperties[];
18
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmXApi = void 0;
4
+ class ConfirmXApi {
5
+ constructor() {
6
+ this.name = 'confirmXApi';
7
+ this.displayName = 'ConfirmX API';
8
+ this.documentationUrl = 'https://docs.confirmx.app/public-api';
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 ConfirmX API key. Create one in Settings → API Keys. Format: cfx_live_... (production) or cfx_test_... (local).',
18
+ },
19
+ {
20
+ displayName: 'Base URL',
21
+ name: 'baseUrl',
22
+ type: 'string',
23
+ default: 'https://app.confirmx.com/api/v1',
24
+ required: true,
25
+ description: 'Base URL of the ConfirmX v1 API (including the /api/v1 suffix). For local dev: http://localhost:3001/api/v1.',
26
+ },
27
+ ];
28
+ }
29
+ }
30
+ exports.ConfirmXApi = ConfirmXApi;
31
+ //# sourceMappingURL=ConfirmXApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmXApi.credentials.js","sourceRoot":"","sources":["ConfirmXApi.credentials.ts"],"names":[],"mappings":";;;AAaA,MAAa,WAAW;IAAxB;QACE,SAAI,GAAG,aAAa,CAAA;QACpB,gBAAW,GAAG,cAAc,CAAA;QAC5B,qBAAgB,GAAG,sCAAsC,CAAA;QAEzD,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,sHAAsH;aACzH;YACD;gBACE,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,iCAAiC;gBAC1C,QAAQ,EAAE,IAAI;gBACd,WAAW,EACT,8GAA8G;aACjH;SACF,CAAA;IACH,CAAC;CAAA;AA1BD,kCA0BC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ConfirmX API credentials — a single API key + base URL is all that's
3
+ * needed to authenticate every ConfirmX node in this package.
4
+ *
5
+ * - `apiKey`: the plaintext key from Settings → API Keys. Format
6
+ * `cfx_live_...` for production, `cfx_test_...` for local dev. The
7
+ * server hashes with a pepper before lookup, so we never log or store
8
+ * the plaintext ourselves.
9
+ * - `baseUrl`: full base URL of the v1 API including the `/api/v1` suffix.
10
+ * Defaults are provided for hosted production and local dev.
11
+ */
12
+ import type { ICredentialType, INodeProperties } from 'n8n-workflow'
13
+
14
+ export class ConfirmXApi implements ICredentialType {
15
+ name = 'confirmXApi'
16
+ displayName = 'ConfirmX API'
17
+ documentationUrl = 'https://docs.confirmx.app/public-api'
18
+
19
+ properties: INodeProperties[] = [
20
+ {
21
+ displayName: 'API Key',
22
+ name: 'apiKey',
23
+ type: 'string',
24
+ typeOptions: { password: true },
25
+ default: '',
26
+ required: true,
27
+ description:
28
+ 'Your ConfirmX API key. Create one in Settings → API Keys. Format: cfx_live_... (production) or cfx_test_... (local).',
29
+ },
30
+ {
31
+ displayName: 'Base URL',
32
+ name: 'baseUrl',
33
+ type: 'string',
34
+ default: 'https://app.confirmx.com/api/v1',
35
+ required: true,
36
+ description:
37
+ 'Base URL of the ConfirmX v1 API (including the /api/v1 suffix). For local dev: http://localhost:3001/api/v1.',
38
+ },
39
+ ]
40
+ }
package/index.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Package entry point — re-exports the 7 ConfirmX node classes and the
3
+ * ConfirmXApi credentials class for n8n's loader to discover.
4
+ *
5
+ * Built CJS output is emitted to ./index.js by `npm run build` (tsc).
6
+ */
7
+ export { ConfirmXApi } from './credentials/ConfirmXApi.credentials';
8
+ export { ConfirmXAccount } from './nodes/ConfirmX/ConfirmXAccount.node';
9
+ export { ConfirmXTemplate } from './nodes/ConfirmX/ConfirmXTemplate.node';
10
+ export { ConfirmXConversation } from './nodes/ConfirmX/ConfirmXConversation.node';
11
+ export { ConfirmXMessage } from './nodes/ConfirmX/ConfirmXMessage.node';
12
+ export { ConfirmXWebhook } from './nodes/ConfirmX/ConfirmXWebhook.node';
13
+ export { ConfirmXShippingZone } from './nodes/ConfirmX/ConfirmXShippingZone.node';
14
+ export { ConfirmXTrigger } from './nodes/ConfirmX/ConfirmXTrigger.node';
package/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmXTrigger = exports.ConfirmXShippingZone = exports.ConfirmXWebhook = exports.ConfirmXMessage = exports.ConfirmXConversation = exports.ConfirmXTemplate = exports.ConfirmXAccount = exports.ConfirmXApi = void 0;
4
+ /**
5
+ * Package entry point — re-exports the 7 ConfirmX node classes and the
6
+ * ConfirmXApi credentials class for n8n's loader to discover.
7
+ *
8
+ * Built CJS output is emitted to ./index.js by `npm run build` (tsc).
9
+ */
10
+ var ConfirmXApi_credentials_1 = require("./credentials/ConfirmXApi.credentials");
11
+ Object.defineProperty(exports, "ConfirmXApi", { enumerable: true, get: function () { return ConfirmXApi_credentials_1.ConfirmXApi; } });
12
+ var ConfirmXAccount_node_1 = require("./nodes/ConfirmX/ConfirmXAccount.node");
13
+ Object.defineProperty(exports, "ConfirmXAccount", { enumerable: true, get: function () { return ConfirmXAccount_node_1.ConfirmXAccount; } });
14
+ var ConfirmXTemplate_node_1 = require("./nodes/ConfirmX/ConfirmXTemplate.node");
15
+ Object.defineProperty(exports, "ConfirmXTemplate", { enumerable: true, get: function () { return ConfirmXTemplate_node_1.ConfirmXTemplate; } });
16
+ var ConfirmXConversation_node_1 = require("./nodes/ConfirmX/ConfirmXConversation.node");
17
+ Object.defineProperty(exports, "ConfirmXConversation", { enumerable: true, get: function () { return ConfirmXConversation_node_1.ConfirmXConversation; } });
18
+ var ConfirmXMessage_node_1 = require("./nodes/ConfirmX/ConfirmXMessage.node");
19
+ Object.defineProperty(exports, "ConfirmXMessage", { enumerable: true, get: function () { return ConfirmXMessage_node_1.ConfirmXMessage; } });
20
+ var ConfirmXWebhook_node_1 = require("./nodes/ConfirmX/ConfirmXWebhook.node");
21
+ Object.defineProperty(exports, "ConfirmXWebhook", { enumerable: true, get: function () { return ConfirmXWebhook_node_1.ConfirmXWebhook; } });
22
+ var ConfirmXShippingZone_node_1 = require("./nodes/ConfirmX/ConfirmXShippingZone.node");
23
+ Object.defineProperty(exports, "ConfirmXShippingZone", { enumerable: true, get: function () { return ConfirmXShippingZone_node_1.ConfirmXShippingZone; } });
24
+ var ConfirmXTrigger_node_1 = require("./nodes/ConfirmX/ConfirmXTrigger.node");
25
+ Object.defineProperty(exports, "ConfirmXTrigger", { enumerable: true, get: function () { return ConfirmXTrigger_node_1.ConfirmXTrigger; } });
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,5 @@
1
+ import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class ConfirmXAccount implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: any): Promise<any[][]>;
5
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmXAccount = void 0;
4
+ const http_1 = require("../../transports/http");
5
+ class ConfirmXAccount {
6
+ constructor() {
7
+ this.description = {
8
+ displayName: 'ConfirmX Account',
9
+ name: 'confirmXAccount',
10
+ icon: 'file:confirmx.svg',
11
+ group: ['transform'],
12
+ version: 1,
13
+ subtitle: '={{$parameter["operation"]}}',
14
+ description: 'Discover WhatsApp Business accounts linked to your ConfirmX organization. Use to look up an accountId for sending messages or managing templates.',
15
+ defaults: { name: 'ConfirmX Account' },
16
+ inputs: ['main'],
17
+ outputs: ['main'],
18
+ credentials: [{ name: 'confirmXApi', required: true }],
19
+ properties: [
20
+ {
21
+ displayName: 'Operation',
22
+ name: 'operation',
23
+ type: 'options',
24
+ noDataExpression: true,
25
+ options: [
26
+ {
27
+ name: 'List',
28
+ value: 'list',
29
+ action: 'List WhatsApp accounts',
30
+ description: 'List WhatsApp Business accounts linked to the current ConfirmX organization. Use when you need an `accountId` to send a template, start a conversation, or list templates — returns `id`, `label`, `phoneNumberId`, `businessAccountId`, and `isActive` for each. No required parameters.',
31
+ },
32
+ ],
33
+ default: 'list',
34
+ },
35
+ {
36
+ displayName: 'Return All',
37
+ name: 'returnAll',
38
+ type: 'boolean',
39
+ default: false,
40
+ displayOptions: { show: { operation: ['list'] } },
41
+ description: 'Whether to return all results or limit the page size',
42
+ },
43
+ {
44
+ displayName: 'Limit',
45
+ name: 'limit',
46
+ type: 'number',
47
+ default: 50,
48
+ typeOptions: { minValue: 1, maxValue: 200 },
49
+ displayOptions: {
50
+ show: { operation: ['list'], returnAll: [false] },
51
+ },
52
+ description: 'Maximum number of accounts to return',
53
+ },
54
+ ],
55
+ // Eligible as a tool for n8n AI Agent — single operation.
56
+ usableAsTool: true,
57
+ };
58
+ }
59
+ async execute() {
60
+ const items = this.getInputData();
61
+ const returnData = [];
62
+ for (let i = 0; i < items.length; i++) {
63
+ const operation = this.getNodeParameter('operation', i);
64
+ if (operation === 'list') {
65
+ const returnAll = this.getNodeParameter('returnAll', i);
66
+ const limit = this.getNodeParameter('limit', i) || 50;
67
+ const res = await (0, http_1.confirmxApiRequest)(this, {
68
+ method: 'GET',
69
+ endpoint: '/accounts',
70
+ });
71
+ const accounts = res.accounts || [];
72
+ const sliced = returnAll ? accounts : accounts.slice(0, limit);
73
+ const data = sliced.map((a) => ({ json: a }));
74
+ returnData.push(...data);
75
+ }
76
+ }
77
+ return [returnData];
78
+ }
79
+ }
80
+ exports.ConfirmXAccount = ConfirmXAccount;
81
+ //# sourceMappingURL=ConfirmXAccount.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmXAccount.node.js","sourceRoot":"","sources":["ConfirmXAccount.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { INodeType, INodeTypeDescription } from 'n8n-workflow'
2
+ import { confirmxApiRequest } from '../../transports/http'
3
+
4
+ export class ConfirmXAccount implements INodeType {
5
+ description: INodeTypeDescription = {
6
+ displayName: 'ConfirmX Account',
7
+ name: 'confirmXAccount',
8
+ icon: 'file:confirmx.svg',
9
+ group: ['transform'],
10
+ version: 1,
11
+ subtitle: '={{$parameter["operation"]}}',
12
+ description:
13
+ 'Discover WhatsApp Business accounts linked to your ConfirmX organization. Use to look up an accountId for sending messages or managing templates.',
14
+ defaults: { name: 'ConfirmX Account' },
15
+ inputs: ['main'],
16
+ outputs: ['main'],
17
+ credentials: [{ name: 'confirmXApi', required: true }],
18
+ properties: [
19
+ {
20
+ displayName: 'Operation',
21
+ name: 'operation',
22
+ type: 'options',
23
+ noDataExpression: true,
24
+ options: [
25
+ {
26
+ name: 'List',
27
+ value: 'list',
28
+ action: 'List WhatsApp accounts',
29
+ description:
30
+ 'List WhatsApp Business accounts linked to the current ConfirmX organization. Use when you need an `accountId` to send a template, start a conversation, or list templates — returns `id`, `label`, `phoneNumberId`, `businessAccountId`, and `isActive` for each. No required parameters.',
31
+ },
32
+ ],
33
+ default: 'list',
34
+ },
35
+ {
36
+ displayName: 'Return All',
37
+ name: 'returnAll',
38
+ type: 'boolean',
39
+ default: false,
40
+ displayOptions: { show: { operation: ['list'] } },
41
+ description: 'Whether to return all results or limit the page size',
42
+ },
43
+ {
44
+ displayName: 'Limit',
45
+ name: 'limit',
46
+ type: 'number',
47
+ default: 50,
48
+ typeOptions: { minValue: 1, maxValue: 200 },
49
+ displayOptions: {
50
+ show: { operation: ['list'], returnAll: [false] },
51
+ },
52
+ description: 'Maximum number of accounts to return',
53
+ },
54
+ ],
55
+ // Eligible as a tool for n8n AI Agent — single operation.
56
+ usableAsTool: true,
57
+ }
58
+
59
+ async execute(this: any) {
60
+ const items = this.getInputData()
61
+ const returnData: any[] = []
62
+
63
+ for (let i = 0; i < items.length; i++) {
64
+ const operation = this.getNodeParameter('operation', i) as string
65
+ if (operation === 'list') {
66
+ const returnAll = this.getNodeParameter('returnAll', i) as boolean
67
+ const limit = (this.getNodeParameter('limit', i) as number) || 50
68
+ const res = await confirmxApiRequest<{ accounts: any[] }>(this, {
69
+ method: 'GET',
70
+ endpoint: '/accounts',
71
+ })
72
+ const accounts = res.accounts || []
73
+ const sliced = returnAll ? accounts : accounts.slice(0, limit)
74
+ const data = sliced.map((a) => ({ json: a }))
75
+ returnData.push(...data)
76
+ }
77
+ }
78
+
79
+ return [returnData]
80
+ }
81
+ }
@@ -0,0 +1,13 @@
1
+ import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class ConfirmXConversation implements INodeType {
3
+ description: INodeTypeDescription;
4
+ methods: {
5
+ loadOptions: {
6
+ getAccounts(this: any): Promise<{
7
+ name: string;
8
+ value: string;
9
+ }[]>;
10
+ };
11
+ };
12
+ execute(this: any): Promise<any[][]>;
13
+ }