@linqapp/sdk 0.28.0 → 0.28.2

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 (147) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/client.d.mts +59 -9
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +59 -9
  5. package/client.d.ts.map +1 -1
  6. package/client.js +63 -5
  7. package/client.js.map +1 -1
  8. package/client.mjs +64 -6
  9. package/client.mjs.map +1 -1
  10. package/internal/qs/formats.d.mts +7 -0
  11. package/internal/qs/formats.d.mts.map +1 -0
  12. package/internal/qs/formats.d.ts +7 -0
  13. package/internal/qs/formats.d.ts.map +1 -0
  14. package/internal/qs/formats.js +13 -0
  15. package/internal/qs/formats.js.map +1 -0
  16. package/internal/qs/formats.mjs +9 -0
  17. package/internal/qs/formats.mjs.map +1 -0
  18. package/internal/qs/index.d.mts +10 -0
  19. package/internal/qs/index.d.mts.map +1 -0
  20. package/internal/qs/index.d.ts +10 -0
  21. package/internal/qs/index.d.ts.map +1 -0
  22. package/internal/qs/index.js +14 -0
  23. package/internal/qs/index.js.map +1 -0
  24. package/internal/qs/index.mjs +10 -0
  25. package/internal/qs/index.mjs.map +1 -0
  26. package/internal/qs/stringify.d.mts +3 -0
  27. package/internal/qs/stringify.d.mts.map +1 -0
  28. package/internal/qs/stringify.d.ts +3 -0
  29. package/internal/qs/stringify.d.ts.map +1 -0
  30. package/internal/qs/stringify.js +277 -0
  31. package/internal/qs/stringify.js.map +1 -0
  32. package/internal/qs/stringify.mjs +274 -0
  33. package/internal/qs/stringify.mjs.map +1 -0
  34. package/internal/qs/types.d.mts +57 -0
  35. package/internal/qs/types.d.mts.map +1 -0
  36. package/internal/qs/types.d.ts +57 -0
  37. package/internal/qs/types.d.ts.map +1 -0
  38. package/internal/qs/types.js +3 -0
  39. package/internal/qs/types.js.map +1 -0
  40. package/internal/qs/types.mjs +2 -0
  41. package/internal/qs/types.mjs.map +1 -0
  42. package/internal/qs/utils.d.mts +15 -0
  43. package/internal/qs/utils.d.mts.map +1 -0
  44. package/internal/qs/utils.d.ts +15 -0
  45. package/internal/qs/utils.d.ts.map +1 -0
  46. package/internal/qs/utils.js +230 -0
  47. package/internal/qs/utils.js.map +1 -0
  48. package/internal/qs/utils.mjs +217 -0
  49. package/internal/qs/utils.mjs.map +1 -0
  50. package/internal/tslib.js +17 -17
  51. package/internal/utils/query.d.mts +0 -3
  52. package/internal/utils/query.d.mts.map +1 -1
  53. package/internal/utils/query.d.ts +0 -3
  54. package/internal/utils/query.d.ts.map +1 -1
  55. package/internal/utils/query.js +3 -16
  56. package/internal/utils/query.js.map +1 -1
  57. package/internal/utils/query.mjs +2 -16
  58. package/internal/utils/query.mjs.map +1 -1
  59. package/package.json +1 -1
  60. package/resources/attachments.d.mts +1 -1
  61. package/resources/attachments.d.ts +1 -1
  62. package/resources/attachments.js +1 -1
  63. package/resources/attachments.mjs +1 -1
  64. package/resources/available-number.d.mts +58 -0
  65. package/resources/available-number.d.mts.map +1 -0
  66. package/resources/available-number.d.ts +58 -0
  67. package/resources/available-number.d.ts.map +1 -0
  68. package/resources/available-number.js +36 -0
  69. package/resources/available-number.js.map +1 -0
  70. package/resources/available-number.mjs +32 -0
  71. package/resources/available-number.mjs.map +1 -0
  72. package/resources/chats/chats.d.mts +59 -11
  73. package/resources/chats/chats.d.mts.map +1 -1
  74. package/resources/chats/chats.d.ts +59 -11
  75. package/resources/chats/chats.d.ts.map +1 -1
  76. package/resources/chats/chats.js.map +1 -1
  77. package/resources/chats/chats.mjs.map +1 -1
  78. package/resources/chats/location.d.mts +9 -8
  79. package/resources/chats/location.d.mts.map +1 -1
  80. package/resources/chats/location.d.ts +9 -8
  81. package/resources/chats/location.d.ts.map +1 -1
  82. package/resources/chats/location.js +9 -8
  83. package/resources/chats/location.js.map +1 -1
  84. package/resources/chats/location.mjs +9 -8
  85. package/resources/chats/location.mjs.map +1 -1
  86. package/resources/chats/messages.d.mts +84 -6
  87. package/resources/chats/messages.d.mts.map +1 -1
  88. package/resources/chats/messages.d.ts +84 -6
  89. package/resources/chats/messages.d.ts.map +1 -1
  90. package/resources/chats/messages.js +40 -0
  91. package/resources/chats/messages.js.map +1 -1
  92. package/resources/chats/messages.mjs +40 -0
  93. package/resources/chats/messages.mjs.map +1 -1
  94. package/resources/contact-card.d.mts +1 -2
  95. package/resources/contact-card.d.mts.map +1 -1
  96. package/resources/contact-card.d.ts +1 -2
  97. package/resources/contact-card.d.ts.map +1 -1
  98. package/resources/index.d.mts +3 -2
  99. package/resources/index.d.mts.map +1 -1
  100. package/resources/index.d.ts +3 -2
  101. package/resources/index.d.ts.map +1 -1
  102. package/resources/index.js +3 -1
  103. package/resources/index.js.map +1 -1
  104. package/resources/index.mjs +2 -1
  105. package/resources/index.mjs.map +1 -1
  106. package/resources/messages.d.mts +400 -7
  107. package/resources/messages.d.mts.map +1 -1
  108. package/resources/messages.d.ts +400 -7
  109. package/resources/messages.d.ts.map +1 -1
  110. package/resources/messages.js +148 -0
  111. package/resources/messages.js.map +1 -1
  112. package/resources/messages.mjs +148 -0
  113. package/resources/messages.mjs.map +1 -1
  114. package/resources/phone-numbers.d.mts +68 -23
  115. package/resources/phone-numbers.d.mts.map +1 -1
  116. package/resources/phone-numbers.d.ts +68 -23
  117. package/resources/phone-numbers.d.ts.map +1 -1
  118. package/resources/phone-numbers.js +23 -0
  119. package/resources/phone-numbers.js.map +1 -1
  120. package/resources/phone-numbers.mjs +23 -0
  121. package/resources/phone-numbers.mjs.map +1 -1
  122. package/resources/webhooks.d.mts +14 -14
  123. package/resources/webhooks.d.ts +14 -14
  124. package/src/client.ts +94 -8
  125. package/src/internal/qs/LICENSE.md +13 -0
  126. package/src/internal/qs/README.md +3 -0
  127. package/src/internal/qs/formats.ts +10 -0
  128. package/src/internal/qs/index.ts +13 -0
  129. package/src/internal/qs/stringify.ts +385 -0
  130. package/src/internal/qs/types.ts +71 -0
  131. package/src/internal/qs/utils.ts +265 -0
  132. package/src/internal/utils/query.ts +2 -18
  133. package/src/resources/attachments.ts +1 -1
  134. package/src/resources/available-number.ts +72 -0
  135. package/src/resources/chats/chats.ts +64 -12
  136. package/src/resources/chats/location.ts +9 -8
  137. package/src/resources/chats/messages.ts +87 -6
  138. package/src/resources/contact-card.ts +1 -2
  139. package/src/resources/index.ts +15 -1
  140. package/src/resources/messages.ts +453 -6
  141. package/src/resources/phone-numbers.ts +85 -23
  142. package/src/resources/webhooks.ts +14 -14
  143. package/src/version.ts +1 -1
  144. package/version.d.mts +1 -1
  145. package/version.d.ts +1 -1
  146. package/version.js +1 -1
  147. package/version.mjs +1 -1
