@linqapp/sdk 0.1.5 → 0.2.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 +20 -0
- package/client.d.mts +280 -1
- package/client.d.mts.map +1 -1
- package/client.d.ts +280 -1
- package/client.d.ts.map +1 -1
- package/client.js +281 -12
- package/client.js.map +1 -1
- package/client.mjs +281 -12
- package/client.mjs.map +1 -1
- 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 +1 -1
- 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 +3 -0
- package/resources/capability.d.mts.map +1 -1
- package/resources/capability.d.ts +3 -0
- package/resources/capability.d.ts.map +1 -1
- package/resources/capability.js +3 -0
- package/resources/capability.js.map +1 -1
- package/resources/capability.mjs +3 -0
- package/resources/capability.mjs.map +1 -1
- package/resources/chats/chats.d.mts +9 -13
- package/resources/chats/chats.d.mts.map +1 -1
- package/resources/chats/chats.d.ts +9 -13
- package/resources/chats/chats.d.ts.map +1 -1
- package/resources/chats/chats.js.map +1 -1
- package/resources/chats/chats.mjs.map +1 -1
- package/resources/chats/messages.d.mts +9 -0
- package/resources/chats/messages.d.mts.map +1 -1
- package/resources/chats/messages.d.ts +9 -0
- package/resources/chats/messages.d.ts.map +1 -1
- package/resources/chats/messages.js +9 -0
- package/resources/chats/messages.js.map +1 -1
- package/resources/chats/messages.mjs +9 -0
- 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/messages.d.mts +9 -0
- package/resources/messages.d.mts.map +1 -1
- package/resources/messages.d.ts +9 -0
- package/resources/messages.d.ts.map +1 -1
- package/resources/messages.js +9 -0
- package/resources/messages.js.map +1 -1
- package/resources/messages.mjs +9 -0
- 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/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/src/client.ts +284 -17
- package/src/internal/utils/query.ts +23 -0
- package/src/internal/utils.ts +1 -0
- package/src/resources/attachments.ts +64 -0
- package/src/resources/capability.ts +3 -0
- package/src/resources/chats/chats.ts +9 -15
- package/src/resources/chats/messages.ts +9 -0
- package/src/resources/chats/participants.ts +18 -0
- package/src/resources/chats/typing.ts +18 -0
- package/src/resources/messages.ts +9 -0
- package/src/resources/phone-numbers.ts +9 -0
- package/src/resources/phonenumbers.ts +9 -0
- package/src/resources/webhook-events.ts +90 -0
- package/src/resources/webhook-subscriptions.ts +89 -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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 (2026-03-05)
|
|
4
|
+
|
|
5
|
+
Full Changelog: [v0.1.5...v0.2.0](https://github.com/linq-team/linq-node/compare/v0.1.5...v0.2.0)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* Allow 100 presigned URL or uploaded attachments (URL + ID) in a message ([adb1e81](https://github.com/linq-team/linq-node/commit/adb1e812c68ab101e2f1362a3c53602dc9c589af))
|
|
10
|
+
* Plt 361 synapse support editing messages in v3 ([68d7b8a](https://github.com/linq-team/linq-node/commit/68d7b8afbc158ecb3fd0ce85e9ca8c0ad324b6bc))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* remove unused part-level idempotency_key from OpenAPI spec ([24df345](https://github.com/linq-team/linq-node/commit/24df345db930e173b4618ce04819dd9dc021aa02))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Chores
|
|
19
|
+
|
|
20
|
+
* **internal:** codegen related update ([3c28377](https://github.com/linq-team/linq-node/commit/3c283771a2d2ff459ed32f289d2e03fa379278af))
|
|
21
|
+
* **internal:** move stringifyQuery implementation to internal function ([b86f2c0](https://github.com/linq-team/linq-node/commit/b86f2c05a2c2e2b2ea4fe1df03c70b27f35def30))
|
|
22
|
+
|
|
3
23
|
## 0.1.5 (2026-02-24)
|
|
4
24
|
|
|
5
25
|
Full Changelog: [v0.1.4...v0.1.5](https://github.com/linq-team/linq-node/compare/v0.1.4...v0.1.5)
|
package/client.d.mts
CHANGED
|
@@ -125,7 +125,7 @@ export declare class LinqAPIV3 {
|
|
|
125
125
|
/**
|
|
126
126
|
* Basic re-implementation of `qs.stringify` for primitive types.
|
|
127
127
|
*/
|
|
128
|
-
protected stringifyQuery(query: Record<string, unknown>): string;
|
|
128
|
+
protected stringifyQuery(query: object | Record<string, unknown>): string;
|
|
129
129
|
private getUserAgent;
|
|
130
130
|
protected defaultIdempotencyKey(): string;
|
|
131
131
|
protected makeStatusError(status: number, error: Object, message: string | undefined, headers: Headers): Errors.APIError;
|
|
@@ -183,12 +183,291 @@ export declare class LinqAPIV3 {
|
|
|
183
183
|
static UnprocessableEntityError: typeof Errors.UnprocessableEntityError;
|
|
184
184
|
static toFile: typeof Uploads.toFile;
|
|
185
185
|
chats: API.Chats;
|
|
186
|
+
/**
|
|
187
|
+
* Messages are individual text or multimedia communications within a chat thread.
|
|
188
|
+
*
|
|
189
|
+
* Messages can include text, attachments, special effects (like confetti or fireworks),
|
|
190
|
+
* and reactions. All messages are associated with a specific chat and sent from a
|
|
191
|
+
* phone number you own.
|
|
192
|
+
*
|
|
193
|
+
* Messages support delivery status tracking, read receipts, and editing capabilities.
|
|
194
|
+
*
|
|
195
|
+
*/
|
|
186
196
|
messages: API.Messages;
|
|
197
|
+
/**
|
|
198
|
+
* Send files (images, videos, documents, audio) with messages by providing a URL in a media part.
|
|
199
|
+
* Pre-uploading via `POST /v3/attachments` is **optional** and only needed for specific optimization scenarios.
|
|
200
|
+
*
|
|
201
|
+
* ## Sending Media via URL (up to 10MB)
|
|
202
|
+
*
|
|
203
|
+
* Provide a publicly accessible HTTPS URL with a [supported media type](#supported-file-types) in the `url` field of a media part.
|
|
204
|
+
*
|
|
205
|
+
* ```json
|
|
206
|
+
* {
|
|
207
|
+
* "parts": [
|
|
208
|
+
* { "type": "media", "url": "https://your-cdn.com/images/photo.jpg" }
|
|
209
|
+
* ]
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* This works with any URL you already host — no pre-upload step required. **Maximum file size: 10MB.**
|
|
214
|
+
*
|
|
215
|
+
* ## Pre-Upload (required for files over 10MB)
|
|
216
|
+
*
|
|
217
|
+
* Use `POST /v3/attachments` when you want to:
|
|
218
|
+
* - **Send files larger than 10MB** (up to 100MB) — URL-based downloads are limited to 10MB
|
|
219
|
+
* - **Send the same file to many recipients** — upload once, reuse the `attachment_id` without re-downloading each time
|
|
220
|
+
* - **Reduce message send latency** — the file is already stored, so sending is faster
|
|
221
|
+
*
|
|
222
|
+
* **How it works:**
|
|
223
|
+
* 1. `POST /v3/attachments` with file metadata → returns a presigned `upload_url` (valid for **15 minutes**) and a permanent `attachment_id`
|
|
224
|
+
* 2. PUT the raw file bytes to the `upload_url` with the `required_headers` (no JSON or multipart — just the binary content)
|
|
225
|
+
* 3. Reference the `attachment_id` in your media part when sending messages (no expiration)
|
|
226
|
+
*
|
|
227
|
+
* **Key difference:** When you provide an external `url`, we download and process the file on every send.
|
|
228
|
+
* When you use a pre-uploaded `attachment_id`, the file is already stored — so repeated sends skip the download step entirely.
|
|
229
|
+
*
|
|
230
|
+
* ## Domain Allowlisting
|
|
231
|
+
*
|
|
232
|
+
* Attachment URLs in API responses are served from `cdn.linqapp.com`. This includes:
|
|
233
|
+
* - `url` fields in media and voice memo message parts
|
|
234
|
+
* - `download_url` fields in attachment and upload response objects
|
|
235
|
+
*
|
|
236
|
+
* If your application enforces domain allowlists (e.g., for SSRF protection), add:
|
|
237
|
+
*
|
|
238
|
+
* ```
|
|
239
|
+
* cdn.linqapp.com
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* ## Supported File Types
|
|
243
|
+
*
|
|
244
|
+
* - **Images:** JPEG, PNG, GIF, HEIC, HEIF, TIFF, BMP
|
|
245
|
+
* - **Videos:** MP4, MOV, M4V
|
|
246
|
+
* - **Audio:** M4A, AAC, MP3, WAV, AIFF, CAF, AMR
|
|
247
|
+
* - **Documents:** PDF, TXT, RTF, CSV, Office formats, ZIP
|
|
248
|
+
* - **Contact & Calendar:** VCF, ICS
|
|
249
|
+
*
|
|
250
|
+
* ## Audio: Attachment vs Voice Memo
|
|
251
|
+
*
|
|
252
|
+
* Audio files sent as media parts appear as **downloadable file attachments** in iMessage.
|
|
253
|
+
* To send audio as an **iMessage voice memo bubble** (with native inline playback UI),
|
|
254
|
+
* use the dedicated `POST /v3/chats/{chatId}/voicememo` endpoint instead.
|
|
255
|
+
*
|
|
256
|
+
* ## File Size Limits
|
|
257
|
+
*
|
|
258
|
+
* - **URL-based (`url` field):** 10MB maximum
|
|
259
|
+
* - **Pre-upload (`attachment_id`):** 100MB maximum
|
|
260
|
+
*
|
|
261
|
+
*/
|
|
187
262
|
attachments: API.Attachments;
|
|
263
|
+
/**
|
|
264
|
+
* Phone Numbers represent the phone numbers assigned to your partner account.
|
|
265
|
+
*
|
|
266
|
+
* Use the list phone numbers endpoint to discover which phone numbers are available
|
|
267
|
+
* for sending messages.
|
|
268
|
+
*
|
|
269
|
+
* When creating chats, listing chats, or sending a voice memo, use one of your assigned phone numbers
|
|
270
|
+
* in the `from` field.
|
|
271
|
+
*
|
|
272
|
+
*/
|
|
188
273
|
phonenumbers: API.Phonenumbers;
|
|
274
|
+
/**
|
|
275
|
+
* Phone Numbers represent the phone numbers assigned to your partner account.
|
|
276
|
+
*
|
|
277
|
+
* Use the list phone numbers endpoint to discover which phone numbers are available
|
|
278
|
+
* for sending messages.
|
|
279
|
+
*
|
|
280
|
+
* When creating chats, listing chats, or sending a voice memo, use one of your assigned phone numbers
|
|
281
|
+
* in the `from` field.
|
|
282
|
+
*
|
|
283
|
+
*/
|
|
189
284
|
phoneNumbers: API.PhoneNumbers;
|
|
285
|
+
/**
|
|
286
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
287
|
+
* occur on your account.
|
|
288
|
+
*
|
|
289
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
290
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
291
|
+
*
|
|
292
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
293
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
294
|
+
* deduplication.
|
|
295
|
+
*
|
|
296
|
+
* ## Webhook Headers
|
|
297
|
+
*
|
|
298
|
+
* Each webhook request includes the following headers:
|
|
299
|
+
*
|
|
300
|
+
* | Header | Description |
|
|
301
|
+
* |--------|-------------|
|
|
302
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
303
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
304
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
305
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
306
|
+
*
|
|
307
|
+
* ## Verifying Webhook Signatures
|
|
308
|
+
*
|
|
309
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
310
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
311
|
+
*
|
|
312
|
+
* **Signature Construction:**
|
|
313
|
+
*
|
|
314
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
315
|
+
*
|
|
316
|
+
* ```
|
|
317
|
+
* {timestamp}.{payload}
|
|
318
|
+
* ```
|
|
319
|
+
*
|
|
320
|
+
* Where:
|
|
321
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
322
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
323
|
+
*
|
|
324
|
+
* **Verification Steps:**
|
|
325
|
+
*
|
|
326
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
327
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
328
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
329
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
330
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
331
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
332
|
+
*
|
|
333
|
+
* **Example (Python):**
|
|
334
|
+
*
|
|
335
|
+
* ```python
|
|
336
|
+
* import hmac
|
|
337
|
+
* import hashlib
|
|
338
|
+
*
|
|
339
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
340
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
341
|
+
* expected = hmac.new(
|
|
342
|
+
* signing_secret.encode('utf-8'),
|
|
343
|
+
* message.encode('utf-8'),
|
|
344
|
+
* hashlib.sha256
|
|
345
|
+
* ).hexdigest()
|
|
346
|
+
* return hmac.compare_digest(expected, signature)
|
|
347
|
+
* ```
|
|
348
|
+
*
|
|
349
|
+
* **Example (Node.js):**
|
|
350
|
+
*
|
|
351
|
+
* ```javascript
|
|
352
|
+
* const crypto = require('crypto');
|
|
353
|
+
*
|
|
354
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
355
|
+
* const message = `${timestamp}.${payload}`;
|
|
356
|
+
* const expected = crypto
|
|
357
|
+
* .createHmac('sha256', signingSecret)
|
|
358
|
+
* .update(message)
|
|
359
|
+
* .digest('hex');
|
|
360
|
+
* return crypto.timingSafeEqual(
|
|
361
|
+
* Buffer.from(expected),
|
|
362
|
+
* Buffer.from(signature)
|
|
363
|
+
* );
|
|
364
|
+
* }
|
|
365
|
+
* ```
|
|
366
|
+
*
|
|
367
|
+
* **Security Best Practices:**
|
|
368
|
+
*
|
|
369
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
370
|
+
* - Always use constant-time comparison for signature verification
|
|
371
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
372
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
373
|
+
*
|
|
374
|
+
*/
|
|
190
375
|
webhookEvents: API.WebhookEvents;
|
|
376
|
+
/**
|
|
377
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
378
|
+
* occur on your account.
|
|
379
|
+
*
|
|
380
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
381
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
382
|
+
*
|
|
383
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
384
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
385
|
+
* deduplication.
|
|
386
|
+
*
|
|
387
|
+
* ## Webhook Headers
|
|
388
|
+
*
|
|
389
|
+
* Each webhook request includes the following headers:
|
|
390
|
+
*
|
|
391
|
+
* | Header | Description |
|
|
392
|
+
* |--------|-------------|
|
|
393
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
394
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
395
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
396
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
397
|
+
*
|
|
398
|
+
* ## Verifying Webhook Signatures
|
|
399
|
+
*
|
|
400
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
401
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
402
|
+
*
|
|
403
|
+
* **Signature Construction:**
|
|
404
|
+
*
|
|
405
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
406
|
+
*
|
|
407
|
+
* ```
|
|
408
|
+
* {timestamp}.{payload}
|
|
409
|
+
* ```
|
|
410
|
+
*
|
|
411
|
+
* Where:
|
|
412
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
413
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
414
|
+
*
|
|
415
|
+
* **Verification Steps:**
|
|
416
|
+
*
|
|
417
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
418
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
419
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
420
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
421
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
422
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
423
|
+
*
|
|
424
|
+
* **Example (Python):**
|
|
425
|
+
*
|
|
426
|
+
* ```python
|
|
427
|
+
* import hmac
|
|
428
|
+
* import hashlib
|
|
429
|
+
*
|
|
430
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
431
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
432
|
+
* expected = hmac.new(
|
|
433
|
+
* signing_secret.encode('utf-8'),
|
|
434
|
+
* message.encode('utf-8'),
|
|
435
|
+
* hashlib.sha256
|
|
436
|
+
* ).hexdigest()
|
|
437
|
+
* return hmac.compare_digest(expected, signature)
|
|
438
|
+
* ```
|
|
439
|
+
*
|
|
440
|
+
* **Example (Node.js):**
|
|
441
|
+
*
|
|
442
|
+
* ```javascript
|
|
443
|
+
* const crypto = require('crypto');
|
|
444
|
+
*
|
|
445
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
446
|
+
* const message = `${timestamp}.${payload}`;
|
|
447
|
+
* const expected = crypto
|
|
448
|
+
* .createHmac('sha256', signingSecret)
|
|
449
|
+
* .update(message)
|
|
450
|
+
* .digest('hex');
|
|
451
|
+
* return crypto.timingSafeEqual(
|
|
452
|
+
* Buffer.from(expected),
|
|
453
|
+
* Buffer.from(signature)
|
|
454
|
+
* );
|
|
455
|
+
* }
|
|
456
|
+
* ```
|
|
457
|
+
*
|
|
458
|
+
* **Security Best Practices:**
|
|
459
|
+
*
|
|
460
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
461
|
+
* - Always use constant-time comparison for signature verification
|
|
462
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
463
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
464
|
+
*
|
|
465
|
+
*/
|
|
191
466
|
webhookSubscriptions: API.WebhookSubscriptions;
|
|
467
|
+
/**
|
|
468
|
+
* Check whether a recipient address supports iMessage or RCS before sending a message.
|
|
469
|
+
*
|
|
470
|
+
*/
|
|
192
471
|
capability: API.Capability;
|
|
193
472
|
}
|
|
194
473
|
export declare namespace LinqAPIV3 {
|
package/client.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.mts","sourceRoot":"","sources":["src/client.ts"],"names":[],"mappings":"OAEO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAY;OAC3C,KAAK,EAAc,cAAc,EAAE,iBAAiB,EAAE,oBAAoB,EAAE;YAIvE,EAAE,MAAM,EAAE,QAAQ,EAAE;OAKzB,KAAK,IAAI;
|
|
1
|
+
{"version":3,"file":"client.d.mts","sourceRoot":"","sources":["src/client.ts"],"names":[],"mappings":"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"}
|
package/client.d.ts
CHANGED
|
@@ -125,7 +125,7 @@ export declare class LinqAPIV3 {
|
|
|
125
125
|
/**
|
|
126
126
|
* Basic re-implementation of `qs.stringify` for primitive types.
|
|
127
127
|
*/
|
|
128
|
-
protected stringifyQuery(query: Record<string, unknown>): string;
|
|
128
|
+
protected stringifyQuery(query: object | Record<string, unknown>): string;
|
|
129
129
|
private getUserAgent;
|
|
130
130
|
protected defaultIdempotencyKey(): string;
|
|
131
131
|
protected makeStatusError(status: number, error: Object, message: string | undefined, headers: Headers): Errors.APIError;
|
|
@@ -183,12 +183,291 @@ export declare class LinqAPIV3 {
|
|
|
183
183
|
static UnprocessableEntityError: typeof Errors.UnprocessableEntityError;
|
|
184
184
|
static toFile: typeof Uploads.toFile;
|
|
185
185
|
chats: API.Chats;
|
|
186
|
+
/**
|
|
187
|
+
* Messages are individual text or multimedia communications within a chat thread.
|
|
188
|
+
*
|
|
189
|
+
* Messages can include text, attachments, special effects (like confetti or fireworks),
|
|
190
|
+
* and reactions. All messages are associated with a specific chat and sent from a
|
|
191
|
+
* phone number you own.
|
|
192
|
+
*
|
|
193
|
+
* Messages support delivery status tracking, read receipts, and editing capabilities.
|
|
194
|
+
*
|
|
195
|
+
*/
|
|
186
196
|
messages: API.Messages;
|
|
197
|
+
/**
|
|
198
|
+
* Send files (images, videos, documents, audio) with messages by providing a URL in a media part.
|
|
199
|
+
* Pre-uploading via `POST /v3/attachments` is **optional** and only needed for specific optimization scenarios.
|
|
200
|
+
*
|
|
201
|
+
* ## Sending Media via URL (up to 10MB)
|
|
202
|
+
*
|
|
203
|
+
* Provide a publicly accessible HTTPS URL with a [supported media type](#supported-file-types) in the `url` field of a media part.
|
|
204
|
+
*
|
|
205
|
+
* ```json
|
|
206
|
+
* {
|
|
207
|
+
* "parts": [
|
|
208
|
+
* { "type": "media", "url": "https://your-cdn.com/images/photo.jpg" }
|
|
209
|
+
* ]
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* This works with any URL you already host — no pre-upload step required. **Maximum file size: 10MB.**
|
|
214
|
+
*
|
|
215
|
+
* ## Pre-Upload (required for files over 10MB)
|
|
216
|
+
*
|
|
217
|
+
* Use `POST /v3/attachments` when you want to:
|
|
218
|
+
* - **Send files larger than 10MB** (up to 100MB) — URL-based downloads are limited to 10MB
|
|
219
|
+
* - **Send the same file to many recipients** — upload once, reuse the `attachment_id` without re-downloading each time
|
|
220
|
+
* - **Reduce message send latency** — the file is already stored, so sending is faster
|
|
221
|
+
*
|
|
222
|
+
* **How it works:**
|
|
223
|
+
* 1. `POST /v3/attachments` with file metadata → returns a presigned `upload_url` (valid for **15 minutes**) and a permanent `attachment_id`
|
|
224
|
+
* 2. PUT the raw file bytes to the `upload_url` with the `required_headers` (no JSON or multipart — just the binary content)
|
|
225
|
+
* 3. Reference the `attachment_id` in your media part when sending messages (no expiration)
|
|
226
|
+
*
|
|
227
|
+
* **Key difference:** When you provide an external `url`, we download and process the file on every send.
|
|
228
|
+
* When you use a pre-uploaded `attachment_id`, the file is already stored — so repeated sends skip the download step entirely.
|
|
229
|
+
*
|
|
230
|
+
* ## Domain Allowlisting
|
|
231
|
+
*
|
|
232
|
+
* Attachment URLs in API responses are served from `cdn.linqapp.com`. This includes:
|
|
233
|
+
* - `url` fields in media and voice memo message parts
|
|
234
|
+
* - `download_url` fields in attachment and upload response objects
|
|
235
|
+
*
|
|
236
|
+
* If your application enforces domain allowlists (e.g., for SSRF protection), add:
|
|
237
|
+
*
|
|
238
|
+
* ```
|
|
239
|
+
* cdn.linqapp.com
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* ## Supported File Types
|
|
243
|
+
*
|
|
244
|
+
* - **Images:** JPEG, PNG, GIF, HEIC, HEIF, TIFF, BMP
|
|
245
|
+
* - **Videos:** MP4, MOV, M4V
|
|
246
|
+
* - **Audio:** M4A, AAC, MP3, WAV, AIFF, CAF, AMR
|
|
247
|
+
* - **Documents:** PDF, TXT, RTF, CSV, Office formats, ZIP
|
|
248
|
+
* - **Contact & Calendar:** VCF, ICS
|
|
249
|
+
*
|
|
250
|
+
* ## Audio: Attachment vs Voice Memo
|
|
251
|
+
*
|
|
252
|
+
* Audio files sent as media parts appear as **downloadable file attachments** in iMessage.
|
|
253
|
+
* To send audio as an **iMessage voice memo bubble** (with native inline playback UI),
|
|
254
|
+
* use the dedicated `POST /v3/chats/{chatId}/voicememo` endpoint instead.
|
|
255
|
+
*
|
|
256
|
+
* ## File Size Limits
|
|
257
|
+
*
|
|
258
|
+
* - **URL-based (`url` field):** 10MB maximum
|
|
259
|
+
* - **Pre-upload (`attachment_id`):** 100MB maximum
|
|
260
|
+
*
|
|
261
|
+
*/
|
|
187
262
|
attachments: API.Attachments;
|
|
263
|
+
/**
|
|
264
|
+
* Phone Numbers represent the phone numbers assigned to your partner account.
|
|
265
|
+
*
|
|
266
|
+
* Use the list phone numbers endpoint to discover which phone numbers are available
|
|
267
|
+
* for sending messages.
|
|
268
|
+
*
|
|
269
|
+
* When creating chats, listing chats, or sending a voice memo, use one of your assigned phone numbers
|
|
270
|
+
* in the `from` field.
|
|
271
|
+
*
|
|
272
|
+
*/
|
|
188
273
|
phonenumbers: API.Phonenumbers;
|
|
274
|
+
/**
|
|
275
|
+
* Phone Numbers represent the phone numbers assigned to your partner account.
|
|
276
|
+
*
|
|
277
|
+
* Use the list phone numbers endpoint to discover which phone numbers are available
|
|
278
|
+
* for sending messages.
|
|
279
|
+
*
|
|
280
|
+
* When creating chats, listing chats, or sending a voice memo, use one of your assigned phone numbers
|
|
281
|
+
* in the `from` field.
|
|
282
|
+
*
|
|
283
|
+
*/
|
|
189
284
|
phoneNumbers: API.PhoneNumbers;
|
|
285
|
+
/**
|
|
286
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
287
|
+
* occur on your account.
|
|
288
|
+
*
|
|
289
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
290
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
291
|
+
*
|
|
292
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
293
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
294
|
+
* deduplication.
|
|
295
|
+
*
|
|
296
|
+
* ## Webhook Headers
|
|
297
|
+
*
|
|
298
|
+
* Each webhook request includes the following headers:
|
|
299
|
+
*
|
|
300
|
+
* | Header | Description |
|
|
301
|
+
* |--------|-------------|
|
|
302
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
303
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
304
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
305
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
306
|
+
*
|
|
307
|
+
* ## Verifying Webhook Signatures
|
|
308
|
+
*
|
|
309
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
310
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
311
|
+
*
|
|
312
|
+
* **Signature Construction:**
|
|
313
|
+
*
|
|
314
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
315
|
+
*
|
|
316
|
+
* ```
|
|
317
|
+
* {timestamp}.{payload}
|
|
318
|
+
* ```
|
|
319
|
+
*
|
|
320
|
+
* Where:
|
|
321
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
322
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
323
|
+
*
|
|
324
|
+
* **Verification Steps:**
|
|
325
|
+
*
|
|
326
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
327
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
328
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
329
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
330
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
331
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
332
|
+
*
|
|
333
|
+
* **Example (Python):**
|
|
334
|
+
*
|
|
335
|
+
* ```python
|
|
336
|
+
* import hmac
|
|
337
|
+
* import hashlib
|
|
338
|
+
*
|
|
339
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
340
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
341
|
+
* expected = hmac.new(
|
|
342
|
+
* signing_secret.encode('utf-8'),
|
|
343
|
+
* message.encode('utf-8'),
|
|
344
|
+
* hashlib.sha256
|
|
345
|
+
* ).hexdigest()
|
|
346
|
+
* return hmac.compare_digest(expected, signature)
|
|
347
|
+
* ```
|
|
348
|
+
*
|
|
349
|
+
* **Example (Node.js):**
|
|
350
|
+
*
|
|
351
|
+
* ```javascript
|
|
352
|
+
* const crypto = require('crypto');
|
|
353
|
+
*
|
|
354
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
355
|
+
* const message = `${timestamp}.${payload}`;
|
|
356
|
+
* const expected = crypto
|
|
357
|
+
* .createHmac('sha256', signingSecret)
|
|
358
|
+
* .update(message)
|
|
359
|
+
* .digest('hex');
|
|
360
|
+
* return crypto.timingSafeEqual(
|
|
361
|
+
* Buffer.from(expected),
|
|
362
|
+
* Buffer.from(signature)
|
|
363
|
+
* );
|
|
364
|
+
* }
|
|
365
|
+
* ```
|
|
366
|
+
*
|
|
367
|
+
* **Security Best Practices:**
|
|
368
|
+
*
|
|
369
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
370
|
+
* - Always use constant-time comparison for signature verification
|
|
371
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
372
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
373
|
+
*
|
|
374
|
+
*/
|
|
190
375
|
webhookEvents: API.WebhookEvents;
|
|
376
|
+
/**
|
|
377
|
+
* Webhook Subscriptions allow you to receive real-time notifications when events
|
|
378
|
+
* occur on your account.
|
|
379
|
+
*
|
|
380
|
+
* Configure webhook endpoints to receive events such as messages sent/received,
|
|
381
|
+
* delivery status changes, reactions, typing indicators, and more.
|
|
382
|
+
*
|
|
383
|
+
* Failed deliveries (5xx, 429, network errors) are retried up to 10 times over
|
|
384
|
+
* ~2 hours with exponential backoff. Each event includes a unique ID for
|
|
385
|
+
* deduplication.
|
|
386
|
+
*
|
|
387
|
+
* ## Webhook Headers
|
|
388
|
+
*
|
|
389
|
+
* Each webhook request includes the following headers:
|
|
390
|
+
*
|
|
391
|
+
* | Header | Description |
|
|
392
|
+
* |--------|-------------|
|
|
393
|
+
* | `X-Webhook-Event` | The event type (e.g., `message.sent`, `message.received`) |
|
|
394
|
+
* | `X-Webhook-Subscription-ID` | Your webhook subscription ID |
|
|
395
|
+
* | `X-Webhook-Timestamp` | Unix timestamp (seconds) when the webhook was sent |
|
|
396
|
+
* | `X-Webhook-Signature` | HMAC-SHA256 signature for verification |
|
|
397
|
+
*
|
|
398
|
+
* ## Verifying Webhook Signatures
|
|
399
|
+
*
|
|
400
|
+
* All webhooks are signed using HMAC-SHA256. You should always verify the signature
|
|
401
|
+
* to ensure the webhook originated from Linq and hasn't been tampered with.
|
|
402
|
+
*
|
|
403
|
+
* **Signature Construction:**
|
|
404
|
+
*
|
|
405
|
+
* The signature is computed over a concatenation of the timestamp and payload:
|
|
406
|
+
*
|
|
407
|
+
* ```
|
|
408
|
+
* {timestamp}.{payload}
|
|
409
|
+
* ```
|
|
410
|
+
*
|
|
411
|
+
* Where:
|
|
412
|
+
* - `timestamp` is the value from the `X-Webhook-Timestamp` header
|
|
413
|
+
* - `payload` is the raw JSON request body (exact bytes, not re-serialized)
|
|
414
|
+
*
|
|
415
|
+
* **Verification Steps:**
|
|
416
|
+
*
|
|
417
|
+
* 1. Extract the `X-Webhook-Timestamp` and `X-Webhook-Signature` headers
|
|
418
|
+
* 2. Get the raw request body bytes (do not parse and re-serialize)
|
|
419
|
+
* 3. Concatenate: `"{timestamp}.{payload}"`
|
|
420
|
+
* 4. Compute HMAC-SHA256 using your signing secret as the key
|
|
421
|
+
* 5. Hex-encode the result and compare with `X-Webhook-Signature`
|
|
422
|
+
* 6. Use constant-time comparison to prevent timing attacks
|
|
423
|
+
*
|
|
424
|
+
* **Example (Python):**
|
|
425
|
+
*
|
|
426
|
+
* ```python
|
|
427
|
+
* import hmac
|
|
428
|
+
* import hashlib
|
|
429
|
+
*
|
|
430
|
+
* def verify_webhook(signing_secret, payload, timestamp, signature):
|
|
431
|
+
* message = f"{timestamp}.{payload.decode('utf-8')}"
|
|
432
|
+
* expected = hmac.new(
|
|
433
|
+
* signing_secret.encode('utf-8'),
|
|
434
|
+
* message.encode('utf-8'),
|
|
435
|
+
* hashlib.sha256
|
|
436
|
+
* ).hexdigest()
|
|
437
|
+
* return hmac.compare_digest(expected, signature)
|
|
438
|
+
* ```
|
|
439
|
+
*
|
|
440
|
+
* **Example (Node.js):**
|
|
441
|
+
*
|
|
442
|
+
* ```javascript
|
|
443
|
+
* const crypto = require('crypto');
|
|
444
|
+
*
|
|
445
|
+
* function verifyWebhook(signingSecret, payload, timestamp, signature) {
|
|
446
|
+
* const message = `${timestamp}.${payload}`;
|
|
447
|
+
* const expected = crypto
|
|
448
|
+
* .createHmac('sha256', signingSecret)
|
|
449
|
+
* .update(message)
|
|
450
|
+
* .digest('hex');
|
|
451
|
+
* return crypto.timingSafeEqual(
|
|
452
|
+
* Buffer.from(expected),
|
|
453
|
+
* Buffer.from(signature)
|
|
454
|
+
* );
|
|
455
|
+
* }
|
|
456
|
+
* ```
|
|
457
|
+
*
|
|
458
|
+
* **Security Best Practices:**
|
|
459
|
+
*
|
|
460
|
+
* - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
|
|
461
|
+
* - Always use constant-time comparison for signature verification
|
|
462
|
+
* - Store your signing secret securely (e.g., environment variable, secrets manager)
|
|
463
|
+
* - Return a 2xx status code quickly, then process the webhook asynchronously
|
|
464
|
+
*
|
|
465
|
+
*/
|
|
191
466
|
webhookSubscriptions: API.WebhookSubscriptions;
|
|
467
|
+
/**
|
|
468
|
+
* Check whether a recipient address supports iMessage or RCS before sending a message.
|
|
469
|
+
*
|
|
470
|
+
*/
|
|
192
471
|
capability: API.Capability;
|
|
193
472
|
}
|
|
194
473
|
export declare namespace LinqAPIV3 {
|