@linqapp/sdk 0.1.5 → 0.4.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/CHANGELOG.md +36 -0
- package/README.md +31 -0
- package/client.d.mts +299 -7
- package/client.d.mts.map +1 -1
- package/client.d.ts +299 -7
- package/client.d.ts.map +1 -1
- package/client.js +294 -12
- package/client.js.map +1 -1
- package/client.mjs +294 -12
- package/client.mjs.map +1 -1
- package/core/pagination.d.mts +69 -0
- package/core/pagination.d.mts.map +1 -0
- package/core/pagination.d.ts +69 -0
- package/core/pagination.d.ts.map +1 -0
- package/core/pagination.js +125 -0
- package/core/pagination.js.map +1 -0
- package/core/pagination.mjs +118 -0
- package/core/pagination.mjs.map +1 -0
- package/index.d.mts +1 -0
- package/index.d.mts.map +1 -1
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +3 -1
- package/index.js.map +1 -1
- package/index.mjs +1 -0
- package/index.mjs.map +1 -1
- package/internal/tslib.js +18 -18
- package/internal/utils/query.d.mts +5 -0
- package/internal/utils/query.d.mts.map +1 -0
- package/internal/utils/query.d.ts +5 -0
- package/internal/utils/query.d.ts.map +1 -0
- package/internal/utils/query.js +23 -0
- package/internal/utils/query.js.map +1 -0
- package/internal/utils/query.mjs +20 -0
- package/internal/utils/query.mjs.map +1 -0
- package/internal/utils.d.mts +1 -0
- package/internal/utils.d.ts +1 -0
- package/internal/utils.js +1 -0
- package/internal/utils.js.map +1 -1
- package/internal/utils.mjs +1 -0
- package/package.json +11 -1
- package/pagination.d.mts +2 -0
- package/pagination.d.mts.map +1 -0
- package/pagination.d.ts +2 -0
- package/pagination.d.ts.map +1 -0
- package/pagination.js +6 -0
- package/pagination.js.map +1 -0
- package/pagination.mjs +2 -0
- package/pagination.mjs.map +1 -0
- package/resources/attachments.d.mts +64 -0
- package/resources/attachments.d.mts.map +1 -1
- package/resources/attachments.d.ts +64 -0
- package/resources/attachments.d.ts.map +1 -1
- package/resources/attachments.js +64 -0
- package/resources/attachments.js.map +1 -1
- package/resources/attachments.mjs +64 -0
- package/resources/attachments.mjs.map +1 -1
- package/resources/capability.d.mts +12 -9
- package/resources/capability.d.mts.map +1 -1
- package/resources/capability.d.ts +12 -9
- package/resources/capability.d.ts.map +1 -1
- package/resources/capability.js +7 -4
- package/resources/capability.js.map +1 -1
- package/resources/capability.mjs +7 -4
- package/resources/capability.mjs.map +1 -1
- package/resources/chats/chats.d.mts +76 -97
- package/resources/chats/chats.d.mts.map +1 -1
- package/resources/chats/chats.d.ts +76 -97
- package/resources/chats/chats.d.ts.map +1 -1
- package/resources/chats/chats.js +8 -4
- package/resources/chats/chats.js.map +1 -1
- package/resources/chats/chats.mjs +9 -5
- package/resources/chats/chats.mjs.map +1 -1
- package/resources/chats/index.d.mts +2 -2
- package/resources/chats/index.d.mts.map +1 -1
- package/resources/chats/index.d.ts +2 -2
- package/resources/chats/index.d.ts.map +1 -1
- package/resources/chats/index.js.map +1 -1
- package/resources/chats/index.mjs.map +1 -1
- package/resources/chats/messages.d.mts +21 -25
- package/resources/chats/messages.d.mts.map +1 -1
- package/resources/chats/messages.d.ts +21 -25
- package/resources/chats/messages.d.ts.map +1 -1
- package/resources/chats/messages.js +16 -3
- package/resources/chats/messages.js.map +1 -1
- package/resources/chats/messages.mjs +16 -3
- package/resources/chats/messages.mjs.map +1 -1
- package/resources/chats/participants.d.mts +18 -0
- package/resources/chats/participants.d.mts.map +1 -1
- package/resources/chats/participants.d.ts +18 -0
- package/resources/chats/participants.d.ts.map +1 -1
- package/resources/chats/participants.js +18 -0
- package/resources/chats/participants.js.map +1 -1
- package/resources/chats/participants.mjs +18 -0
- package/resources/chats/participants.mjs.map +1 -1
- package/resources/chats/typing.d.mts +18 -0
- package/resources/chats/typing.d.mts.map +1 -1
- package/resources/chats/typing.d.ts +18 -0
- package/resources/chats/typing.d.ts.map +1 -1
- package/resources/chats/typing.js +18 -0
- package/resources/chats/typing.js.map +1 -1
- package/resources/chats/typing.mjs +18 -0
- package/resources/chats/typing.mjs.map +1 -1
- package/resources/index.d.mts +4 -3
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +4 -3
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js +3 -1
- package/resources/index.js.map +1 -1
- package/resources/index.mjs +1 -0
- package/resources/index.mjs.map +1 -1
- package/resources/messages.d.mts +37 -72
- package/resources/messages.d.mts.map +1 -1
- package/resources/messages.d.ts +37 -72
- package/resources/messages.d.ts.map +1 -1
- package/resources/messages.js +34 -4
- package/resources/messages.js.map +1 -1
- package/resources/messages.mjs +34 -4
- package/resources/messages.mjs.map +1 -1
- package/resources/phone-numbers.d.mts +9 -0
- package/resources/phone-numbers.d.mts.map +1 -1
- package/resources/phone-numbers.d.ts +9 -0
- package/resources/phone-numbers.d.ts.map +1 -1
- package/resources/phone-numbers.js +9 -0
- package/resources/phone-numbers.js.map +1 -1
- package/resources/phone-numbers.mjs +9 -0
- package/resources/phone-numbers.mjs.map +1 -1
- package/resources/phonenumbers.d.mts +9 -0
- package/resources/phonenumbers.d.mts.map +1 -1
- package/resources/phonenumbers.d.ts +9 -0
- package/resources/phonenumbers.d.ts.map +1 -1
- package/resources/phonenumbers.js +9 -0
- package/resources/phonenumbers.js.map +1 -1
- package/resources/phonenumbers.mjs +9 -0
- package/resources/phonenumbers.mjs.map +1 -1
- package/resources/shared.d.mts +51 -0
- package/resources/shared.d.mts.map +1 -1
- package/resources/shared.d.ts +51 -0
- package/resources/shared.d.ts.map +1 -1
- package/resources/webhook-events.d.mts +90 -1
- package/resources/webhook-events.d.mts.map +1 -1
- package/resources/webhook-events.d.ts +90 -1
- package/resources/webhook-events.d.ts.map +1 -1
- package/resources/webhook-events.js +89 -0
- package/resources/webhook-events.js.map +1 -1
- package/resources/webhook-events.mjs +89 -0
- package/resources/webhook-events.mjs.map +1 -1
- package/resources/webhook-subscriptions.d.mts +89 -0
- package/resources/webhook-subscriptions.d.mts.map +1 -1
- package/resources/webhook-subscriptions.d.ts +89 -0
- package/resources/webhook-subscriptions.d.ts.map +1 -1
- package/resources/webhook-subscriptions.js +89 -0
- package/resources/webhook-subscriptions.js.map +1 -1
- package/resources/webhook-subscriptions.mjs +89 -0
- package/resources/webhook-subscriptions.mjs.map +1 -1
- package/resources/webhooks.d.mts +2506 -0
- package/resources/webhooks.d.mts.map +1 -0
- package/resources/webhooks.d.ts +2506 -0
- package/resources/webhooks.d.ts.map +1 -0
- package/resources/webhooks.js +12 -0
- package/resources/webhooks.js.map +1 -0
- package/resources/webhooks.mjs +8 -0
- package/resources/webhooks.mjs.map +1 -0
- package/src/client.ts +443 -37
- package/src/core/pagination.ts +212 -0
- package/src/index.ts +1 -0
- package/src/internal/utils/query.ts +23 -0
- package/src/internal/utils.ts +1 -0
- package/src/pagination.ts +2 -0
- package/src/resources/attachments.ts +64 -0
- package/src/resources/capability.ts +17 -14
- package/src/resources/chats/chats.ts +86 -115
- package/src/resources/chats/index.ts +4 -3
- package/src/resources/chats/messages.ts +30 -30
- package/src/resources/chats/participants.ts +18 -0
- package/src/resources/chats/typing.ts +18 -0
- package/src/resources/index.ts +55 -10
- package/src/resources/messages.ts +49 -90
- package/src/resources/phone-numbers.ts +9 -0
- package/src/resources/phonenumbers.ts +9 -0
- package/src/resources/shared.ts +62 -0
- package/src/resources/webhook-events.ts +90 -0
- package/src/resources/webhook-subscriptions.ts +89 -0
- package/src/resources/webhooks.ts +3089 -0
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
2
|
import { APIResource } from "../core/resource.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
5
|
+
* occur on your account.
|
|
6
|
+
*
|
|
7
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
8
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
9
|
+
*
|
|
10
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
11
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
12
|
+
* deduplication.
|
|
13
|
+
*
|
|
14
|
+
* ## Webhook Headers
|
|
15
|
+
*
|
|
16
|
+
* Each webhook request includes the following headers:
|
|
17
|
+
*
|
|
18
|
+
* | Header | Description |
|
|
19
|
+
* |--------|-------------|
|
|
20
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
21
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
22
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
23
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
24
|
+
*
|
|
25
|
+
* ## Verifying Webhook Signatures
|
|
26
|
+
*
|
|
27
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
28
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
29
|
+
*
|
|
30
|
+
* **Signature Construction:**
|
|
31
|
+
*
|
|
32
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
33
|
+
*
|
|
34
|
+
* ```
|
|
35
|
+
* {timestamp}.{payload}
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* Where:
|
|
39
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
40
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
41
|
+
*
|
|
42
|
+
* **Verification Steps:**
|
|
43
|
+
*
|
|
44
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
45
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
46
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
47
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
48
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
49
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
50
|
+
*
|
|
51
|
+
* **Example (Python):**
|
|
52
|
+
*
|
|
53
|
+
* ```python
|
|
54
|
+
* import hmac
|
|
55
|
+
* import hashlib
|
|
56
|
+
*
|
|
57
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
58
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
59
|
+
* expected = hmac.new(
|
|
60
|
+
* signing_secret.encode('utf-8'),
|
|
61
|
+
* message.encode('utf-8'),
|
|
62
|
+
* hashlib.sha256
|
|
63
|
+
* ).hexdigest()
|
|
64
|
+
* return hmac.compare_digest(expected, signature)
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* **Example (Node.js):**
|
|
68
|
+
*
|
|
69
|
+
* ```javascript
|
|
70
|
+
* const crypto = require('crypto');
|
|
71
|
+
*
|
|
72
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
73
|
+
* const message = `${timestamp}.${payload}`;
|
|
74
|
+
* const expected = crypto
|
|
75
|
+
* .createHmac('sha256', signingSecret)
|
|
76
|
+
* .update(message)
|
|
77
|
+
* .digest('hex');
|
|
78
|
+
* return crypto.timingSafeEqual(
|
|
79
|
+
* Buffer.from(expected),
|
|
80
|
+
* Buffer.from(signature)
|
|
81
|
+
* );
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* **Security Best Practices:**
|
|
86
|
+
*
|
|
87
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
88
|
+
* - Always use constant-time comparison for signature verification
|
|
89
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
90
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
91
|
+
*/
|
|
3
92
|
export class WebhookEvents extends APIResource {
|
|
4
93
|
/**
|
|
5
94
|
* Returns all available webhook event types that can be subscribed to. Use this
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-events.mjs","sourceRoot":"","sources":["../src/resources/webhook-events.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,WAAW,EAAE;AAItB,MAAM,OAAO,aAAc,SAAQ,WAAW;IAC5C;;;;OAIG;IACH,IAAI,CAAC,OAAwB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"webhook-events.mjs","sourceRoot":"","sources":["../src/resources/webhook-events.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,WAAW,EAAE;AAItB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AACH,MAAM,OAAO,aAAc,SAAQ,WAAW;IAC5C;;;;OAIG;IACH,IAAI,CAAC,OAAwB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;CACF"}
|
|
@@ -2,6 +2,95 @@ import { APIResource } from "../core/resource.mjs";
|
|
|
2
2
|
import * as WebhookEventsAPI from "./webhook-events.mjs";
|
|
3
3
|
import { APIPromise } from "../core/api-promise.mjs";
|
|
4
4
|
import { RequestOptions } from "../internal/request-options.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
7
|
+
* occur on your account.
|
|
8
|
+
*
|
|
9
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
10
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
11
|
+
*
|
|
12
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
13
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
14
|
+
* deduplication.
|
|
15
|
+
*
|
|
16
|
+
* ## Webhook Headers
|
|
17
|
+
*
|
|
18
|
+
* Each webhook request includes the following headers:
|
|
19
|
+
*
|
|
20
|
+
* | Header | Description |
|
|
21
|
+
* |--------|-------------|
|
|
22
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
23
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
24
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
25
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
26
|
+
*
|
|
27
|
+
* ## Verifying Webhook Signatures
|
|
28
|
+
*
|
|
29
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
30
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
31
|
+
*
|
|
32
|
+
* **Signature Construction:**
|
|
33
|
+
*
|
|
34
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
35
|
+
*
|
|
36
|
+
* ```
|
|
37
|
+
* {timestamp}.{payload}
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* Where:
|
|
41
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
42
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
43
|
+
*
|
|
44
|
+
* **Verification Steps:**
|
|
45
|
+
*
|
|
46
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
47
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
48
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
49
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
50
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
51
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
52
|
+
*
|
|
53
|
+
* **Example (Python):**
|
|
54
|
+
*
|
|
55
|
+
* ```python
|
|
56
|
+
* import hmac
|
|
57
|
+
* import hashlib
|
|
58
|
+
*
|
|
59
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
60
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
61
|
+
* expected = hmac.new(
|
|
62
|
+
* signing_secret.encode('utf-8'),
|
|
63
|
+
* message.encode('utf-8'),
|
|
64
|
+
* hashlib.sha256
|
|
65
|
+
* ).hexdigest()
|
|
66
|
+
* return hmac.compare_digest(expected, signature)
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* **Example (Node.js):**
|
|
70
|
+
*
|
|
71
|
+
* ```javascript
|
|
72
|
+
* const crypto = require('crypto');
|
|
73
|
+
*
|
|
74
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
75
|
+
* const message = `${timestamp}.${payload}`;
|
|
76
|
+
* const expected = crypto
|
|
77
|
+
* .createHmac('sha256', signingSecret)
|
|
78
|
+
* .update(message)
|
|
79
|
+
* .digest('hex');
|
|
80
|
+
* return crypto.timingSafeEqual(
|
|
81
|
+
* Buffer.from(expected),
|
|
82
|
+
* Buffer.from(signature)
|
|
83
|
+
* );
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* **Security Best Practices:**
|
|
88
|
+
*
|
|
89
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
90
|
+
* - Always use constant-time comparison for signature verification
|
|
91
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
92
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
93
|
+
*/
|
|
5
94
|
export declare class WebhookSubscriptions extends APIResource {
|
|
6
95
|
/**
|
|
7
96
|
* Create a new webhook subscription to receive events at a target URL. Upon
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-subscriptions.d.mts","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,KAAK,gBAAgB;OACrB,EAAE,UAAU,EAAE;OAEd,EAAE,cAAc,EAAE;AAGzB,qBAAa,oBAAqB,SAAQ,WAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,iCAAiC,CAAC;IAIhD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,mBAAmB,CAAC;IAI3F;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,mBAAmB,CAAC;IAIlC;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,+BAA+B,CAAC;IAI3E;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;CAM3E;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iCAAiC;IAChD;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE7D;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,WAAW,oBAAoB,CAAC;IAC5C,OAAO,EACL,KAAK,mBAAmB,IAAI,mBAAmB,EAC/C,KAAK,iCAAiC,IAAI,iCAAiC,EAC3E,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,GACxE,CAAC;CACH"}
|
|
1
|
+
{"version":3,"file":"webhook-subscriptions.d.mts","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,KAAK,gBAAgB;OACrB,EAAE,UAAU,EAAE;OAEd,EAAE,cAAc,EAAE;AAGzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AACH,qBAAa,oBAAqB,SAAQ,WAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,iCAAiC,CAAC;IAIhD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,mBAAmB,CAAC;IAI3F;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,mBAAmB,CAAC;IAIlC;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,+BAA+B,CAAC;IAI3E;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;CAM3E;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iCAAiC;IAChD;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE7D;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,WAAW,oBAAoB,CAAC;IAC5C,OAAO,EACL,KAAK,mBAAmB,IAAI,mBAAmB,EAC/C,KAAK,iCAAiC,IAAI,iCAAiC,EAC3E,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,GACxE,CAAC;CACH"}
|
|
@@ -2,6 +2,95 @@ import { APIResource } from "../core/resource.js";
|
|
|
2
2
|
import * as WebhookEventsAPI from "./webhook-events.js";
|
|
3
3
|
import { APIPromise } from "../core/api-promise.js";
|
|
4
4
|
import { RequestOptions } from "../internal/request-options.js";
|
|
5
|
+
/**
|
|
6
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
7
|
+
* occur on your account.
|
|
8
|
+
*
|
|
9
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
10
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
11
|
+
*
|
|
12
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
13
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
14
|
+
* deduplication.
|
|
15
|
+
*
|
|
16
|
+
* ## Webhook Headers
|
|
17
|
+
*
|
|
18
|
+
* Each webhook request includes the following headers:
|
|
19
|
+
*
|
|
20
|
+
* | Header | Description |
|
|
21
|
+
* |--------|-------------|
|
|
22
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
23
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
24
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
25
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
26
|
+
*
|
|
27
|
+
* ## Verifying Webhook Signatures
|
|
28
|
+
*
|
|
29
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
30
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
31
|
+
*
|
|
32
|
+
* **Signature Construction:**
|
|
33
|
+
*
|
|
34
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
35
|
+
*
|
|
36
|
+
* ```
|
|
37
|
+
* {timestamp}.{payload}
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* Where:
|
|
41
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
42
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
43
|
+
*
|
|
44
|
+
* **Verification Steps:**
|
|
45
|
+
*
|
|
46
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
47
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
48
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
49
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
50
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
51
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
52
|
+
*
|
|
53
|
+
* **Example (Python):**
|
|
54
|
+
*
|
|
55
|
+
* ```python
|
|
56
|
+
* import hmac
|
|
57
|
+
* import hashlib
|
|
58
|
+
*
|
|
59
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
60
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
61
|
+
* expected = hmac.new(
|
|
62
|
+
* signing_secret.encode('utf-8'),
|
|
63
|
+
* message.encode('utf-8'),
|
|
64
|
+
* hashlib.sha256
|
|
65
|
+
* ).hexdigest()
|
|
66
|
+
* return hmac.compare_digest(expected, signature)
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* **Example (Node.js):**
|
|
70
|
+
*
|
|
71
|
+
* ```javascript
|
|
72
|
+
* const crypto = require('crypto');
|
|
73
|
+
*
|
|
74
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
75
|
+
* const message = `${timestamp}.${payload}`;
|
|
76
|
+
* const expected = crypto
|
|
77
|
+
* .createHmac('sha256', signingSecret)
|
|
78
|
+
* .update(message)
|
|
79
|
+
* .digest('hex');
|
|
80
|
+
* return crypto.timingSafeEqual(
|
|
81
|
+
* Buffer.from(expected),
|
|
82
|
+
* Buffer.from(signature)
|
|
83
|
+
* );
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* **Security Best Practices:**
|
|
88
|
+
*
|
|
89
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
90
|
+
* - Always use constant-time comparison for signature verification
|
|
91
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
92
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
93
|
+
*/
|
|
5
94
|
export declare class WebhookSubscriptions extends APIResource {
|
|
6
95
|
/**
|
|
7
96
|
* Create a new webhook subscription to receive events at a target URL. Upon
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-subscriptions.d.ts","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,KAAK,gBAAgB;OACrB,EAAE,UAAU,EAAE;OAEd,EAAE,cAAc,EAAE;AAGzB,qBAAa,oBAAqB,SAAQ,WAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,iCAAiC,CAAC;IAIhD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,mBAAmB,CAAC;IAI3F;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,mBAAmB,CAAC;IAIlC;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,+BAA+B,CAAC;IAI3E;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;CAM3E;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iCAAiC;IAChD;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE7D;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,WAAW,oBAAoB,CAAC;IAC5C,OAAO,EACL,KAAK,mBAAmB,IAAI,mBAAmB,EAC/C,KAAK,iCAAiC,IAAI,iCAAiC,EAC3E,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,GACxE,CAAC;CACH"}
|
|
1
|
+
{"version":3,"file":"webhook-subscriptions.d.ts","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,KAAK,gBAAgB;OACrB,EAAE,UAAU,EAAE;OAEd,EAAE,cAAc,EAAE;AAGzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AACH,qBAAa,oBAAqB,SAAQ,WAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,iCAAiC,CAAC;IAIhD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,mBAAmB,CAAC;IAI3F;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,mBAAmB,CAAC;IAIlC;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,+BAA+B,CAAC;IAI3E;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;CAM3E;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iCAAiC;IAChD;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,iBAAiB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE5D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAE7D;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,WAAW,oBAAoB,CAAC;IAC5C,OAAO,EACL,KAAK,mBAAmB,IAAI,mBAAmB,EAC/C,KAAK,iCAAiC,IAAI,iCAAiC,EAC3E,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,GACxE,CAAC;CACH"}
|
|
@@ -5,6 +5,95 @@ exports.WebhookSubscriptions = void 0;
|
|
|
5
5
|
const resource_1 = require("../core/resource.js");
|
|
6
6
|
const headers_1 = require("../internal/headers.js");
|
|
7
7
|
const path_1 = require("../internal/utils/path.js");
|
|
8
|
+
/**
|
|
9
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
10
|
+
* occur on your account.
|
|
11
|
+
*
|
|
12
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
13
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
14
|
+
*
|
|
15
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
16
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
17
|
+
* deduplication.
|
|
18
|
+
*
|
|
19
|
+
* ## Webhook Headers
|
|
20
|
+
*
|
|
21
|
+
* Each webhook request includes the following headers:
|
|
22
|
+
*
|
|
23
|
+
* | Header | Description |
|
|
24
|
+
* |--------|-------------|
|
|
25
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
26
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
27
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
28
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
29
|
+
*
|
|
30
|
+
* ## Verifying Webhook Signatures
|
|
31
|
+
*
|
|
32
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
33
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
34
|
+
*
|
|
35
|
+
* **Signature Construction:**
|
|
36
|
+
*
|
|
37
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
38
|
+
*
|
|
39
|
+
* ```
|
|
40
|
+
* {timestamp}.{payload}
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* Where:
|
|
44
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
45
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
46
|
+
*
|
|
47
|
+
* **Verification Steps:**
|
|
48
|
+
*
|
|
49
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
50
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
51
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
52
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
53
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
54
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
55
|
+
*
|
|
56
|
+
* **Example (Python):**
|
|
57
|
+
*
|
|
58
|
+
* ```python
|
|
59
|
+
* import hmac
|
|
60
|
+
* import hashlib
|
|
61
|
+
*
|
|
62
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
63
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
64
|
+
* expected = hmac.new(
|
|
65
|
+
* signing_secret.encode('utf-8'),
|
|
66
|
+
* message.encode('utf-8'),
|
|
67
|
+
* hashlib.sha256
|
|
68
|
+
* ).hexdigest()
|
|
69
|
+
* return hmac.compare_digest(expected, signature)
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* **Example (Node.js):**
|
|
73
|
+
*
|
|
74
|
+
* ```javascript
|
|
75
|
+
* const crypto = require('crypto');
|
|
76
|
+
*
|
|
77
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
78
|
+
* const message = `${timestamp}.${payload}`;
|
|
79
|
+
* const expected = crypto
|
|
80
|
+
* .createHmac('sha256', signingSecret)
|
|
81
|
+
* .update(message)
|
|
82
|
+
* .digest('hex');
|
|
83
|
+
* return crypto.timingSafeEqual(
|
|
84
|
+
* Buffer.from(expected),
|
|
85
|
+
* Buffer.from(signature)
|
|
86
|
+
* );
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* **Security Best Practices:**
|
|
91
|
+
*
|
|
92
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
93
|
+
* - Always use constant-time comparison for signature verification
|
|
94
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
95
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
96
|
+
*/
|
|
8
97
|
class WebhookSubscriptions extends resource_1.APIResource {
|
|
9
98
|
/**
|
|
10
99
|
* Create a new webhook subscription to receive events at a target URL. Upon
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-subscriptions.js","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;AAEtF,kDAA+C;AAG/C,oDAAmD;AAEnD,oDAA8C;AAE9C,MAAa,oBAAqB,SAAQ,sBAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAsB,EAAE,OAAwB;QACvD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAA,WAAI,EAAA,6BAA6B,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;IACtF,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAsB,EACtB,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAA,WAAI,EAAA,6BAA6B,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnG,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAwB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAsB,EAAE,OAAwB;QACrD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAA,WAAI,EAAA,6BAA6B,cAAc,EAAE,EAAE;YAC5E,GAAG,OAAO;YACV,OAAO,EAAE,IAAA,sBAAY,EAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC;CACF;AA5GD,oDA4GC"}
|
|
1
|
+
{"version":3,"file":"webhook-subscriptions.js","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;AAEtF,kDAA+C;AAG/C,oDAAmD;AAEnD,oDAA8C;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AACH,MAAa,oBAAqB,SAAQ,sBAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAsB,EAAE,OAAwB;QACvD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAA,WAAI,EAAA,6BAA6B,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;IACtF,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAsB,EACtB,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAA,WAAI,EAAA,6BAA6B,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnG,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAwB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAsB,EAAE,OAAwB;QACrD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAA,WAAI,EAAA,6BAA6B,cAAc,EAAE,EAAE;YAC5E,GAAG,OAAO;YACV,OAAO,EAAE,IAAA,sBAAY,EAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC;CACF;AA5GD,oDA4GC"}
|
|
@@ -2,6 +2,95 @@
|
|
|
2
2
|
import { APIResource } from "../core/resource.mjs";
|
|
3
3
|
import { buildHeaders } from "../internal/headers.mjs";
|
|
4
4
|
import { path } from "../internal/utils/path.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
7
|
+
* occur on your account.
|
|
8
|
+
*
|
|
9
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
10
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
11
|
+
*
|
|
12
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
13
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
14
|
+
* deduplication.
|
|
15
|
+
*
|
|
16
|
+
* ## Webhook Headers
|
|
17
|
+
*
|
|
18
|
+
* Each webhook request includes the following headers:
|
|
19
|
+
*
|
|
20
|
+
* | Header | Description |
|
|
21
|
+
* |--------|-------------|
|
|
22
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
23
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
24
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
25
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
26
|
+
*
|
|
27
|
+
* ## Verifying Webhook Signatures
|
|
28
|
+
*
|
|
29
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
30
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
31
|
+
*
|
|
32
|
+
* **Signature Construction:**
|
|
33
|
+
*
|
|
34
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
35
|
+
*
|
|
36
|
+
* ```
|
|
37
|
+
* {timestamp}.{payload}
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* Where:
|
|
41
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
42
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
43
|
+
*
|
|
44
|
+
* **Verification Steps:**
|
|
45
|
+
*
|
|
46
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
47
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
48
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
49
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
50
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
51
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
52
|
+
*
|
|
53
|
+
* **Example (Python):**
|
|
54
|
+
*
|
|
55
|
+
* ```python
|
|
56
|
+
* import hmac
|
|
57
|
+
* import hashlib
|
|
58
|
+
*
|
|
59
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
60
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
61
|
+
* expected = hmac.new(
|
|
62
|
+
* signing_secret.encode('utf-8'),
|
|
63
|
+
* message.encode('utf-8'),
|
|
64
|
+
* hashlib.sha256
|
|
65
|
+
* ).hexdigest()
|
|
66
|
+
* return hmac.compare_digest(expected, signature)
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* **Example (Node.js):**
|
|
70
|
+
*
|
|
71
|
+
* ```javascript
|
|
72
|
+
* const crypto = require('crypto');
|
|
73
|
+
*
|
|
74
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
75
|
+
* const message = `${timestamp}.${payload}`;
|
|
76
|
+
* const expected = crypto
|
|
77
|
+
* .createHmac('sha256', signingSecret)
|
|
78
|
+
* .update(message)
|
|
79
|
+
* .digest('hex');
|
|
80
|
+
* return crypto.timingSafeEqual(
|
|
81
|
+
* Buffer.from(expected),
|
|
82
|
+
* Buffer.from(signature)
|
|
83
|
+
* );
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* **Security Best Practices:**
|
|
88
|
+
*
|
|
89
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
90
|
+
* - Always use constant-time comparison for signature verification
|
|
91
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
92
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
93
|
+
*/
|
|
5
94
|
export class WebhookSubscriptions extends APIResource {
|
|
6
95
|
/**
|
|
7
96
|
* Create a new webhook subscription to receive events at a target URL. Upon
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-subscriptions.mjs","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,WAAW,EAAE;OAGf,EAAE,YAAY,EAAE;OAEhB,EAAE,IAAI,EAAE;AAEf,MAAM,OAAO,oBAAqB,SAAQ,WAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAsB,EAAE,OAAwB;QACvD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA,6BAA6B,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;IACtF,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAsB,EACtB,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA,6BAA6B,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnG,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAwB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAsB,EAAE,OAAwB;QACrD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAA,6BAA6B,cAAc,EAAE,EAAE;YAC5E,GAAG,OAAO;YACV,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"webhook-subscriptions.mjs","sourceRoot":"","sources":["../src/resources/webhook-subscriptions.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,WAAW,EAAE;OAGf,EAAE,YAAY,EAAE;OAEhB,EAAE,IAAI,EAAE;AAEf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AACH,MAAM,OAAO,oBAAqB,SAAQ,WAAW;IACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CACJ,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAsB,EAAE,OAAwB;QACvD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA,6BAA6B,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;IACtF,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,cAAsB,EACtB,IAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA,6BAA6B,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnG,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAwB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAsB,EAAE,OAAwB;QACrD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAA,6BAA6B,cAAc,EAAE,EAAE;YAC5E,GAAG,OAAO;YACV,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC;CACF"}
|