@@ -2,6 +2,8 @@
2
2
 
3
3
  import { APIResource } from '../core/resource';
4
4
  import * as Shared from './shared';
5
+ import * as ChatsAPI from './chats/chats';
6
+ import * as ChatsMessagesAPI from './chats/messages';
5
7
  import { APIPromise } from '../core/api-promise';
6
8
  import { ListMessagesPagination, type ListMessagesPaginationParams, PagePromise } from '../core/pagination';
7
9
  import { buildHeaders } from '../internal/headers';
@@ -27,8 +29,118 @@ import { path } from '../internal/utils/path';
27
29
  * **Limitations:**
28
30
  * - A `link` part cannot be combined with other parts in the same message.
29
31
  * - Maximum URL length: 2,048 characters.
32
+ *
33
+ * ## Ephemeral Messages (Privacy Tier)
34
+ *
35
+ * For regulated or sensitive conversations, opt in to the **ephemeral messages** tier by contacting your Linq support contact. When enabled, every message on the covered phone numbers is automatically given a fixed **24-hour retention window** — after that window the platform permanently deletes the message from Linq storage. There is no per-message flag; ephemerality is applied automatically based on your configuration.
36
+ *
37
+ * You can request it at two scopes:
38
+ *
39
+ * | Scope | Effect |
40
+ * |---|---|
41
+ * | **Partner-wide** | Every outbound and inbound message on every phone number under your account is retained for 24 hours, then deleted. |
42
+ * | **Per phone number** | Only the specified phone numbers have their messages auto-deleted. The rest follow the standard message-retention policy. |
43
+ *
44
+ * **Behavioral differences vs the standard default:**
45
+ *
46
+ * | Aspect | Standard | Ephemeral |
47
+ * |---|---|---|
48
+ * | Retention | Retained per the standard message-retention policy | **Hard backstop: 24 hours** from when the message is created |
49
+ * | After expiry | Message stays retrievable | Message is permanently deleted — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages` |
50
+ * | Content on expiry | N/A | Text, formatting, and attachment references are scrubbed; the message is gone, not blanked out |
51
+ * | Cross-partner isolation | Enforced | Enforced |
52
+ *
53
+ * **How the 24-hour window works:**
54
+ *
55
+ * - The window is fixed at **24 hours from message creation** (`created_at`) and cannot be configured per message.
56
+ * - It mirrors the ephemeral *attachments* 1-day backstop, so a message and any media it carries expire together.
57
+ * - Expiry is delivery-independent — the clock starts when the message is created, not when it is delivered or read.
58
+ *
59
+ * **What you observe:**
60
+ *
61
+ * - **No expiry timestamp is exposed.** API responses and webhook payloads do not include the deletion time. If you need it, compute `created_at + 24h` yourself.
62
+ * - **No deletion webhook is sent.** There is no `message.deleted` event — a message simply stops being retrievable once its window passes.
63
+ * - **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the usual `message.sent` / `message.received` and status webhooks exactly like standard messages. Only retention changes.
64
+ *
65
+ * **When to choose ephemeral:**
66
+ *
67
+ * - You have a compliance requirement that the platform must not retain message content beyond a short window.
68
+ * - The conversation is high-sensitivity (PHI, financial, identity verification) and you do not want it sitting in storage long-term.
69
+ * - Your application is the system of record — you capture what you need from the delivery webhook in real time and do not rely on reading message history back from Linq later.
70
+ *
71
+ * **Important:** ephemeral applies in *both directions* — messages you send **and** messages received by the phone numbers in that scope. Because Linq can no longer return the message after 24 hours, persist anything you need to keep from the webhook payload at the time it is delivered.
30
72
  */
31
73
  export class Messages extends APIResource {
74
+ /**
75
+ * Send a message to one or more recipients **without supplying a `from` number**.
76
+ * Linq resolves both the sending line and the target chat for you, then returns
77
+ * exactly which line was used, which chat the message landed in, whether a new
78
+ * chat was created, and every resulting message id.
79
+ *
80
+ * This fuses "create chat" and "send message" behind a single message-centric
81
+ * resource. Provide only the recipients (`to`) and the `message`; the platform
82
+ * decides the rest.
83
+ *
84
+ * ## How the from-number and chat are chosen
85
+ *
86
+ * - **Reuse** — if a chat with exactly these recipients already exists and the
87
+ * line it lives on is healthy, the message is sent into that chat on its
88
+ * existing line (`from_selection.reason = reused_active_chat`).
89
+ * - **New** — if no such chat exists, a new chat is created on the best available
90
+ * line (`from_selection.reason = new_best_number`).
91
+ * - **Failover** — if a matching chat exists but its line has been flagged, a
92
+ * **new** chat is created on a fresh best line and the flagged chat is abandoned
93
+ * (`from_selection.reason = failover_flagged`, `previous_chat_id` set). If you
94
+ * supply `continuation_message`, that text is sent as the single message INSTEAD
95
+ * of `message` (useful as a fresh-number-appropriate opener). Exactly one
96
+ * message is sent either way.
97
+ *
98
+ * Recipients (`to`) are an order-independent set: a single handle is a direct
99
+ * chat, multiple handles a group chat.
100
+ *
101
+ * ## Differences from POST /v3/chats
102
+ *
103
+ * - The first message **may contain a link** (including for a newly created chat).
104
+ * Note: sending a link as the very first message on a freshly selected line can
105
+ * elevate that line's flagging risk — it is allowed, not recommended.
106
+ * - Voice memos are **not** supported here. To send an iMessage voice-memo bubble,
107
+ * use `POST /v3/chats/{chatId}/voicememo` with a known chat id.
108
+ *
109
+ * ## Service preference, effects, decorations
110
+ *
111
+ * Set `message.preferred_service` (`iMessage` | `RCS` | `SMS`), `message.effect`,
112
+ * and per-part `text_decorations` exactly as on the other send endpoints.
113
+ *
114
+ * Always responds `202 Accepted` — chat creation is incidental to the send.
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * const message = await client.messages.create({
119
+ * message: {
120
+ * parts: [
121
+ * {
122
+ * type: 'text',
123
+ * value:
124
+ * 'Hi! Thanks for reaching out — how can we help?',
125
+ * },
126
+ * ],
127
+ * },
128
+ * to: ['+14155559876'],
129
+ * });
130
+ * ```
131
+ */
132
+ create(params: MessageCreateParams, options?: RequestOptions): APIPromise<MessageCreateResponse> {
133
+ const { 'Idempotency-Key': idempotencyKey, ...body } = params;
134
+ return this._client.post('/v3/messages', {
135
+ body,
136
+ ...options,
137
+ headers: buildHeaders([
138
+ { ...(idempotencyKey != null ? { 'Idempotency-Key': idempotencyKey } : undefined) },
139
+ options?.headers,
140
+ ]),
141
+ });
142
+ }
143
+
32
144
  /**
33
145
  * Retrieve all messages in a conversation thread. Given any message ID in the
34
146
  * thread, returns the originator message and all replies in chronological order.
@@ -138,6 +250,50 @@ export class Messages extends APIResource {
138
250
  update(messageID: string, body: MessageUpdateParams, options?: RequestOptions): APIPromise<Message> {
139
251
  return this._client.patch(path`/v3/messages/${messageID}`, { body, ...options });
140
252
  }
253
+
254
+ /**
255
+ * Replaces a previously delivered `imessage_app` card on the recipient's screen
256
+ * with new content, instead of posting a new bubble (like a game move redrawing
257
+ * the board).
258
+ *
259
+ * The update is delivered as a **new message** with its own id and delivery
260
+ * lifecycle (`message.sent` / `message.delivered` / `message.failed` webhooks fire
261
+ * for the new id). To update the card again, reference the message id returned by
262
+ * this call.
263
+ *
264
+ * Constraints:
265
+ *
266
+ * - The referenced message must be an `imessage_app` card sent by you (`400`
267
+ * otherwise — inbound cards cannot be updated).
268
+ * - The referenced card must already be delivered (`409` otherwise — retry after
269
+ * the `message.delivered` webhook for it).
270
+ * - The app identity (`team_id`, `bundle_id`, name) is inherited from the original
271
+ * card and cannot change; only `url`, `fallback_text`, and `layout` are
272
+ * replaced.
273
+ * - iMessage-only, like all app cards.
274
+ * - Concurrent updates against the same card are not serialized server-side; the
275
+ * last one delivered wins on the recipient's screen. Serialize updates by always
276
+ * referencing the message id returned by the previous call.
277
+ *
278
+ * @example
279
+ * ```ts
280
+ * const response = await client.messages.updateAppCard(
281
+ * '69a37c7d-af4f-4b5e-af42-e28e98ce873a',
282
+ * {
283
+ * layout: { caption: 'Score: 2 – 1' },
284
+ * fallback_text: 'Score update',
285
+ * url: 'https://app.example.com/card?game=7f3a&move=2',
286
+ * },
287
+ * );
288
+ * ```
289
+ */
290
+ updateAppCard(
291
+ messageID: string,
292
+ body: MessageUpdateAppCardParams,
293
+ options?: RequestOptions,
294
+ ): APIPromise<MessageUpdateAppCardResponse> {
295
+ return this._client.post(path`/v3/messages/${messageID}/update`, { body, ...options });
296
+ }
141
297
  }
