sendblue 2.0.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/LICENSE +1 -1
  3. package/README.md +34 -5
  4. package/client.d.mts +25 -3
  5. package/client.d.mts.map +1 -1
  6. package/client.d.ts +25 -3
  7. package/client.d.ts.map +1 -1
  8. package/client.js +41 -17
  9. package/client.js.map +1 -1
  10. package/client.mjs +41 -17
  11. package/client.mjs.map +1 -1
  12. package/internal/parse.d.mts.map +1 -1
  13. package/internal/parse.d.ts.map +1 -1
  14. package/internal/parse.js +5 -0
  15. package/internal/parse.js.map +1 -1
  16. package/internal/parse.mjs +5 -0
  17. package/internal/parse.mjs.map +1 -1
  18. package/internal/utils/query.d.mts +5 -0
  19. package/internal/utils/query.d.mts.map +1 -0
  20. package/internal/utils/query.d.ts +5 -0
  21. package/internal/utils/query.d.ts.map +1 -0
  22. package/internal/utils/query.js +23 -0
  23. package/internal/utils/query.js.map +1 -0
  24. package/internal/utils/query.mjs +20 -0
  25. package/internal/utils/query.mjs.map +1 -0
  26. package/internal/utils.d.mts +1 -0
  27. package/internal/utils.d.ts +1 -0
  28. package/internal/utils.js +1 -0
  29. package/internal/utils.js.map +1 -1
  30. package/internal/utils.mjs +1 -0
  31. package/package.json +1 -1
  32. package/resources/contacts/bulk.d.mts +25 -3
  33. package/resources/contacts/bulk.d.mts.map +1 -1
  34. package/resources/contacts/bulk.d.ts +25 -3
  35. package/resources/contacts/bulk.d.ts.map +1 -1
  36. package/resources/contacts/bulk.js +3 -0
  37. package/resources/contacts/bulk.js.map +1 -1
  38. package/resources/contacts/bulk.mjs +3 -0
  39. package/resources/contacts/bulk.mjs.map +1 -1
  40. package/resources/contacts/contacts.d.mts +101 -18
  41. package/resources/contacts/contacts.d.mts.map +1 -1
  42. package/resources/contacts/contacts.d.ts +101 -18
  43. package/resources/contacts/contacts.d.ts.map +1 -1
  44. package/resources/contacts/contacts.js +5 -2
  45. package/resources/contacts/contacts.js.map +1 -1
  46. package/resources/contacts/contacts.mjs +5 -2
  47. package/resources/contacts/contacts.mjs.map +1 -1
  48. package/resources/contacts/index.d.mts +1 -1
  49. package/resources/contacts/index.d.mts.map +1 -1
  50. package/resources/contacts/index.d.ts +1 -1
  51. package/resources/contacts/index.d.ts.map +1 -1
  52. package/resources/contacts/index.js.map +1 -1
  53. package/resources/contacts/index.mjs.map +1 -1
  54. package/resources/groups.d.mts +3 -0
  55. package/resources/groups.d.mts.map +1 -1
  56. package/resources/groups.d.ts +3 -0
  57. package/resources/groups.d.ts.map +1 -1
  58. package/resources/groups.js +3 -0
  59. package/resources/groups.js.map +1 -1
  60. package/resources/groups.mjs +3 -0
  61. package/resources/groups.mjs.map +1 -1
  62. package/resources/index.d.mts +1 -1
  63. package/resources/index.d.mts.map +1 -1
  64. package/resources/index.d.ts +1 -1
  65. package/resources/index.d.ts.map +1 -1
  66. package/resources/index.js.map +1 -1
  67. package/resources/index.mjs.map +1 -1
  68. package/resources/lookups.d.mts +3 -0
  69. package/resources/lookups.d.mts.map +1 -1
  70. package/resources/lookups.d.ts +3 -0
  71. package/resources/lookups.d.ts.map +1 -1
  72. package/resources/lookups.js +3 -0
  73. package/resources/lookups.js.map +1 -1
  74. package/resources/lookups.mjs +3 -0
  75. package/resources/lookups.mjs.map +1 -1
  76. package/resources/media-objects.d.mts +3 -0
  77. package/resources/media-objects.d.mts.map +1 -1
  78. package/resources/media-objects.d.ts +3 -0
  79. package/resources/media-objects.d.ts.map +1 -1
  80. package/resources/media-objects.js +3 -0
  81. package/resources/media-objects.js.map +1 -1
  82. package/resources/media-objects.mjs +3 -0
  83. package/resources/media-objects.mjs.map +1 -1
  84. package/resources/messages.d.mts +50 -7
  85. package/resources/messages.d.mts.map +1 -1
  86. package/resources/messages.d.ts +50 -7
  87. package/resources/messages.d.ts.map +1 -1
  88. package/resources/messages.js +19 -0
  89. package/resources/messages.js.map +1 -1
  90. package/resources/messages.mjs +19 -0
  91. package/resources/messages.mjs.map +1 -1
  92. package/resources/typing-indicators.d.mts +10 -2
  93. package/resources/typing-indicators.d.mts.map +1 -1
  94. package/resources/typing-indicators.d.ts +10 -2
  95. package/resources/typing-indicators.d.ts.map +1 -1
  96. package/resources/typing-indicators.js +5 -2
  97. package/resources/typing-indicators.js.map +1 -1
  98. package/resources/typing-indicators.mjs +5 -2
  99. package/resources/typing-indicators.mjs.map +1 -1
  100. package/resources/webhooks.d.mts +149 -145
  101. package/resources/webhooks.d.mts.map +1 -1
  102. package/resources/webhooks.d.ts +149 -145
  103. package/resources/webhooks.d.ts.map +1 -1
  104. package/resources/webhooks.js +11 -57
  105. package/resources/webhooks.js.map +1 -1
  106. package/resources/webhooks.mjs +11 -57
  107. package/resources/webhooks.mjs.map +1 -1
  108. package/src/client.ts +48 -22
  109. package/src/internal/parse.ts +6 -0
  110. package/src/internal/utils/query.ts +23 -0
  111. package/src/internal/utils.ts +1 -0
  112. package/src/resources/contacts/bulk.ts +24 -3
  113. package/src/resources/contacts/contacts.ts +113 -18
  114. package/src/resources/contacts/index.ts +1 -0
  115. package/src/resources/groups.ts +3 -0
  116. package/src/resources/index.ts +1 -0
  117. package/src/resources/lookups.ts +3 -0
  118. package/src/resources/media-objects.ts +3 -0
  119. package/src/resources/messages.ts +52 -7
  120. package/src/resources/typing-indicators.ts +11 -2
  121. package/src/resources/webhooks.ts +185 -154
  122. package/src/version.ts +1 -1
  123. package/version.d.mts +1 -1
  124. package/version.d.ts +1 -1
  125. package/version.js +1 -1
  126. package/version.mjs +1 -1
