n8n-nodes-42min 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 (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/dist/credentials/FortyTwoMinApi.credentials.d.ts +10 -0
  4. package/dist/credentials/FortyTwoMinApi.credentials.js +45 -0
  5. package/dist/credentials/FortyTwoMinApi.credentials.js.map +1 -0
  6. package/dist/icons/fortytwomin.dark.svg +22 -0
  7. package/dist/icons/fortytwomin.svg +22 -0
  8. package/dist/nodes/FortyTwoMin/FortyTwoMin.node.d.ts +4 -0
  9. package/dist/nodes/FortyTwoMin/FortyTwoMin.node.js +68 -0
  10. package/dist/nodes/FortyTwoMin/FortyTwoMin.node.js.map +1 -0
  11. package/dist/nodes/FortyTwoMin/FortyTwoMin.node.json +18 -0
  12. package/dist/nodes/FortyTwoMin/FortyTwoMinTrigger.node.d.ts +12 -0
  13. package/dist/nodes/FortyTwoMin/FortyTwoMinTrigger.node.js +185 -0
  14. package/dist/nodes/FortyTwoMin/FortyTwoMinTrigger.node.js.map +1 -0
  15. package/dist/nodes/FortyTwoMin/FortyTwoMinTrigger.node.json +18 -0
  16. package/dist/nodes/FortyTwoMin/GenericFunctions.d.ts +11 -0
  17. package/dist/nodes/FortyTwoMin/GenericFunctions.js +120 -0
  18. package/dist/nodes/FortyTwoMin/GenericFunctions.js.map +1 -0
  19. package/dist/nodes/FortyTwoMin/Routing.d.ts +10 -0
  20. package/dist/nodes/FortyTwoMin/Routing.js +63 -0
  21. package/dist/nodes/FortyTwoMin/Routing.js.map +1 -0
  22. package/dist/nodes/FortyTwoMin/descriptions/BookingDescription.d.ts +3 -0
  23. package/dist/nodes/FortyTwoMin/descriptions/BookingDescription.js +477 -0
  24. package/dist/nodes/FortyTwoMin/descriptions/BookingDescription.js.map +1 -0
  25. package/dist/nodes/FortyTwoMin/descriptions/EventTypeDescription.d.ts +3 -0
  26. package/dist/nodes/FortyTwoMin/descriptions/EventTypeDescription.js +143 -0
  27. package/dist/nodes/FortyTwoMin/descriptions/EventTypeDescription.js.map +1 -0
  28. package/dist/nodes/FortyTwoMin/descriptions/SlotDescription.d.ts +3 -0
  29. package/dist/nodes/FortyTwoMin/descriptions/SlotDescription.js +127 -0
  30. package/dist/nodes/FortyTwoMin/descriptions/SlotDescription.js.map +1 -0
  31. package/dist/nodes/FortyTwoMin/descriptions/UserDescription.d.ts +3 -0
  32. package/dist/nodes/FortyTwoMin/descriptions/UserDescription.js +28 -0
  33. package/dist/nodes/FortyTwoMin/descriptions/UserDescription.js.map +1 -0
  34. package/index.js +3 -0
  35. package/package.json +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 42min
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,151 @@
1
+ # n8n-nodes-42min
2
+
3
+ An [n8n](https://n8n.io) community node for [42min](https://42min.us), a meeting
4
+ scheduling platform. Create and manage bookings, look up availability, and start
5
+ workflows the moment something happens on a calendar.
6
+
7
+ This is a community node. It runs inside your own n8n instance and talks directly to
8
+ `api.42min.us`; nothing routes through a third party.
9
+
10
+ ## Installation
11
+
12
+ In n8n, go to **Settings → Community Nodes → Install** and enter:
13
+
14
+ ```
15
+ n8n-nodes-42min
16
+ ```
17
+
18
+ Or install it manually next to your n8n data directory:
19
+
20
+ ```bash
21
+ npm install n8n-nodes-42min
22
+ ```
23
+
24
+ Requires n8n 1.x and Node.js 20.15 or newer.
25
+
26
+ ## Credentials
27
+
28
+ The node authenticates with a **personal access token**.
29
+
30
+ 1. In 42min, open **Settings → API** and create a token.
31
+ 2. Give it the scopes you need. For everything this node offers:
32
+ `user:read`, `event_types:read`, `slots:read`, `bookings:read`, `bookings:create`,
33
+ `bookings:cancel`, `bookings:reschedule`, `bookings:update`, `webhooks:read`,
34
+ `webhooks:write`.
35
+ 3. In n8n, create a **42min API** credential and paste the token.
36
+
37
+ Use **Test** to confirm it works. Leave **Base URL** alone unless you run a
38
+ self-hosted 42min.
39
+
40
+ ## Operations
41
+
42
+ ### 42min (action node)
43
+
44
+ | Resource | Operations |
45
+ |---|---|
46
+ | **Booking** | Create, Get, Get Many, Update, Cancel, Reschedule |
47
+ | **Event Type** | Get, Get Many |
48
+ | **Slot** | Get Many, Check |
49
+ | **User** | Get Current |
50
+
51
+ ### 42min Trigger
52
+
53
+ Starts a workflow on any of these events:
54
+
55
+ `booking_created`, `booking_updated`, `booking_canceled`, `booking_rescheduled`,
56
+ `booking_no_show`, `event_type_updated`, `event_type_deleted`,
57
+ `routing_form_submitted`.
58
+
59
+ Activating a workflow registers a webhook subscription with 42min automatically, and
60
+ deactivating it removes the subscription again.
61
+
62
+ ## Things worth knowing
63
+
64
+ **Trigger items and lookup items use the same field names.** 42min delivers webhooks
65
+ in nested camelCase (`data.booking.startTime`) while the REST API is flat snake_case
66
+ (`start_at`). Booking triggers reshape the delivery into the REST vocabulary so you do
67
+ not have to learn two names for every field. The original envelope fields survive as
68
+ `event_id`, `event` and `occurred_at`. Set **Raw Payload** if you want the delivery
69
+ untouched.
70
+
71
+ **Deliveries are verified.** Every webhook is checked against its
72
+ `X-42min-Webhook-Signature` HMAC, with a replay window, and anything that fails is
73
+ rejected with a 401 instead of starting your workflow. Turn **Verify Signature** off
74
+ only if something between 42min and n8n rewrites the request body.
75
+
76
+ **Dedupe on `delivery_id`, not `event_id`.** The delivery id is stable across retries.
77
+ Both are attached to every trigger item.
78
+
79
+ **Writes are idempotent.** Booking creates, updates, cancels and reschedules send an
80
+ `Idempotency-Key` derived from the execution and item, so a retry inside one execution
81
+ replays the original result rather than double-booking. Set **Idempotency Key**
82
+ yourself when the same logical operation might be attempted from more than one
83
+ execution, for example keyed on a CRM record id.
84
+
85
+ **Get Event Type identifies by ID or by username plus slug.** A slug alone is not
86
+ enough, since it is unique per user rather than per account. The node encodes the
87
+ `username/slug` pair into the single path segment the API expects.
88
+
89
+ **Check the slot before you book.** Use **Slot: Check** first. A slot that was free a
90
+ moment ago may not be, and Create Booking sends real email and writes to a real
91
+ calendar.
92
+
93
+ **Updating a booking reads it first.** 42min requires the `If-Match` version token on
94
+ a PATCH, so the node fetches the booking, takes its ETag and sends it back. A
95
+ concurrent edit fails with a 409 rather than being silently overwritten. Only
96
+ `metadata`, `responses` and `attendee_name` are writable: to move a booking use
97
+ **Reschedule**, to cancel it use **Cancel**.
98
+
99
+ ## Trigger requirements
100
+
101
+ 42min delivers over HTTPS to public addresses only. Your n8n must be:
102
+
103
+ - reachable at an `https://` URL, and
104
+ - resolvable to a public IP. Deliveries to private ranges are refused.
105
+
106
+ If n8n advertises a non-HTTPS address the trigger will say so when you activate the
107
+ workflow. Set `WEBHOOK_URL` (or `N8N_PROTOCOL` and `N8N_HOST`) accordingly.
108
+
109
+ The action node has no such requirement: it only makes outbound calls, so it works
110
+ behind a firewall.
111
+
112
+ ## Local development
113
+
114
+ ```bash
115
+ npm install
116
+ npm run lint
117
+ npm test
118
+ ```
119
+
120
+ To run n8n with the node loaded and rebuilt on every change:
121
+
122
+ ```bash
123
+ npm run dev
124
+ ```
125
+
126
+ For the trigger you need a publicly reachable n8n, so use a tunnel during
127
+ development.
128
+
129
+ ## Releasing
130
+
131
+ Publishing happens in GitHub Actions, which attaches an npm provenance
132
+ statement. n8n requires this: nodes published from a local machine are not
133
+ accepted for verification.
134
+
135
+ ```bash
136
+ npm version minor
137
+ git push --follow-tags
138
+ ```
139
+
140
+ Pushing the tag runs `.github/workflows/publish.yml`, which lints, builds and
141
+ publishes. Update `CHANGELOG.md` in the same commit as the version bump.
142
+
143
+ ## Resources
144
+
145
+ - [42min API reference](https://42min.us/help/api)
146
+ - [OpenAPI specification](https://api.42min.us/openapi.yaml)
147
+ - [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
148
+
149
+ ## License
150
+
151
+ [MIT](LICENSE)
@@ -0,0 +1,10 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, Icon, INodeProperties } from 'n8n-workflow';
2
+ export declare class FortyTwoMinApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ icon: Icon;
6
+ documentationUrl: string;
7
+ properties: INodeProperties[];
8
+ authenticate: IAuthenticateGeneric;
9
+ test: ICredentialTestRequest;
10
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FortyTwoMinApi = void 0;
4
+ class FortyTwoMinApi {
5
+ constructor() {
6
+ this.name = 'fortyTwoMinApi';
7
+ this.displayName = '42min API';
8
+ this.icon = { light: 'file:../icons/fortytwomin.svg', dark: 'file:../icons/fortytwomin.dark.svg' };
9
+ this.documentationUrl = 'https://42min.us/help/api';
10
+ this.properties = [
11
+ {
12
+ displayName: 'Access Token',
13
+ name: 'accessToken',
14
+ type: 'string',
15
+ typeOptions: { password: true },
16
+ default: '',
17
+ required: true,
18
+ description: 'Personal access token from 42min. Create one under Settings > API in your 42min account.',
19
+ },
20
+ {
21
+ displayName: 'Base URL',
22
+ name: 'baseUrl',
23
+ type: 'string',
24
+ default: 'https://api.42min.us',
25
+ description: 'Change this only if you run a self-hosted 42min instance. Do not include a trailing slash or the /v1 path.',
26
+ },
27
+ ];
28
+ this.authenticate = {
29
+ type: 'generic',
30
+ properties: {
31
+ headers: {
32
+ Authorization: '=Bearer {{$credentials.accessToken}}',
33
+ },
34
+ },
35
+ };
36
+ this.test = {
37
+ request: {
38
+ baseURL: '={{$credentials.baseUrl}}',
39
+ url: '/v1/me',
40
+ },
41
+ };
42
+ }
43
+ }
44
+ exports.FortyTwoMinApi = FortyTwoMinApi;
45
+ //# sourceMappingURL=FortyTwoMinApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FortyTwoMinApi.credentials.js","sourceRoot":"","sources":["../../credentials/FortyTwoMinApi.credentials.ts"],"names":[],"mappings":";;;AAQA,MAAa,cAAc;IAA3B;QACC,SAAI,GAAG,gBAAgB,CAAC;QAExB,gBAAW,GAAG,WAAW,CAAC;QAE1B,SAAI,GAAS,EAAE,KAAK,EAAE,+BAA+B,EAAE,IAAI,EAAE,oCAAoC,EAAE,CAAC;QAEpG,qBAAgB,GAAG,2BAA2B,CAAC;QAE/C,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,cAAc;gBAC3B,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EACV,6FAA6F;aAC9F;YACD;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,sBAAsB;gBAC/B,WAAW,EACV,4GAA4G;aAC7G;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EAAE,sCAAsC;iBACrD;aACD;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,2BAA2B;gBACpC,GAAG,EAAE,QAAQ;aACb;SACD,CAAC;IACH,CAAC;CAAA;AA7CD,wCA6CC"}
@@ -0,0 +1,22 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
2
+ <defs>
3
+ <clipPath id="fortytwomin-clip-dark">
4
+ <rect x="2" y="5" width="28" height="26" rx="3"></rect>
5
+ </clipPath>
6
+ </defs>
7
+
8
+ <rect x="8" y="1" width="2.5" height="5" rx="1.2" fill="#fdf6ec"></rect>
9
+ <rect x="21.5" y="1" width="2.5" height="5" rx="1.2" fill="#fdf6ec"></rect>
10
+
11
+ <rect x="2" y="5" width="28" height="26" rx="3" fill="#1a1625"></rect>
12
+
13
+ <g clip-path="url(#fortytwomin-clip-dark)">
14
+ <rect x="2" y="5" width="28" height="9" fill="#f25c2c"></rect>
15
+ </g>
16
+
17
+ <line x1="2" y1="14" x2="30" y2="14" stroke="#fdf6ec" stroke-width="1.6"></line>
18
+
19
+ <text x="16" y="27" text-anchor="middle" fill="#fdf6ec" font-family="Outfit, &#39;Trebuchet MS&#39;, sans-serif" font-size="14" font-weight="900" letter-spacing="-0.5">42</text>
20
+
21
+ <rect x="2" y="5" width="28" height="26" rx="3" fill="none" stroke="#fdf6ec" stroke-width="2"></rect>
22
+ </svg>
@@ -0,0 +1,22 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
2
+ <defs>
3
+ <clipPath id="fortytwomin-clip">
4
+ <rect x="2" y="5" width="28" height="26" rx="3"></rect>
5
+ </clipPath>
6
+ </defs>
7
+
8
+ <rect x="8" y="1" width="2.5" height="5" rx="1.2" fill="#1a1625"></rect>
9
+ <rect x="21.5" y="1" width="2.5" height="5" rx="1.2" fill="#1a1625"></rect>
10
+
11
+ <rect x="2" y="5" width="28" height="26" rx="3" fill="#fdf6ec"></rect>
12
+
13
+ <g clip-path="url(#fortytwomin-clip)">
14
+ <rect x="2" y="5" width="28" height="9" fill="#f25c2c"></rect>
15
+ </g>
16
+
17
+ <line x1="2" y1="14" x2="30" y2="14" stroke="#1a1625" stroke-width="1.6"></line>
18
+
19
+ <text x="16" y="27" text-anchor="middle" fill="#1a1625" font-family="Outfit, &#39;Trebuchet MS&#39;, sans-serif" font-size="14" font-weight="900" letter-spacing="-0.5">42</text>
20
+
21
+ <rect x="2" y="5" width="28" height="26" rx="3" fill="none" stroke="#1a1625" stroke-width="2"></rect>
22
+ </svg>
@@ -0,0 +1,4 @@
1
+ import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class FortyTwoMin implements INodeType {
3
+ description: INodeTypeDescription;
4
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FortyTwoMin = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const BookingDescription_1 = require("./descriptions/BookingDescription");
6
+ const EventTypeDescription_1 = require("./descriptions/EventTypeDescription");
7
+ const SlotDescription_1 = require("./descriptions/SlotDescription");
8
+ const UserDescription_1 = require("./descriptions/UserDescription");
9
+ class FortyTwoMin {
10
+ constructor() {
11
+ this.description = {
12
+ displayName: '42min',
13
+ name: 'fortyTwoMin',
14
+ icon: { light: 'file:../../icons/fortytwomin.svg', dark: 'file:../../icons/fortytwomin.dark.svg' },
15
+ group: ['transform'],
16
+ version: 1,
17
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
18
+ description: 'Read and write bookings, event types and availability in 42min',
19
+ defaults: { name: '42min' },
20
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
21
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
22
+ usableAsTool: true,
23
+ credentials: [{ name: 'fortyTwoMinApi', required: true }],
24
+ requestDefaults: {
25
+ baseURL: '={{$credentials.baseUrl.replace(/\\/+$/, "")}}/v1',
26
+ headers: {
27
+ Accept: 'application/json',
28
+ 'Content-Type': 'application/json',
29
+ },
30
+ },
31
+ properties: [
32
+ {
33
+ displayName: 'Resource',
34
+ name: 'resource',
35
+ type: 'options',
36
+ noDataExpression: true,
37
+ options: [
38
+ { name: 'Booking', value: 'booking' },
39
+ { name: 'Event Type', value: 'eventType' },
40
+ { name: 'Slot', value: 'slot' },
41
+ { name: 'User', value: 'user' },
42
+ ],
43
+ default: 'booking',
44
+ },
45
+ ...BookingDescription_1.bookingOperations,
46
+ ...BookingDescription_1.bookingFields,
47
+ ...EventTypeDescription_1.eventTypeOperations,
48
+ ...EventTypeDescription_1.eventTypeFields,
49
+ ...SlotDescription_1.slotOperations,
50
+ ...SlotDescription_1.slotFields,
51
+ ...UserDescription_1.userOperations,
52
+ ...UserDescription_1.userFields,
53
+ {
54
+ displayName: 'Idempotency Key',
55
+ name: 'idempotencyKey',
56
+ type: 'string',
57
+ default: '',
58
+ displayOptions: {
59
+ show: { resource: ['booking'], operation: ['create', 'update', 'cancel', 'reschedule'] },
60
+ },
61
+ description: 'Leave empty to derive one from the execution and item. Set it to a stable value of your own, such as a CRM record ID, when the same logical operation may be attempted from more than one execution.',
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ }
67
+ exports.FortyTwoMin = FortyTwoMin;
68
+ //# sourceMappingURL=FortyTwoMin.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FortyTwoMin.node.js","sourceRoot":"","sources":["../../../nodes/FortyTwoMin/FortyTwoMin.node.ts"],"names":[],"mappings":";;;AACA,+CAAmD;AAEnD,0EAAqF;AACrF,8EAA2F;AAC3F,oEAA4E;AAC5E,oEAA4E;AAE5E,MAAa,WAAW;IAAxB;QACC,gBAAW,GAAyB;YACnC,WAAW,EAAE,OAAO;YACpB,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,EAAE,KAAK,EAAE,kCAAkC,EAAE,IAAI,EAAE,uCAAuC,EAAE;YAClG,KAAK,EAAE,CAAC,WAAW,CAAC;YACpB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,8DAA8D;YACxE,WAAW,EAAE,gEAAgE;YAC7E,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC3B,MAAM,EAAE,CAAC,kCAAmB,CAAC,IAAI,CAAC;YAClC,OAAO,EAAE,CAAC,kCAAmB,CAAC,IAAI,CAAC;YACnC,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACzD,eAAe,EAAE;gBAChB,OAAO,EAAE,mDAAmD;gBAC5D,OAAO,EAAE;oBACR,MAAM,EAAE,kBAAkB;oBAC1B,cAAc,EAAE,kBAAkB;iBAClC;aACD;YACD,UAAU,EAAE;gBACX;oBACC,WAAW,EAAE,UAAU;oBACvB,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,SAAS;oBACf,gBAAgB,EAAE,IAAI;oBACtB,OAAO,EAAE;wBACR,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;wBACrC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE;wBAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;wBAC/B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;qBAC/B;oBACD,OAAO,EAAE,SAAS;iBAClB;gBAED,GAAG,sCAAiB;gBACpB,GAAG,kCAAa;gBAChB,GAAG,0CAAmB;gBACtB,GAAG,sCAAe;gBAClB,GAAG,gCAAc;gBACjB,GAAG,4BAAU;gBACb,GAAG,gCAAc;gBACjB,GAAG,4BAAU;gBAEb;oBACC,WAAW,EAAE,iBAAiB;oBAC9B,IAAI,EAAE,gBAAgB;oBACtB,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,EAAE;oBACX,cAAc,EAAE;wBACf,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE;qBACxF;oBACD,WAAW,EACV,sMAAsM;iBACvM;aACD;SACD,CAAC;IACH,CAAC;CAAA;AA1DD,kCA0DC"}
@@ -0,0 +1,18 @@
1
+ {
2
+ "node": "n8n-nodes-42min.fortyTwoMin",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "categories": ["Productivity", "Sales"],
6
+ "resources": {
7
+ "credentialDocumentation": [
8
+ {
9
+ "url": "https://42min.us/help/integrations/n8n"
10
+ }
11
+ ],
12
+ "primaryDocumentation": [
13
+ {
14
+ "url": "https://42min.us/help/api/overview"
15
+ }
16
+ ]
17
+ }
18
+ }
@@ -0,0 +1,12 @@
1
+ import type { IHookFunctions, INodeType, INodeTypeDescription, IWebhookFunctions, IWebhookResponseData } from 'n8n-workflow';
2
+ export declare class FortyTwoMinTrigger implements INodeType {
3
+ description: INodeTypeDescription;
4
+ webhookMethods: {
5
+ default: {
6
+ checkExists(this: IHookFunctions): Promise<boolean>;
7
+ create(this: IHookFunctions): Promise<boolean>;
8
+ delete(this: IHookFunctions): Promise<boolean>;
9
+ };
10
+ };
11
+ webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
12
+ }
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FortyTwoMinTrigger = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const GenericFunctions_1 = require("./GenericFunctions");
6
+ class FortyTwoMinTrigger {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: '42min Trigger',
10
+ name: 'fortyTwoMinTrigger',
11
+ icon: { light: 'file:../../icons/fortytwomin.svg', dark: 'file:../../icons/fortytwomin.dark.svg' },
12
+ group: ['trigger'],
13
+ version: 1,
14
+ subtitle: '={{$parameter["events"].join(", ")}}',
15
+ description: 'Starts a workflow when something happens in 42min',
16
+ defaults: { name: '42min Trigger' },
17
+ inputs: [],
18
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
19
+ credentials: [{ name: 'fortyTwoMinApi', required: true }],
20
+ webhooks: [
21
+ {
22
+ name: 'default',
23
+ httpMethod: 'POST',
24
+ responseMode: 'onReceived',
25
+ path: 'webhook',
26
+ rawBody: true,
27
+ },
28
+ ],
29
+ properties: [
30
+ {
31
+ displayName: 'Events',
32
+ name: 'events',
33
+ type: 'multiOptions',
34
+ required: true,
35
+ default: ['booking_created'],
36
+ description: 'The events to subscribe to',
37
+ options: [
38
+ { name: 'Booking Canceled', value: 'booking_canceled' },
39
+ { name: 'Booking Created', value: 'booking_created' },
40
+ { name: 'Booking Marked No-Show', value: 'booking_no_show' },
41
+ { name: 'Booking Rescheduled', value: 'booking_rescheduled' },
42
+ { name: 'Booking Updated', value: 'booking_updated' },
43
+ { name: 'Event Type Deleted', value: 'event_type_deleted' },
44
+ { name: 'Event Type Updated', value: 'event_type_updated' },
45
+ { name: 'Routing Form Submitted', value: 'routing_form_submitted' },
46
+ ],
47
+ },
48
+ {
49
+ displayName: 'Options',
50
+ name: 'options',
51
+ type: 'collection',
52
+ placeholder: 'Add Option',
53
+ default: {},
54
+ options: [
55
+ {
56
+ displayName: 'Raw Payload',
57
+ name: 'rawPayload',
58
+ type: 'boolean',
59
+ default: false,
60
+ description: 'Whether to emit the delivery exactly as 42min sent it. By default booking events are reshaped into the same flat, snake_case field names the REST API uses, so a trigger item and a lookup item can be read the same way.',
61
+ },
62
+ {
63
+ displayName: 'Timestamp Tolerance (Seconds)',
64
+ name: 'tolerance',
65
+ type: 'number',
66
+ default: 300,
67
+ typeOptions: { minValue: 0 },
68
+ description: 'Reject deliveries whose signature timestamp is older than this. Guards against a captured delivery being replayed.',
69
+ },
70
+ {
71
+ displayName: 'Verify Signature',
72
+ name: 'verifySignature',
73
+ type: 'boolean',
74
+ default: true,
75
+ description: 'Whether to check the X-42min-Webhook-Signature header and reject anything that fails. Turn this off only if your reverse proxy rewrites the request body.',
76
+ },
77
+ ],
78
+ },
79
+ ],
80
+ };
81
+ this.webhookMethods = {
82
+ default: {
83
+ async checkExists() {
84
+ const staticData = this.getWorkflowStaticData('node');
85
+ const webhookUrl = this.getNodeWebhookUrl('default');
86
+ const response = await GenericFunctions_1.fortyTwoMinApiRequest.call(this, 'GET', '/v1/webhooks');
87
+ const existing = (response.data ?? []).find((hook) => hook.url === webhookUrl);
88
+ if (!existing) {
89
+ delete staticData.webhookId;
90
+ delete staticData.signingSecret;
91
+ return false;
92
+ }
93
+ if (!staticData.signingSecret) {
94
+ await GenericFunctions_1.fortyTwoMinApiRequest
95
+ .call(this, 'DELETE', `/v1/webhooks/${existing.id}`)
96
+ .catch(() => undefined);
97
+ delete staticData.webhookId;
98
+ return false;
99
+ }
100
+ staticData.webhookId = existing.id;
101
+ return true;
102
+ },
103
+ async create() {
104
+ const staticData = this.getWorkflowStaticData('node');
105
+ const webhookUrl = this.getNodeWebhookUrl('default');
106
+ const events = this.getNodeParameter('events');
107
+ if (!webhookUrl?.startsWith('https://')) {
108
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), '42min delivers webhooks over HTTPS only, and this n8n instance is reachable at a non-HTTPS URL', {
109
+ description: 'Set WEBHOOK_URL (or N8N_PROTOCOL/N8N_HOST) so n8n advertises a public https:// address, then activate the workflow again. The address must also resolve to a public IP: 42min refuses to deliver to private ranges.',
110
+ });
111
+ }
112
+ const response = await GenericFunctions_1.fortyTwoMinApiRequest.call(this, 'POST', '/v1/webhooks', {
113
+ url: webhookUrl,
114
+ events,
115
+ description: `n8n: ${this.getWorkflow().name ?? 'workflow'}`,
116
+ });
117
+ const created = (response.data ?? {});
118
+ if (!created.id || !created.signing_secret) {
119
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), '42min did not return a subscription ID and signing secret');
120
+ }
121
+ staticData.webhookId = created.id;
122
+ staticData.signingSecret = created.signing_secret;
123
+ return true;
124
+ },
125
+ async delete() {
126
+ const staticData = this.getWorkflowStaticData('node');
127
+ if (!staticData.webhookId)
128
+ return true;
129
+ try {
130
+ await GenericFunctions_1.fortyTwoMinApiRequest.call(this, 'DELETE', `/v1/webhooks/${staticData.webhookId}`);
131
+ }
132
+ catch (error) {
133
+ const status = error?.httpCode ?? error?.statusCode;
134
+ if (String(status) !== '404')
135
+ return false;
136
+ }
137
+ delete staticData.webhookId;
138
+ delete staticData.signingSecret;
139
+ return true;
140
+ },
141
+ },
142
+ };
143
+ }
144
+ async webhook() {
145
+ const staticData = this.getWorkflowStaticData('node');
146
+ const options = this.getNodeParameter('options', {});
147
+ const headers = this.getHeaderData();
148
+ const request = this.getRequestObject();
149
+ const verify = options.verifySignature !== false;
150
+ const rawBody = request.rawBody;
151
+ if (verify) {
152
+ if (!rawBody) {
153
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'The raw request body was not available, so the webhook signature could not be verified', {
154
+ description: 'Something between 42min and n8n is re-serializing the request. Fix the proxy, or turn off Verify Signature if you accept unauthenticated deliveries.',
155
+ });
156
+ }
157
+ const result = (0, GenericFunctions_1.verifyWebhookSignature)(rawBody, headers['x-42min-webhook-signature'], staticData.signingSecret ?? '', options.tolerance ?? 300);
158
+ if (!result.ok) {
159
+ const response = this.getResponseObject();
160
+ response.status(401).send(`Webhook signature rejected: ${result.reason}`);
161
+ return { noWebhookResponse: true };
162
+ }
163
+ }
164
+ let envelope;
165
+ if (rawBody) {
166
+ try {
167
+ envelope = JSON.parse(rawBody.toString('utf8'));
168
+ }
169
+ catch {
170
+ envelope = this.getBodyData();
171
+ }
172
+ }
173
+ else {
174
+ envelope = this.getBodyData();
175
+ }
176
+ const isBookingEvent = String(envelope.event ?? '').startsWith('booking.');
177
+ const emitRaw = options.rawPayload === true || !isBookingEvent;
178
+ const item = emitRaw ? envelope : (0, GenericFunctions_1.normalizeBookingEvent)(envelope);
179
+ item.delivery_id = headers['x-42min-webhook-id'] ?? null;
180
+ item.delivery_attempt = headers['x-42min-webhook-attempt'] ?? null;
181
+ return { workflowData: [this.helpers.returnJsonArray([item])] };
182
+ }
183
+ }
184
+ exports.FortyTwoMinTrigger = FortyTwoMinTrigger;
185
+ //# sourceMappingURL=FortyTwoMinTrigger.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FortyTwoMinTrigger.node.js","sourceRoot":"","sources":["../../../nodes/FortyTwoMin/FortyTwoMinTrigger.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ {
2
+ "node": "n8n-nodes-42min.fortyTwoMinTrigger",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "categories": ["Productivity", "Sales"],
6
+ "resources": {
7
+ "credentialDocumentation": [
8
+ {
9
+ "url": "https://42min.us/help/integrations/n8n"
10
+ }
11
+ ],
12
+ "primaryDocumentation": [
13
+ {
14
+ "url": "https://42min.us/help/api/webhooks"
15
+ }
16
+ ]
17
+ }
18
+ }
@@ -0,0 +1,11 @@
1
+ import type { IDataObject, IExecuteFunctions, IHookFunctions, IHttpRequestMethods, ILoadOptionsFunctions, IWebhookFunctions } from 'n8n-workflow';
2
+ type RequestContext = IExecuteFunctions | IHookFunctions | ILoadOptionsFunctions | IWebhookFunctions;
3
+ export declare function fortyTwoMinApiRequest(this: RequestContext, method: IHttpRequestMethods, resource: string, body?: IDataObject, qs?: IDataObject): Promise<IDataObject>;
4
+ export declare function verifyWebhookSignature(rawBody: Buffer | string, signatureHeader: string | undefined, secret: string, toleranceSeconds?: number): {
5
+ ok: true;
6
+ } | {
7
+ ok: false;
8
+ reason: string;
9
+ };
10
+ export declare function normalizeBookingEvent(envelope: IDataObject): IDataObject;
11
+ export {};