142
298
 
143
299
  export type MessagesListMessagesPagination = ListMessagesPagination<Message>;
@@ -255,9 +411,19 @@ export namespace Message {
255
411
 
256
412
  /**
257
413
  * Visible layout of the card. At least one of `caption`, `subcaption`,
258
- * `trailing_caption`, or `trailing_subcaption` must be set, otherwise the card
259
- * renders as an empty bubble. Any image on the card is drawn by the recipient's
260
- * installed app extension; it cannot be supplied here.
414
+ * `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
415
+ * the card renders as an empty bubble.
416
+ *
417
+ * `image_url` displays a preview image at the top of the card. The image renders
418
+ * on the recipient's card whether or not they have your app installed. The small
419
+ * icon beside the caption is the app's own icon and is not settable here.
420
+ *
421
+ * `* Note - requires a trusted chat w/ inbound activity`
422
+ *
423
+ * `image_title` and `image_subtitle` render as text overlaid on the image (title
424
+ * bold, subtitle beneath it). They only appear when `image_url` is set — without
425
+ * an image there is nothing to overlay — so setting either without `image_url` is
426
+ * rejected.
261
427
  */
262
428
  layout: IMessageAppPartResponse.Layout;
263
429
 
@@ -311,9 +477,19 @@ export namespace Message {
311
477
 
312
478
  /**
313
479
  * Visible layout of the card. At least one of `caption`, `subcaption`,
314
- * `trailing_caption`, or `trailing_subcaption` must be set, otherwise the card
315
- * renders as an empty bubble. Any image on the card is drawn by the recipient's
316
- * installed app extension; it cannot be supplied here.
480
+ * `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
481
+ * the card renders as an empty bubble.
482
+ *
483
+ * `image_url` displays a preview image at the top of the card. The image renders
484
+ * on the recipient's card whether or not they have your app installed. The small
485
+ * icon beside the caption is the app's own icon and is not settable here.
486
+ *
487
+ * `* Note - requires a trusted chat w/ inbound activity`
488
+ *
489
+ * `image_title` and `image_subtitle` render as text overlaid on the image (title
490
+ * bold, subtitle beneath it). They only appear when `image_url` is set — without
491
+ * an image there is nothing to overlay — so setting either without `image_url` is
492
+ * rejected.
317
493
  */
318
494
  export interface Layout {
319
495
  /**
@@ -321,6 +497,27 @@ export namespace Message {
321
497
  */
322
498
  caption?: string;
323
499
 
500
+ /**
501
+ * Text shown below `image_title`, overlaid on the card image. Requires
502
+ * `image_url`.
503
+ */
504
+ image_subtitle?: string;
505
+
506
+ /**
507
+ * Bold text overlaid on the card image. Requires `image_url` (rejected without
508
+ * it).
509
+ */
510
+ image_title?: string;
511
+
512
+ /**
513
+ * URL of an image (JPEG, PNG, HEIF, or WebP) to display as the card's preview
514
+ * image; an unreachable or non-image URL returns a validation error. Renders for
515
+ * all recipients regardless of whether they have the app. Note - requires a
516
+ * trusted chat w/ inbound activity. In responses, this is the re-hosted
517
+ * `cdn.linqapp.com` copy of the image you supplied, not your original URL.
518
+ */
519
+ image_url?: string;
520
+
324
521
  /**
325
522
  * Secondary label, below `caption` on the left.
326
523
  */
@@ -375,6 +572,79 @@ export interface ReplyTo {
375
572
  part_index?: number;
376
573
  }
377
574
 
575
+ /**
576
+ * Result of an auto-from send. Self-describing: which line was used, which chat
577
+ * the message landed in, whether a new chat was created, and the resulting message
578
+ * id(s).
579
+ */
580
+ export interface MessageCreateResponse {
581
+ /**
582
+ * The resolved chat (reused or newly created) the message landed in.
583
+ */
584
+ chat_id: string;
585
+
586
+ /**
587
+ * True when a new chat was created (new or failover), false on reuse.
588
+ */
589
+ created_new_chat: boolean;
590
+
591
+ /**
592
+ * The line (E.164) the message was actually sent from.
593
+ */
594
+ from: string;
595
+
596
+ /**
597
+ * Why this line/chat was chosen.
598
+ */
599
+ from_selection: MessageCreateResponse.FromSelection;
600
+
601
+ /**
602
+ * Participants of the resolved chat.
603
+ */
604
+ handles: Array<Shared.ChatHandle>;
605
+
606
+ /**
607
+ * Whether the resolved chat is a group chat.
608
+ */
609
+ is_group: boolean;
610
+
611
+ /**
612
+ * A message that was sent (used in CreateChat and SendMessage responses)
613
+ */
614
+ message: ChatsMessagesAPI.SentMessage;
615
+
616
+ /**
617
+ * Messaging service type
618
+ */
619
+ service: Shared.ServiceType;
620
+
621
+ /**
622
+ * Set ONLY on `failover_flagged`: the abandoned flagged chat that was NOT sent
623
+ * into. Null otherwise.
624
+ */
625
+ previous_chat_id?: string | null;
626
+ }
627
+
628
+ export namespace MessageCreateResponse {
629
+ /**
630
+ * Why this line/chat was chosen.
631
+ */
632
+ export interface FromSelection {
633
+ /**
634
+ * - `reused_active_chat` — reused an existing chat on its healthy line
635
+ * - `new_best_number` — created a new chat on the best available line
636
+ * - `failover_flagged` — prior chat's line was flagged; created a new chat on a
637
+ * fresh line
638
+ */
639
+ reason: 'reused_active_chat' | 'new_best_number' | 'failover_flagged';
640
+
641
+ /**
642
+ * True only when an existing chat was reused.
643
+ */
644
+ reused_existing_chat: boolean;
645
+ }
646
+ }
647
+
378
648
  export interface MessageAddReactionResponse {
379
649
  message?: string;
380
650
 
@@ -383,6 +653,74 @@ export interface MessageAddReactionResponse {
383
653
  trace_id?: string;
384
654
  }
385
655
 
656
+ /**
657
+ * Response for sending a message to a chat
658
+ */
659
+ export interface MessageUpdateAppCardResponse {
660
+ /**
661
+ * Unique identifier of the chat this message was sent to
662
+ */
663
+ chat_id: string;
664
+
665
+ /**
666
+ * A message that was sent (used in CreateChat and SendMessage responses)
667
+ */
668
+ message: ChatsMessagesAPI.SentMessage;
669
+ }
670
+
671
+ export interface MessageCreateParams {
672
+ /**
673
+ * Body param: Message content container. Groups all message-related fields
674
+ * together, separating the "what" (message content) from the "where" (routing
675
+ * fields like from/to).
676
+ */
677
+ message: ChatsAPI.MessageContent;
678
+
679
+ /**
680
+ * Body param: Recipient handles (E.164 phone numbers or email addresses). One
681
+ * handle is a direct chat; multiple handles a group chat. Order-independent — the
682
+ * set identifies the chat.
683
+ */
684
+ to: Array<string>;
685
+
686
+ /**
687
+ * Body param: Text-only fallback that **replaces** `message` ONLY on the failover
688
+ * branch — when a chat with these recipients already existed but its line was
689
+ * flagged, so a new chat is created on a fresh line. On that branch this text is
690
+ * sent as the single message instead of `message` (the recipient is on a new
691
+ * number, so you typically want a fresh-number-appropriate opener rather than the
692
+ * original content). Ignored otherwise (a healthy reuse, or genuine first
693
+ * contact). Carries no parts, media, or effects — exactly one message is ever
694
+ * sent.
695
+ */
696
+ continuation_message?: MessageCreateParams.ContinuationMessage;
697
+
698
+ /**
699
+ * Header param: Optional idempotency key for the send. Reuse the same key to
700
+ * safely retry without sending twice. May also be supplied as
701
+ * `message.idempotency_key`.
702
+ */
703
+ 'Idempotency-Key'?: string;
704
+ }
705
+
706
+ export namespace MessageCreateParams {
707
+ /**
708
+ * Text-only fallback that **replaces** `message` ONLY on the failover branch —
709
+ * when a chat with these recipients already existed but its line was flagged, so a
710
+ * new chat is created on a fresh line. On that branch this text is sent as the
711
+ * single message instead of `message` (the recipient is on a new number, so you
712
+ * typically want a fresh-number-appropriate opener rather than the original
713
+ * content). Ignored otherwise (a healthy reuse, or genuine first contact). Carries
714
+ * no parts, media, or effects — exactly one message is ever sent.
715
+ */
716
+ export interface ContinuationMessage {
717
+ /**
718
+ * The replacement message text, sent as the single message on failover.
719
+ */
720
+ text: string;
721
+ }
722
+ }
723
+
386
724
  export interface MessageListMessagesThreadParams extends ListMessagesPaginationParams {
387
725
  /**
388
726
  * Sort order for messages (asc = oldest first, desc = newest first)
@@ -428,15 +766,124 @@ export interface MessageUpdateParams {
428
766
  part_index?: number;
429
767
  }
430
768
 
769
+ export interface MessageUpdateAppCardParams {
770
+ /**
771
+ * Visible layout of the card. At least one of `caption`, `subcaption`,
772
+ * `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
773
+ * the card renders as an empty bubble.
774
+ *
775
+ * `image_url` displays a preview image at the top of the card. The image renders
776
+ * on the recipient's card whether or not they have your app installed. The small
777
+ * icon beside the caption is the app's own icon and is not settable here.
778
+ *
779
+ * `* Note - requires a trusted chat w/ inbound activity`
780
+ *
781
+ * `image_title` and `image_subtitle` render as text overlaid on the image (title
782
+ * bold, subtitle beneath it). They only appear when `image_url` is set — without
783
+ * an image there is nothing to overlay — so setting either without `image_url` is
784
+ * rejected.
785
+ */
786
+ layout: MessageUpdateAppCardParams.Layout;
787
+
788
+ /**
789
+ * Text shown on surfaces that cannot render the card (notifications, lock screen).
790
+ * Defaults to the caption when omitted.
791
+ */
792
+ fallback_text?: string;
793
+
794
+ /**
795
+ * Whether the updated card renders as your app's interactive balloon for
796
+ * recipients who have your iMessage app installed. `true` (default) lets your
797
+ * installed extension draw its live view; `false` always shows the static `layout`
798
+ * card. Recipients without your app always see the static card regardless of this
799
+ * flag.
800
+ *
801
+ * Defaults to `true` when omitted — it is **not** inherited from the original
802
+ * card. To keep a card static across updates, re-send `interactive: false` on each
803
+ * update.
804
+ */
805
+ interactive?: boolean;
806
+
807
+ /**
808
+ * URL the recipient's app opens when they tap the updated card.
809
+ */
810
+ url?: string;
811
+ }
812
+
813
+ export namespace MessageUpdateAppCardParams {
814
+ /**
815
+ * Visible layout of the card. At least one of `caption`, `subcaption`,
816
+ * `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
817
+ * the card renders as an empty bubble.
818
+ *
819
+ * `image_url` displays a preview image at the top of the card. The image renders
820
+ * on the recipient's card whether or not they have your app installed. The small
821
+ * icon beside the caption is the app's own icon and is not settable here.
822
+ *
823
+ * `* Note - requires a trusted chat w/ inbound activity`
824
+ *
825
+ * `image_title` and `image_subtitle` render as text overlaid on the image (title
826
+ * bold, subtitle beneath it). They only appear when `image_url` is set — without
827
+ * an image there is nothing to overlay — so setting either without `image_url` is
828
+ * rejected.
829
+ */
830
+ export interface Layout {
831
+ /**
832
+ * Primary label, top-left and bold.
833
+ */
834
+ caption?: string;
835
+
836
+ /**
837
+ * Text shown below `image_title`, overlaid on the card image. Requires
838
+ * `image_url`.
839
+ */
840
+ image_subtitle?: string;
841
+
842
+ /**
843
+ * Bold text overlaid on the card image. Requires `image_url` (rejected without
844
+ * it).
845
+ */
846
+ image_title?: string;
847
+
848
+ /**
849
+ * URL of an image (JPEG, PNG, HEIF, or WebP) to display as the card's preview
850
+ * image; an unreachable or non-image URL returns a validation error. Renders for
851
+ * all recipients regardless of whether they have the app. Note - requires a
852
+ * trusted chat w/ inbound activity. In responses, this is the re-hosted
853
+ * `cdn.linqapp.com` copy of the image you supplied, not your original URL.
854
+ */
855
+ image_url?: string;
856
+
857
+ /**
858
+ * Secondary label, below `caption` on the left.
859
+ */
860
+ subcaption?: string;
861
+
862
+ /**
863
+ * Label shown top-right.
864
+ */
865
+ trailing_caption?: string;
866
+
867
+ /**
868
+ * Label shown below `trailing_caption`, on the right.
869
+ */
870
+ trailing_subcaption?: string;
871
+ }
872
+ }
873
+
431
874
  export declare namespace Messages {
432
875
  export {
433
876
  type Message as Message,
434
877
  type MessageEffect as MessageEffect,
435
878
  type ReplyTo as ReplyTo,
879
+ type MessageCreateResponse as MessageCreateResponse,
436
880
  type MessageAddReactionResponse as MessageAddReactionResponse,
881
+ type MessageUpdateAppCardResponse as MessageUpdateAppCardResponse,
437
882
  type MessagesListMessagesPagination as MessagesListMessagesPagination,
883
+ type MessageCreateParams as MessageCreateParams,
438
884
  type MessageListMessagesThreadParams as MessageListMessagesThreadParams,
439
885
  type MessageAddReactionParams as MessageAddReactionParams,
440
886
  type MessageUpdateParams as MessageUpdateParams,
887
+ type MessageUpdateAppCardParams as MessageUpdateAppCardParams,
441
888
  };
442
889
  }