package/src/client.ts CHANGED
@@ -11,6 +11,7 @@ import type { APIResponseProps } from './internal/parse';
11
11
  import { getPlatformHeaders } from './internal/detect-platform';
12
12
  import * as Shims from './internal/shims';
13
13
  import * as Opts from './internal/request-options';
14
+ import { stringifyQuery } from './internal/utils/query';
14
15
  import { VERSION } from './version';
15
16
  import * as Errors from './core/error';
16
17
  import * as Uploads from './core/uploads';
@@ -51,6 +52,7 @@ import {
51
52
  ContactCreateParams,
52
53
  ContactCreateResponse,
53
54
  ContactDeleteResponse,
55
+ ContactListParams,
54
56
  ContactListResponse,
55
57
  ContactRetrieveResponse,
56
58
  ContactUpdateParams,
@@ -279,21 +281,8 @@ export class SendblueAPI {
279
281
  /**
280
282
  * Basic re-implementation of `qs.stringify` for primitive types.
281
283
  */
282
- protected stringifyQuery(query: Record<string, unknown>): string {
283
- return Object.entries(query)
284
- .filter(([_, value]) => typeof value !== 'undefined')
285
- .map(([key, value]) => {
286
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
287
- return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
288
- }
289
- if (value === null) {
290
- return `${encodeURIComponent(key)}=`;
291
- }
292
- throw new Errors.SendblueAPIError(
293
- `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
294
- );
295
- })
296
- .join('&');
284
+ protected stringifyQuery(query: object | Record<string, unknown>): string {
285
+ return stringifyQuery(query);
297
286
  }
298
287
 
299
288
  private getUserAgent(): string {
@@ -330,7 +319,7 @@ export class SendblueAPI {
330
319
  }
331
320
 
332
321
  if (typeof query === 'object' && query && !Array.isArray(query)) {
333
- url.search = this.stringifyQuery(query as Record<string, unknown>);
322
+ url.search = this.stringifyQuery(query);
334
323
  }
335
324
 
336
325
  return url.toString();
@@ -514,7 +503,7 @@ export class SendblueAPI {
514
503
  loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
515
504
 
516
505
  const errText = await response.text().catch((err: any) => castToError(err).message);
517
- const errJSON = safeJSON(errText);
506
+ const errJSON = safeJSON(errText) as any;
518
507
  const errMessage = errJSON ? undefined : errText;
519
508
 
520
509
  loggerFor(this).debug(
@@ -555,9 +544,10 @@ export class SendblueAPI {
555
544
  controller: AbortController,
556
545
  ): Promise<Response> {
557
546
  const { signal, method, ...options } = init || {};
558
- if (signal) signal.addEventListener('abort', () => controller.abort());
547
+ const abort = this._makeAbort(controller);
548
+ if (signal) signal.addEventListener('abort', abort, { once: true });
559
549
 
560
- const timeout = setTimeout(() => controller.abort(), ms);
550
+ const timeout = setTimeout(abort, ms);
561
551
 
562
552
  const isReadableBody =
563
553
  ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
@@ -634,9 +624,9 @@ export class SendblueAPI {
634
624
  }
635
625
  }
636
626
 
637
- // If the API asks us to wait a certain amount of time (and it's a reasonable amount),
638
- // just do what it says, but otherwise calculate a default
639
- if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {
627
+ // If the API asks us to wait a certain amount of time, just do what it
628
+ // says, but otherwise calculate a default
629
+ if (timeoutMillis === undefined) {
640
630
  const maxRetries = options.maxRetries ?? this.maxRetries;
641
631
  timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
642
632
  }
@@ -724,6 +714,12 @@ export class SendblueAPI {
724
714
  return headers.values;
725
715
  }
726
716
 
717
+ private _makeAbort(controller: AbortController) {
718
+ // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure
719
+ // would capture all request options, and cause a memory leak.
720
+ return () => controller.abort();
721
+ }
722
+
727
723
  private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
728
724
  bodyHeaders: HeadersLike;
729
725
  body: BodyInit | undefined;
@@ -756,6 +752,14 @@ export class SendblueAPI {
756
752
  (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))
757
753
  ) {
758
754
  return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable<Uint8Array>) };
755
+ } else if (
756
+ typeof body === 'object' &&
757
+ headers.values.get('content-type') === 'application/x-www-form-urlencoded'
758
+ ) {
759
+ return {
760
+ bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' },
761
+ body: this.stringifyQuery(body),
762
+ };
759
763
  } else {
760
764
  return this.#encoder({ body, headers });
761
765
  }
@@ -780,12 +784,33 @@ export class SendblueAPI {
780
784
 
781
785
  static toFile = Uploads.toFile;
782
786
 
787
+ /**
788
+ * Operations for sending and managing messages
789
+ */
783
790
  messages: API.Messages = new API.Messages(this);
791
+ /**
792
+ * Operations for group messaging (beta)
793
+ */
784
794
  groups: API.Groups = new API.Groups(this);
795
+ /**
796
+ * Operations for uploading and managing media files
797
+ */
785
798
  mediaObjects: API.MediaObjects = new API.MediaObjects(this);
799
+ /**
800
+ * Operations for looking up service availability for phone numbers
801
+ */
786
802
  lookups: API.Lookups = new API.Lookups(this);
803
+ /**
804
+ * Operations for sending and managing messages
805
+ */
787
806
  typingIndicators: API.TypingIndicators = new API.TypingIndicators(this);
807
+ /**
808
+ * Operations for managing contacts
809
+ */
788
810
  contacts: API.Contacts = new API.Contacts(this);
811
+ /**
812
+ * Operations for managing webhook subscriptions
813
+ */
789
814
  webhooks: API.Webhooks = new API.Webhooks(this);
790
815
  }
791
816
 
@@ -848,6 +873,7 @@ export declare namespace SendblueAPI {
848
873
  type ContactVerifyResponse as ContactVerifyResponse,
849
874
  type ContactCreateParams as ContactCreateParams,
850
875
  type ContactUpdateParams as ContactUpdateParams,
876
+ type ContactListParams as ContactListParams,
851
877
  type ContactVerifyParams as ContactVerifyParams,
852
878
  };
853
879
 
@@ -29,6 +29,12 @@ export async function defaultParseResponse<T>(client: SendblueAPI, props: APIRes
29
29
  const mediaType = contentType?.split(';')[0]?.trim();
30
30
  const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');
31
31
  if (isJSON) {
32
+ const contentLength = response.headers.get('content-length');
33
+ if (contentLength === '0') {
34
+ // if there is no content we can't do anything
35
+ return undefined as T;
36
+ }
37
+
32
38
  const json = await response.json();
33
39
  return json as T;
34
40
  }
@@ -0,0 +1,23 @@
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ import { SendblueAPIError } from '../../core/error';
4
+
5
+ /**
6
+ * Basic re-implementation of `qs.stringify` for primitive types.
7
+ */
8
+ export function stringifyQuery(query: object | Record<string, unknown>) {
9
+ return Object.entries(query)
10
+ .filter(([_, value]) => typeof value !== 'undefined')
11
+ .map(([key, value]) => {
12
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
13
+ return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
14
+ }
15
+ if (value === null) {
16
+ return `${encodeURIComponent(key)}=`;
17
+ }
18
+ throw new SendblueAPIError(
19
+ `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
20
+ );
21
+ })
22
+ .join('&');
23
+ }
@@ -6,3 +6,4 @@ export * from './utils/env';
6
6
  export * from './utils/log';
7
7
  export * from './utils/uuid';
8
8
  export * from './utils/sleep';
9
+ export * from './utils/query';
@@ -5,6 +5,9 @@ import * as ContactsAPI from './contacts';
5
5
  import { APIPromise } from '../../core/api-promise';
6
6
  import { RequestOptions } from '../../internal/request-options';
7
7
 
8
+ /**
9
+ * Operations for managing contacts
10
+ */
8
11
  export class Bulk extends APIResource {
9
12
  /**
10
13
  * Create multiple contacts in bulk
@@ -56,13 +59,31 @@ export interface BulkCreateParams {
56
59
 
57
60
  export namespace BulkCreateParams {
58
61
  export interface Contact {
62
+ /**
63
+ * Phone number in E.164 format
64
+ */
59
65
  phone: string;
60
66
 
61
- company?: string;
67
+ /**
68
+ * Company name
69
+ */
70
+ company_name?: string;
62
71
 
63
- firstName?: string;
72
+ /**
73
+ * Custom key-value pairs. Keys are human-readable labels; new labels are
74
+ * auto-created.
75
+ */
76
+ custom_variables?: { [key: string]: string };
64
77
 
65
- lastName?: string;
78
+ /**
79
+ * Contact's first name
80
+ */
81
+ first_name?: string;
82
+
83
+ /**
84
+ * Contact's last name
85
+ */
86
+ last_name?: string;
66
87
 
67
88
  tags?: Array<string>;
68
89
  }
@@ -7,6 +7,9 @@ import { APIPromise } from '../../core/api-promise';
7
7
  import { RequestOptions } from '../../internal/request-options';
8
8
  import { path } from '../../internal/utils/path';
9
9
 
10
+ /**
11
+ * Operations for managing contacts
12
+ */
10
13
  export class Contacts extends APIResource {
11
14
  bulk: BulkAPI.Bulk = new BulkAPI.Bulk(this._client);
12
15
 
@@ -62,8 +65,11 @@ export class Contacts extends APIResource {
62
65
  * const contacts = await client.contacts.list();
63
66
  * ```
64
67
  */
65
- list(options?: RequestOptions): APIPromise<ContactListResponse> {
66
- return this._client.get('/api/v2/contacts', options);
68
+ list(
69
+ query: ContactListParams | null | undefined = {},
70
+ options?: RequestOptions,
71
+ ): APIPromise<ContactListResponse> {
72
+ return this._client.get('/api/v2/contacts', { query, ...options });
67
73
  }
68
74
 
69
75
  /**
@@ -109,27 +115,32 @@ export interface Contact {
109
115
  /**
110
116
  * Email of assigned user
111
117
  */
112
- assignedToEmail?: string;
118
+ assigned_to_email?: string;
113
119
 
114
120
  /**
115
121
  * Company name
116
122
  */
117
- companyName?: string;
123
+ company_name?: string;
118
124
 
119
125
  /**
120
126
  * When the contact was created
121
127
  */
122
128
  created_at?: string;
123
129
 
130
+ /**
131
+ * Custom key-value pairs stored on the contact. Keys are human-readable labels.
132
+ */
133
+ custom_variables?: { [key: string]: string };
134
+
124
135
  /**
125
136
  * First name
126
137
  */
127
- firstName?: string;
138
+ first_name?: string;
128
139
 
129
140
  /**
130
141
  * Last name
131
142
  */
132
- lastName?: string;
143
+ last_name?: string;
133
144
 
134
145
  /**
135
146
  * Phone number in E.164 format
@@ -139,7 +150,7 @@ export interface Contact {
139
150
  /**
140
151
  * Associated Sendblue phone number
141
152
  */
142
- sendblueNumber?: string;
153
+ sendblue_number?: string;
143
154
 
144
155
  /**
145
156
  * Tags associated with the contact
@@ -189,57 +200,63 @@ export interface ContactVerifyResponse {
189
200
 
190
201
  export interface ContactCreateParams {
191
202
  /**
192
- * Contact's phone number in E.164 format
203
+ * Contact's phone number in E.164 format (preferred)
193
204
  */
194
205
  number: string;
195
206
 
196
207
  /**
197
- * Email of assigned user
208
+ * Email of assigned user (preferred)
198
209
  */
199
210
  assigned_to_email?: string;
200
211
 
201
212
  /**
202
- * Email of assigned user (alternative)
213
+ * @deprecated Email of assigned user (deprecated, use assigned_to_email)
203
214
  */
204
215
  assignedToEmail?: string;
205
216
 
206
217
  /**
207
- * Contact's first name
218
+ * Custom key-value pairs. Keys are human-readable labels; new labels are
219
+ * auto-created.
220
+ */
221
+ custom_variables?: { [key: string]: string };
222
+
223
+ /**
224
+ * Contact's first name (preferred)
208
225
  */
209
226
  first_name?: string;
210
227
 
211
228
  /**
212
- * Contact's first name (alternative)
229
+ * @deprecated Contact's first name (deprecated, use first_name)
213
230
  */
214
231
  firstName?: string;
215
232
 
216
233
  /**
217
- * Contact's last name
234
+ * Contact's last name (preferred)
218
235
  */
219
236
  last_name?: string;
220
237
 
221
238
  /**
222
- * Contact's last name (alternative)
239
+ * @deprecated Contact's last name (deprecated, use last_name)
223
240
  */
224
241
  lastName?: string;
225
242
 
226
243
  /**
227
- * Contact's phone number (alternative)
244
+ * @deprecated Contact's phone number (deprecated, use number)
228
245
  */
229
246
  phone_number?: string;
230
247
 
231
248
  /**
232
- * Contact's phone number (alternative)
249
+ * @deprecated Contact's phone number (deprecated, use number)
233
250
  */
234
251
  phoneNumber?: string;
235
252
 
236
253
  /**
237
- * Associated Sendblue phone number
254
+ * Associated Sendblue phone number to send with (preferred)
238
255
  */
239
256
  sendblue_number?: string;
240
257
 
241
258
  /**
242
- * Associated Sendblue phone number (alternative)
259
+ * @deprecated Associated Sendblue phone number (deprecated, use sendblue_number)
243
260
  */
244
261
  sendblueNumber?: string;
245
262
 
@@ -255,19 +272,96 @@ export interface ContactCreateParams {
255
272
  }
256
273
 
257
274
  export interface ContactUpdateParams {
275
+ /**
276
+ * Email of assigned user (preferred)
277
+ */
278
+ assigned_to_email?: string;
279
+
280
+ /**
281
+ * @deprecated Deprecated, use assigned_to_email
282
+ */
258
283
  assignedToEmail?: string;
259
284
 
285
+ /**
286
+ * Company name (preferred)
287
+ */
288
+ company_name?: string;
289
+
290
+ /**
291
+ * @deprecated Deprecated, use company_name
292
+ */
260
293
  companyName?: string;
261
294
 
295
+ /**
296
+ * Custom key-value pairs. Merged with existing variables (not replaced).
297
+ */
298
+ custom_variables?: { [key: string]: string };
299
+
300
+ /**
301
+ * Contact's first name (preferred)
302
+ */
303
+ first_name?: string;
304
+
305
+ /**
306
+ * @deprecated Deprecated, use first_name
307
+ */
262
308
  firstName?: string;
263
309
 
310
+ /**
311
+ * Contact's last name (preferred)
312
+ */
313
+ last_name?: string;
314
+
315
+ /**
316
+ * @deprecated Deprecated, use last_name
317
+ */
264
318
  lastName?: string;
265
319
 
320
+ /**
321
+ * Associated Sendblue phone number (preferred)
322
+ */
323
+ sendblue_number?: string;
324
+
325
+ /**
326
+ * @deprecated Deprecated, use sendblue_number
327
+ */
266
328
  sendblueNumber?: string;
267
329
 
268
330
  tags?: Array<string>;
269
331
  }
270
332
 
333
+ export interface ContactListParams {
334
+ /**
335
+ * Filter by contact ID
336
+ */
337
+ cid?: string;
338
+
339
+ /**
340
+ * Maximum number of contacts to return
341
+ */
342
+ limit?: number;
343
+
344
+ /**
345
+ * Number of contacts to skip
346
+ */
347
+ offset?: number;
348
+
349
+ /**
350
+ * Field to sort by
351
+ */
352
+ order_by?: string;
353
+
354
+ /**
355
+ * Sort direction
356
+ */
357
+ order_direction?: 'asc' | 'desc';
358
+
359
+ /**
360
+ * Filter by phone number
361
+ */
362
+ phone_number?: string;
363
+ }
364
+
271
365
  export interface ContactVerifyParams {
272
366
  /**
273
367
  * Phone number to verify
@@ -289,6 +383,7 @@ export declare namespace Contacts {
289
383
  type ContactVerifyResponse as ContactVerifyResponse,
290
384
  type ContactCreateParams as ContactCreateParams,
291
385
  type ContactUpdateParams as ContactUpdateParams,
386
+ type ContactListParams as ContactListParams,
292
387
  type ContactVerifyParams as ContactVerifyParams,
293
388
  };
294
389
 
@@ -19,5 +19,6 @@ export {
19
19
  type ContactVerifyResponse,
20
20
  type ContactCreateParams,
21
21
  type ContactUpdateParams,
22
+ type ContactListParams,
22
23
  type ContactVerifyParams,
23
24
  } from './contacts';
@@ -5,6 +5,9 @@ import * as MessagesAPI from './messages';
5
5
  import { APIPromise } from '../core/api-promise';
6
6
  import { RequestOptions } from '../internal/request-options';
7
7
 
8
+ /**
9
+ * Operations for group messaging (beta)
10
+ */
8
11
  export class Groups extends APIResource {
9
12
  /**
10
13
  * Add or manage participants in a group chat (beta feature)
@@ -12,6 +12,7 @@ export {
12
12
  type ContactVerifyResponse,
13
13
  type ContactCreateParams,
14
14
  type ContactUpdateParams,
15
+ type ContactListParams,
15
16
  type ContactVerifyParams,
16
17
  } from './contacts/contacts';
17
18
  export {
@@ -4,6 +4,9 @@ import { APIResource } from '../core/resource';
4
4
  import { APIPromise } from '../core/api-promise';
5
5
  import { RequestOptions } from '../internal/request-options';
6
6
 
7
+ /**
8
+ * Operations for looking up service availability for phone numbers
9
+ */
7
10
  export class Lookups extends APIResource {
8
11
  /**
9
12
  * Determine if a phone number supports iMessage or SMS. Useful for checking if a
@@ -4,6 +4,9 @@ import { APIResource } from '../core/resource';
4
4
  import { APIPromise } from '../core/api-promise';
5
5
  import { RequestOptions } from '../internal/request-options';
6
6
 
7
+ /**
8
+ * Operations for uploading and managing media files
9
+ */
7
10
  export class MediaObjects extends APIResource {
8
11
  /**
9
12
  * Upload a media file to Sendblue's CDN for use in messages
@@ -5,6 +5,9 @@ import { APIPromise } from '../core/api-promise';
5
5
  import { RequestOptions } from '../internal/request-options';
6
6
  import { path } from '../internal/utils/path';
7
7
 
8
+ /**
9
+ * Operations for sending and managing messages
10
+ */
8
11
  export class Messages extends APIResource {
9
12
  /**
10
13
  * Retrieve details of a specific message by its ID
@@ -24,6 +27,22 @@ export class Messages extends APIResource {
24
27
  * Retrieve a list of messages for the authenticated account with comprehensive
25
28
  * filtering capabilities. Rate limited to 100 requests per 10 seconds per account.
26
29
  *
30
+ * ## Common Use Cases
31
+ *
32
+ * **Polling for inbound messages (no webhooks):**
33
+ *
34
+ * ```
35
+ * GET /api/v2/messages?is_outbound=false&sendblue_number=+16292925296&order_by=createdAt&order_direction=desc&limit=50
36
+ * ```
37
+ *
38
+ * Track processed message IDs to avoid duplicates.
39
+ *
40
+ * **Get conversation with a specific contact:**
41
+ *
42
+ * ```
43
+ * GET /api/v2/messages?number=+15551234567&order_by=createdAt&order_direction=desc
44
+ * ```
45
+ *
27
46
  * @example
28
47
  * ```ts
29
48
  * const messages = await client.messages.list();
@@ -129,7 +148,7 @@ export interface MessageContent {
129
148
  | 'loud'
130
149
  | 'slam';
131
150
 
132
- status?: 'QUEUED' | 'SENT' | 'DELIVERED' | 'READ' | 'ERROR' | 'RECEIVED';
151
+ status?: 'QUEUED' | 'SENT' | 'DELIVERED' | 'ERROR' | 'RECEIVED';
133
152
 
134
153
  /**
135
154
  * Recipient phone number
@@ -211,7 +230,7 @@ export interface MessageResponse {
211
230
  | 'loud'
212
231
  | 'slam';
213
232
 
214
- status?: 'QUEUED' | 'SENT' | 'DELIVERED' | 'READ' | 'ERROR';
233
+ status?: 'QUEUED' | 'SENT' | 'DELIVERED' | 'ERROR';
215
234
  }
216
235
 
217
236
  export interface MessageRetrieveResponse {
@@ -337,7 +356,10 @@ export namespace MessageRetrieveResponse {
337
356
  */
338
357
  sendblue_number?: string | null;
339
358
 
340
- service?: 'iMessage' | 'SMS';
359
+ /**
360
+ * The messaging service used
361
+ */
362
+ service?: 'iMessage' | 'SMS' | 'RCS';
341
363
 
342
364
  status?:
343
365
  | 'REGISTERED'
@@ -488,7 +510,10 @@ export namespace MessageListResponse {
488
510
  */
489
511
  sendblue_number?: string | null;
490
512
 
491
- service?: 'iMessage' | 'SMS';
513
+ /**
514
+ * The messaging service used
515
+ */
516
+ service?: 'iMessage' | 'SMS' | 'RCS';
492
517
 
493
518
  status?:
494
519
  | 'REGISTERED'
@@ -563,7 +588,14 @@ export interface MessageListParams {
563
588
  group_id?: string;
564
589
 
565
590
  /**
566
- * Filter by message direction
591
+ * Filter by message direction. Use `false` to get inbound messages (messages sent
592
+ * TO your Sendblue number).
593
+ *
594
+ * **To get inbound messages for polling:** Use `is_outbound=false` combined with
595
+ * `sendblue_number` or `to_number` set to your Sendblue phone number.
596
+ *
597
+ * Note: Do NOT use `message_type=inbound` - that parameter only accepts `message`
598
+ * or `group` values.
567
599
  */
568
600
  is_outbound?: 'true' | 'false';
569
601
 
@@ -573,10 +605,18 @@ export interface MessageListParams {
573
605
  limit?: number;
574
606
 
575
607
  /**
576
- * Filter by message type
608
+ * Filter by message type (1:1 vs group chat). Only accepts `message` or `group`.
609
+ *
610
+ * **Common mistake:** This is NOT for filtering inbound vs outbound messages. Use
611
+ * `is_outbound` parameter instead.
577
612
  */
578
613
  message_type?: 'message' | 'group';
579
614
 
615
+ /**
616
+ * Filter by any phone number (from or to)
617
+ */
618
+ number?: string;
619
+
580
620
  /**
581
621
  * Number of messages to skip
582
622
  */
@@ -592,6 +632,11 @@ export interface MessageListParams {
592
632
  */
593
633
  order_direction?: 'asc' | 'desc';
594
634
 
635
+ /**
636
+ * Filter by Sendblue phone number
637
+ */
638
+ sendblue_number?: string;
639
+
595
640
  /**
596
641
  * Filter messages sent after this date (ISO 8601 format)
597
642
  */
@@ -605,7 +650,7 @@ export interface MessageListParams {
605
650
  /**
606
651
  * Filter by service type
607
652
  */
608
- service?: 'iMessage' | 'SMS';
653
+ service?: 'iMessage' | 'SMS' | 'RCS';
609
654
 
610
655
  /**
611
656
  * Filter by message status