@sendly/node 3.15.3 → 3.18.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/dist/index.d.mts +146 -3
- package/dist/index.d.ts +146 -3
- package/dist/index.js +123 -1
- package/dist/index.mjs +123 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -59,12 +59,17 @@ interface SendMessageRequest {
|
|
|
59
59
|
* Stored on the message record and included in webhook event payloads.
|
|
60
60
|
*/
|
|
61
61
|
metadata?: Record<string, any>;
|
|
62
|
+
/**
|
|
63
|
+
* URLs of media files to include as MMS attachments.
|
|
64
|
+
* Must be publicly accessible HTTPS URLs. Max 10 per message.
|
|
65
|
+
*/
|
|
66
|
+
mediaUrls?: string[];
|
|
62
67
|
}
|
|
63
68
|
/**
|
|
64
69
|
* Message status values
|
|
65
70
|
* Note: "sending" was removed as it doesn't exist in the database
|
|
66
71
|
*/
|
|
67
|
-
type MessageStatus = "queued" | "sent" | "delivered" | "failed" | "bounced";
|
|
72
|
+
type MessageStatus = "queued" | "sent" | "delivered" | "failed" | "bounced" | "retrying";
|
|
68
73
|
/**
|
|
69
74
|
* How the message was sent
|
|
70
75
|
*/
|
|
@@ -101,6 +106,14 @@ interface Message {
|
|
|
101
106
|
* Error message if status is "failed"
|
|
102
107
|
*/
|
|
103
108
|
error?: string | null;
|
|
109
|
+
/**
|
|
110
|
+
* Structured error code (e.g., "E001" for invalid number)
|
|
111
|
+
*/
|
|
112
|
+
errorCode?: string | null;
|
|
113
|
+
/**
|
|
114
|
+
* Number of retry attempts made
|
|
115
|
+
*/
|
|
116
|
+
retryCount?: number;
|
|
104
117
|
/**
|
|
105
118
|
* Number of SMS segments (1 per 160 chars)
|
|
106
119
|
*/
|
|
@@ -177,6 +190,42 @@ interface MessageListResponse {
|
|
|
177
190
|
*/
|
|
178
191
|
count: number;
|
|
179
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* An uploaded media file for MMS
|
|
195
|
+
*/
|
|
196
|
+
interface MediaFile {
|
|
197
|
+
/**
|
|
198
|
+
* Unique media file identifier
|
|
199
|
+
*/
|
|
200
|
+
id: string;
|
|
201
|
+
/**
|
|
202
|
+
* Publicly accessible URL for the media file
|
|
203
|
+
*/
|
|
204
|
+
url: string;
|
|
205
|
+
/**
|
|
206
|
+
* MIME type of the file (e.g., "image/jpeg")
|
|
207
|
+
*/
|
|
208
|
+
contentType: string;
|
|
209
|
+
/**
|
|
210
|
+
* File size in bytes
|
|
211
|
+
*/
|
|
212
|
+
sizeBytes: number;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Options for uploading a media file
|
|
216
|
+
*/
|
|
217
|
+
interface MediaUploadOptions {
|
|
218
|
+
/**
|
|
219
|
+
* Filename for the upload
|
|
220
|
+
* @default "upload.jpg"
|
|
221
|
+
*/
|
|
222
|
+
filename?: string;
|
|
223
|
+
/**
|
|
224
|
+
* MIME content type
|
|
225
|
+
* @default "image/jpeg"
|
|
226
|
+
*/
|
|
227
|
+
contentType?: string;
|
|
228
|
+
}
|
|
180
229
|
/**
|
|
181
230
|
* Request payload for scheduling an SMS message
|
|
182
231
|
*/
|
|
@@ -625,7 +674,7 @@ declare const ALL_SUPPORTED_COUNTRIES: string[];
|
|
|
625
674
|
/**
|
|
626
675
|
* Webhook event types
|
|
627
676
|
*/
|
|
628
|
-
type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.queued";
|
|
677
|
+
type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.retrying" | "message.queued";
|
|
629
678
|
/**
|
|
630
679
|
* Webhook mode - filters which events are delivered
|
|
631
680
|
* - "all": Receives all events (sandbox + production)
|
|
@@ -1492,6 +1541,10 @@ declare class HttpClient {
|
|
|
1492
1541
|
* Make an HTTP request to the API
|
|
1493
1542
|
*/
|
|
1494
1543
|
request<T>(options: RequestOptions): Promise<T>;
|
|
1544
|
+
/**
|
|
1545
|
+
* Make an HTTP request with a raw body (for multipart uploads)
|
|
1546
|
+
*/
|
|
1547
|
+
requestFormData<T>(path: string, body: FormData, headers?: Record<string, string>): Promise<T>;
|
|
1495
1548
|
/**
|
|
1496
1549
|
* Execute the HTTP request
|
|
1497
1550
|
*/
|
|
@@ -1928,6 +1981,25 @@ declare class WebhooksResource {
|
|
|
1928
1981
|
* ```
|
|
1929
1982
|
*/
|
|
1930
1983
|
test(id: string): Promise<WebhookTestResult>;
|
|
1984
|
+
/**
|
|
1985
|
+
* Reset the circuit breaker for a webhook
|
|
1986
|
+
*
|
|
1987
|
+
* Manually resets an open circuit breaker so deliveries resume immediately
|
|
1988
|
+
* instead of waiting for the automatic 5-minute recovery.
|
|
1989
|
+
*
|
|
1990
|
+
* @param id - Webhook ID
|
|
1991
|
+
* @returns Reset confirmation with updated webhook
|
|
1992
|
+
*
|
|
1993
|
+
* @example
|
|
1994
|
+
* ```typescript
|
|
1995
|
+
* const result = await sendly.webhooks.resetCircuit('whk_xxx');
|
|
1996
|
+
* console.log(result.message);
|
|
1997
|
+
* ```
|
|
1998
|
+
*/
|
|
1999
|
+
resetCircuit(id: string): Promise<{
|
|
2000
|
+
message: string;
|
|
2001
|
+
webhook: Webhook;
|
|
2002
|
+
}>;
|
|
1931
2003
|
/**
|
|
1932
2004
|
* Rotate the webhook signing secret
|
|
1933
2005
|
*
|
|
@@ -2927,6 +2999,57 @@ declare class ContactListsResource {
|
|
|
2927
2999
|
private transformList;
|
|
2928
3000
|
}
|
|
2929
3001
|
|
|
3002
|
+
/**
|
|
3003
|
+
* Media Resource
|
|
3004
|
+
* @packageDocumentation
|
|
3005
|
+
*/
|
|
3006
|
+
|
|
3007
|
+
/**
|
|
3008
|
+
* Media API resource
|
|
3009
|
+
*
|
|
3010
|
+
* @example
|
|
3011
|
+
* ```typescript
|
|
3012
|
+
* // Upload an image and send as MMS
|
|
3013
|
+
* const file = fs.readFileSync('photo.jpg');
|
|
3014
|
+
* const media = await sendly.media.upload(file, {
|
|
3015
|
+
* filename: 'photo.jpg',
|
|
3016
|
+
* contentType: 'image/jpeg'
|
|
3017
|
+
* });
|
|
3018
|
+
*
|
|
3019
|
+
* await sendly.messages.send({
|
|
3020
|
+
* to: '+15551234567',
|
|
3021
|
+
* text: 'Check out this photo!',
|
|
3022
|
+
* mediaUrls: [media.url]
|
|
3023
|
+
* });
|
|
3024
|
+
* ```
|
|
3025
|
+
*/
|
|
3026
|
+
declare class MediaResource {
|
|
3027
|
+
private readonly http;
|
|
3028
|
+
constructor(http: HttpClient);
|
|
3029
|
+
/**
|
|
3030
|
+
* Upload a media file for use in MMS messages
|
|
3031
|
+
*
|
|
3032
|
+
* @param file - File data as a Buffer or ReadableStream
|
|
3033
|
+
* @param options - Upload options (filename, content type)
|
|
3034
|
+
* @returns The uploaded media file with URL
|
|
3035
|
+
*
|
|
3036
|
+
* @example
|
|
3037
|
+
* ```typescript
|
|
3038
|
+
* const media = await sendly.media.upload(
|
|
3039
|
+
* fs.readFileSync('image.png'),
|
|
3040
|
+
* { filename: 'image.png', contentType: 'image/png' }
|
|
3041
|
+
* );
|
|
3042
|
+
*
|
|
3043
|
+
* console.log(media.url); // https://...
|
|
3044
|
+
* ```
|
|
3045
|
+
*
|
|
3046
|
+
* @throws {ValidationError} If the file is invalid or too large
|
|
3047
|
+
* @throws {AuthenticationError} If the API key is invalid
|
|
3048
|
+
* @throws {RateLimitError} If rate limit is exceeded
|
|
3049
|
+
*/
|
|
3050
|
+
upload(file: Buffer | NodeJS.ReadableStream, options?: MediaUploadOptions): Promise<MediaFile>;
|
|
3051
|
+
}
|
|
3052
|
+
|
|
2930
3053
|
/**
|
|
2931
3054
|
* Sendly Client
|
|
2932
3055
|
* @packageDocumentation
|
|
@@ -3097,6 +3220,26 @@ declare class Sendly {
|
|
|
3097
3220
|
* ```
|
|
3098
3221
|
*/
|
|
3099
3222
|
readonly contacts: ContactsResource;
|
|
3223
|
+
/**
|
|
3224
|
+
* Media API resource - Upload media for MMS
|
|
3225
|
+
*
|
|
3226
|
+
* @example
|
|
3227
|
+
* ```typescript
|
|
3228
|
+
* // Upload a file
|
|
3229
|
+
* const media = await sendly.media.upload(fileBuffer, {
|
|
3230
|
+
* filename: 'photo.jpg',
|
|
3231
|
+
* contentType: 'image/jpeg'
|
|
3232
|
+
* });
|
|
3233
|
+
*
|
|
3234
|
+
* // Send as MMS
|
|
3235
|
+
* await sendly.messages.send({
|
|
3236
|
+
* to: '+15551234567',
|
|
3237
|
+
* text: 'Check this out!',
|
|
3238
|
+
* mediaUrls: [media.url]
|
|
3239
|
+
* });
|
|
3240
|
+
* ```
|
|
3241
|
+
*/
|
|
3242
|
+
readonly media: MediaResource;
|
|
3100
3243
|
private readonly http;
|
|
3101
3244
|
private readonly config;
|
|
3102
3245
|
/**
|
|
@@ -3547,4 +3690,4 @@ declare class Webhooks {
|
|
|
3547
3690
|
*/
|
|
3548
3691
|
type WebhookMessageData = WebhookMessageObject;
|
|
3549
3692
|
|
|
3550
|
-
export { ALL_SUPPORTED_COUNTRIES, type Account, type ApiErrorResponse, type ApiKey, AuthenticationError, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreditTransaction, type Credits, type DeliveryStatus, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type Message, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type PricingTier, RateLimitError, type RateLimitInfo, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
|
|
3693
|
+
export { ALL_SUPPORTED_COUNTRIES, type Account, type ApiErrorResponse, type ApiKey, AuthenticationError, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreditTransaction, type Credits, type DeliveryStatus, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type MediaFile, type MediaUploadOptions, type Message, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type PricingTier, RateLimitError, type RateLimitInfo, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -59,12 +59,17 @@ interface SendMessageRequest {
|
|
|
59
59
|
* Stored on the message record and included in webhook event payloads.
|
|
60
60
|
*/
|
|
61
61
|
metadata?: Record<string, any>;
|
|
62
|
+
/**
|
|
63
|
+
* URLs of media files to include as MMS attachments.
|
|
64
|
+
* Must be publicly accessible HTTPS URLs. Max 10 per message.
|
|
65
|
+
*/
|
|
66
|
+
mediaUrls?: string[];
|
|
62
67
|
}
|
|
63
68
|
/**
|
|
64
69
|
* Message status values
|
|
65
70
|
* Note: "sending" was removed as it doesn't exist in the database
|
|
66
71
|
*/
|
|
67
|
-
type MessageStatus = "queued" | "sent" | "delivered" | "failed" | "bounced";
|
|
72
|
+
type MessageStatus = "queued" | "sent" | "delivered" | "failed" | "bounced" | "retrying";
|
|
68
73
|
/**
|
|
69
74
|
* How the message was sent
|
|
70
75
|
*/
|
|
@@ -101,6 +106,14 @@ interface Message {
|
|
|
101
106
|
* Error message if status is "failed"
|
|
102
107
|
*/
|
|
103
108
|
error?: string | null;
|
|
109
|
+
/**
|
|
110
|
+
* Structured error code (e.g., "E001" for invalid number)
|
|
111
|
+
*/
|
|
112
|
+
errorCode?: string | null;
|
|
113
|
+
/**
|
|
114
|
+
* Number of retry attempts made
|
|
115
|
+
*/
|
|
116
|
+
retryCount?: number;
|
|
104
117
|
/**
|
|
105
118
|
* Number of SMS segments (1 per 160 chars)
|
|
106
119
|
*/
|
|
@@ -177,6 +190,42 @@ interface MessageListResponse {
|
|
|
177
190
|
*/
|
|
178
191
|
count: number;
|
|
179
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* An uploaded media file for MMS
|
|
195
|
+
*/
|
|
196
|
+
interface MediaFile {
|
|
197
|
+
/**
|
|
198
|
+
* Unique media file identifier
|
|
199
|
+
*/
|
|
200
|
+
id: string;
|
|
201
|
+
/**
|
|
202
|
+
* Publicly accessible URL for the media file
|
|
203
|
+
*/
|
|
204
|
+
url: string;
|
|
205
|
+
/**
|
|
206
|
+
* MIME type of the file (e.g., "image/jpeg")
|
|
207
|
+
*/
|
|
208
|
+
contentType: string;
|
|
209
|
+
/**
|
|
210
|
+
* File size in bytes
|
|
211
|
+
*/
|
|
212
|
+
sizeBytes: number;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Options for uploading a media file
|
|
216
|
+
*/
|
|
217
|
+
interface MediaUploadOptions {
|
|
218
|
+
/**
|
|
219
|
+
* Filename for the upload
|
|
220
|
+
* @default "upload.jpg"
|
|
221
|
+
*/
|
|
222
|
+
filename?: string;
|
|
223
|
+
/**
|
|
224
|
+
* MIME content type
|
|
225
|
+
* @default "image/jpeg"
|
|
226
|
+
*/
|
|
227
|
+
contentType?: string;
|
|
228
|
+
}
|
|
180
229
|
/**
|
|
181
230
|
* Request payload for scheduling an SMS message
|
|
182
231
|
*/
|
|
@@ -625,7 +674,7 @@ declare const ALL_SUPPORTED_COUNTRIES: string[];
|
|
|
625
674
|
/**
|
|
626
675
|
* Webhook event types
|
|
627
676
|
*/
|
|
628
|
-
type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.queued";
|
|
677
|
+
type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.retrying" | "message.queued";
|
|
629
678
|
/**
|
|
630
679
|
* Webhook mode - filters which events are delivered
|
|
631
680
|
* - "all": Receives all events (sandbox + production)
|
|
@@ -1492,6 +1541,10 @@ declare class HttpClient {
|
|
|
1492
1541
|
* Make an HTTP request to the API
|
|
1493
1542
|
*/
|
|
1494
1543
|
request<T>(options: RequestOptions): Promise<T>;
|
|
1544
|
+
/**
|
|
1545
|
+
* Make an HTTP request with a raw body (for multipart uploads)
|
|
1546
|
+
*/
|
|
1547
|
+
requestFormData<T>(path: string, body: FormData, headers?: Record<string, string>): Promise<T>;
|
|
1495
1548
|
/**
|
|
1496
1549
|
* Execute the HTTP request
|
|
1497
1550
|
*/
|
|
@@ -1928,6 +1981,25 @@ declare class WebhooksResource {
|
|
|
1928
1981
|
* ```
|
|
1929
1982
|
*/
|
|
1930
1983
|
test(id: string): Promise<WebhookTestResult>;
|
|
1984
|
+
/**
|
|
1985
|
+
* Reset the circuit breaker for a webhook
|
|
1986
|
+
*
|
|
1987
|
+
* Manually resets an open circuit breaker so deliveries resume immediately
|
|
1988
|
+
* instead of waiting for the automatic 5-minute recovery.
|
|
1989
|
+
*
|
|
1990
|
+
* @param id - Webhook ID
|
|
1991
|
+
* @returns Reset confirmation with updated webhook
|
|
1992
|
+
*
|
|
1993
|
+
* @example
|
|
1994
|
+
* ```typescript
|
|
1995
|
+
* const result = await sendly.webhooks.resetCircuit('whk_xxx');
|
|
1996
|
+
* console.log(result.message);
|
|
1997
|
+
* ```
|
|
1998
|
+
*/
|
|
1999
|
+
resetCircuit(id: string): Promise<{
|
|
2000
|
+
message: string;
|
|
2001
|
+
webhook: Webhook;
|
|
2002
|
+
}>;
|
|
1931
2003
|
/**
|
|
1932
2004
|
* Rotate the webhook signing secret
|
|
1933
2005
|
*
|
|
@@ -2927,6 +2999,57 @@ declare class ContactListsResource {
|
|
|
2927
2999
|
private transformList;
|
|
2928
3000
|
}
|
|
2929
3001
|
|
|
3002
|
+
/**
|
|
3003
|
+
* Media Resource
|
|
3004
|
+
* @packageDocumentation
|
|
3005
|
+
*/
|
|
3006
|
+
|
|
3007
|
+
/**
|
|
3008
|
+
* Media API resource
|
|
3009
|
+
*
|
|
3010
|
+
* @example
|
|
3011
|
+
* ```typescript
|
|
3012
|
+
* // Upload an image and send as MMS
|
|
3013
|
+
* const file = fs.readFileSync('photo.jpg');
|
|
3014
|
+
* const media = await sendly.media.upload(file, {
|
|
3015
|
+
* filename: 'photo.jpg',
|
|
3016
|
+
* contentType: 'image/jpeg'
|
|
3017
|
+
* });
|
|
3018
|
+
*
|
|
3019
|
+
* await sendly.messages.send({
|
|
3020
|
+
* to: '+15551234567',
|
|
3021
|
+
* text: 'Check out this photo!',
|
|
3022
|
+
* mediaUrls: [media.url]
|
|
3023
|
+
* });
|
|
3024
|
+
* ```
|
|
3025
|
+
*/
|
|
3026
|
+
declare class MediaResource {
|
|
3027
|
+
private readonly http;
|
|
3028
|
+
constructor(http: HttpClient);
|
|
3029
|
+
/**
|
|
3030
|
+
* Upload a media file for use in MMS messages
|
|
3031
|
+
*
|
|
3032
|
+
* @param file - File data as a Buffer or ReadableStream
|
|
3033
|
+
* @param options - Upload options (filename, content type)
|
|
3034
|
+
* @returns The uploaded media file with URL
|
|
3035
|
+
*
|
|
3036
|
+
* @example
|
|
3037
|
+
* ```typescript
|
|
3038
|
+
* const media = await sendly.media.upload(
|
|
3039
|
+
* fs.readFileSync('image.png'),
|
|
3040
|
+
* { filename: 'image.png', contentType: 'image/png' }
|
|
3041
|
+
* );
|
|
3042
|
+
*
|
|
3043
|
+
* console.log(media.url); // https://...
|
|
3044
|
+
* ```
|
|
3045
|
+
*
|
|
3046
|
+
* @throws {ValidationError} If the file is invalid or too large
|
|
3047
|
+
* @throws {AuthenticationError} If the API key is invalid
|
|
3048
|
+
* @throws {RateLimitError} If rate limit is exceeded
|
|
3049
|
+
*/
|
|
3050
|
+
upload(file: Buffer | NodeJS.ReadableStream, options?: MediaUploadOptions): Promise<MediaFile>;
|
|
3051
|
+
}
|
|
3052
|
+
|
|
2930
3053
|
/**
|
|
2931
3054
|
* Sendly Client
|
|
2932
3055
|
* @packageDocumentation
|
|
@@ -3097,6 +3220,26 @@ declare class Sendly {
|
|
|
3097
3220
|
* ```
|
|
3098
3221
|
*/
|
|
3099
3222
|
readonly contacts: ContactsResource;
|
|
3223
|
+
/**
|
|
3224
|
+
* Media API resource - Upload media for MMS
|
|
3225
|
+
*
|
|
3226
|
+
* @example
|
|
3227
|
+
* ```typescript
|
|
3228
|
+
* // Upload a file
|
|
3229
|
+
* const media = await sendly.media.upload(fileBuffer, {
|
|
3230
|
+
* filename: 'photo.jpg',
|
|
3231
|
+
* contentType: 'image/jpeg'
|
|
3232
|
+
* });
|
|
3233
|
+
*
|
|
3234
|
+
* // Send as MMS
|
|
3235
|
+
* await sendly.messages.send({
|
|
3236
|
+
* to: '+15551234567',
|
|
3237
|
+
* text: 'Check this out!',
|
|
3238
|
+
* mediaUrls: [media.url]
|
|
3239
|
+
* });
|
|
3240
|
+
* ```
|
|
3241
|
+
*/
|
|
3242
|
+
readonly media: MediaResource;
|
|
3100
3243
|
private readonly http;
|
|
3101
3244
|
private readonly config;
|
|
3102
3245
|
/**
|
|
@@ -3547,4 +3690,4 @@ declare class Webhooks {
|
|
|
3547
3690
|
*/
|
|
3548
3691
|
type WebhookMessageData = WebhookMessageObject;
|
|
3549
3692
|
|
|
3550
|
-
export { ALL_SUPPORTED_COUNTRIES, type Account, type ApiErrorResponse, type ApiKey, AuthenticationError, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreditTransaction, type Credits, type DeliveryStatus, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type Message, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type PricingTier, RateLimitError, type RateLimitInfo, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
|
|
3693
|
+
export { ALL_SUPPORTED_COUNTRIES, type Account, type ApiErrorResponse, type ApiKey, AuthenticationError, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreditTransaction, type Credits, type DeliveryStatus, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type MediaFile, type MediaUploadOptions, type Message, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type PricingTier, RateLimitError, type RateLimitInfo, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -268,6 +268,44 @@ var HttpClient = class {
|
|
|
268
268
|
}
|
|
269
269
|
throw lastError || new NetworkError("Request failed after retries");
|
|
270
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Make an HTTP request with a raw body (for multipart uploads)
|
|
273
|
+
*/
|
|
274
|
+
async requestFormData(path, body, headers = {}) {
|
|
275
|
+
const url = this.buildUrl(path);
|
|
276
|
+
const baseHeaders = this.buildHeaders();
|
|
277
|
+
delete baseHeaders["Content-Type"];
|
|
278
|
+
const mergedHeaders = { ...baseHeaders, ...headers };
|
|
279
|
+
let lastError;
|
|
280
|
+
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
281
|
+
try {
|
|
282
|
+
const response = await this.executeRequest(url, {
|
|
283
|
+
method: "POST",
|
|
284
|
+
headers: mergedHeaders,
|
|
285
|
+
body
|
|
286
|
+
});
|
|
287
|
+
this.updateRateLimitInfo(response.headers);
|
|
288
|
+
const data = await this.parseResponse(response);
|
|
289
|
+
return data;
|
|
290
|
+
} catch (error) {
|
|
291
|
+
lastError = error;
|
|
292
|
+
if (error instanceof SendlyError) {
|
|
293
|
+
if (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 || error.statusCode === 404 || error.statusCode === 402) {
|
|
294
|
+
throw error;
|
|
295
|
+
}
|
|
296
|
+
if (error instanceof RateLimitError) {
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (attempt < this.config.maxRetries) {
|
|
301
|
+
const backoffTime = this.calculateBackoff(attempt);
|
|
302
|
+
await this.sleep(backoffTime);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
throw lastError || new NetworkError("Request failed after retries");
|
|
308
|
+
}
|
|
271
309
|
/**
|
|
272
310
|
* Execute the HTTP request
|
|
273
311
|
*/
|
|
@@ -640,7 +678,8 @@ var MessagesResource = class {
|
|
|
640
678
|
text: request.text,
|
|
641
679
|
...request.from && { from: request.from },
|
|
642
680
|
...request.messageType && { messageType: request.messageType },
|
|
643
|
-
...request.metadata && { metadata: request.metadata }
|
|
681
|
+
...request.metadata && { metadata: request.metadata },
|
|
682
|
+
...request.mediaUrls && { mediaUrls: request.mediaUrls }
|
|
644
683
|
}
|
|
645
684
|
});
|
|
646
685
|
return message;
|
|
@@ -1246,6 +1285,31 @@ var WebhooksResource = class {
|
|
|
1246
1285
|
});
|
|
1247
1286
|
return transformKeys(response);
|
|
1248
1287
|
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Reset the circuit breaker for a webhook
|
|
1290
|
+
*
|
|
1291
|
+
* Manually resets an open circuit breaker so deliveries resume immediately
|
|
1292
|
+
* instead of waiting for the automatic 5-minute recovery.
|
|
1293
|
+
*
|
|
1294
|
+
* @param id - Webhook ID
|
|
1295
|
+
* @returns Reset confirmation with updated webhook
|
|
1296
|
+
*
|
|
1297
|
+
* @example
|
|
1298
|
+
* ```typescript
|
|
1299
|
+
* const result = await sendly.webhooks.resetCircuit('whk_xxx');
|
|
1300
|
+
* console.log(result.message);
|
|
1301
|
+
* ```
|
|
1302
|
+
*/
|
|
1303
|
+
async resetCircuit(id) {
|
|
1304
|
+
if (!id || !id.startsWith("whk_")) {
|
|
1305
|
+
throw new Error("Invalid webhook ID format");
|
|
1306
|
+
}
|
|
1307
|
+
const response = await this.http.request({
|
|
1308
|
+
method: "POST",
|
|
1309
|
+
path: `/webhooks/${encodeURIComponent(id)}/reset-circuit`
|
|
1310
|
+
});
|
|
1311
|
+
return transformKeys(response);
|
|
1312
|
+
}
|
|
1249
1313
|
/**
|
|
1250
1314
|
* Rotate the webhook signing secret
|
|
1251
1315
|
*
|
|
@@ -2732,6 +2796,43 @@ var ContactListsResource = class {
|
|
|
2732
2796
|
}
|
|
2733
2797
|
};
|
|
2734
2798
|
|
|
2799
|
+
// src/resources/media.ts
|
|
2800
|
+
var MediaResource = class {
|
|
2801
|
+
http;
|
|
2802
|
+
constructor(http) {
|
|
2803
|
+
this.http = http;
|
|
2804
|
+
}
|
|
2805
|
+
/**
|
|
2806
|
+
* Upload a media file for use in MMS messages
|
|
2807
|
+
*
|
|
2808
|
+
* @param file - File data as a Buffer or ReadableStream
|
|
2809
|
+
* @param options - Upload options (filename, content type)
|
|
2810
|
+
* @returns The uploaded media file with URL
|
|
2811
|
+
*
|
|
2812
|
+
* @example
|
|
2813
|
+
* ```typescript
|
|
2814
|
+
* const media = await sendly.media.upload(
|
|
2815
|
+
* fs.readFileSync('image.png'),
|
|
2816
|
+
* { filename: 'image.png', contentType: 'image/png' }
|
|
2817
|
+
* );
|
|
2818
|
+
*
|
|
2819
|
+
* console.log(media.url); // https://...
|
|
2820
|
+
* ```
|
|
2821
|
+
*
|
|
2822
|
+
* @throws {ValidationError} If the file is invalid or too large
|
|
2823
|
+
* @throws {AuthenticationError} If the API key is invalid
|
|
2824
|
+
* @throws {RateLimitError} If rate limit is exceeded
|
|
2825
|
+
*/
|
|
2826
|
+
async upload(file, options) {
|
|
2827
|
+
const filename = options?.filename || "upload.jpg";
|
|
2828
|
+
const contentType = options?.contentType || "image/jpeg";
|
|
2829
|
+
const blob = file instanceof Buffer ? new Blob([file], { type: contentType }) : file;
|
|
2830
|
+
const form = new FormData();
|
|
2831
|
+
form.append("file", blob, filename);
|
|
2832
|
+
return this.http.requestFormData("/media", form);
|
|
2833
|
+
}
|
|
2834
|
+
};
|
|
2835
|
+
|
|
2735
2836
|
// src/client.ts
|
|
2736
2837
|
var DEFAULT_BASE_URL2 = "https://sendly.live/api/v1";
|
|
2737
2838
|
var DEFAULT_TIMEOUT2 = 3e4;
|
|
@@ -2870,6 +2971,26 @@ var Sendly = class {
|
|
|
2870
2971
|
* ```
|
|
2871
2972
|
*/
|
|
2872
2973
|
contacts;
|
|
2974
|
+
/**
|
|
2975
|
+
* Media API resource - Upload media for MMS
|
|
2976
|
+
*
|
|
2977
|
+
* @example
|
|
2978
|
+
* ```typescript
|
|
2979
|
+
* // Upload a file
|
|
2980
|
+
* const media = await sendly.media.upload(fileBuffer, {
|
|
2981
|
+
* filename: 'photo.jpg',
|
|
2982
|
+
* contentType: 'image/jpeg'
|
|
2983
|
+
* });
|
|
2984
|
+
*
|
|
2985
|
+
* // Send as MMS
|
|
2986
|
+
* await sendly.messages.send({
|
|
2987
|
+
* to: '+15551234567',
|
|
2988
|
+
* text: 'Check this out!',
|
|
2989
|
+
* mediaUrls: [media.url]
|
|
2990
|
+
* });
|
|
2991
|
+
* ```
|
|
2992
|
+
*/
|
|
2993
|
+
media;
|
|
2873
2994
|
http;
|
|
2874
2995
|
config;
|
|
2875
2996
|
/**
|
|
@@ -2906,6 +3027,7 @@ var Sendly = class {
|
|
|
2906
3027
|
this.templates = new TemplatesResource(this.http);
|
|
2907
3028
|
this.campaigns = new CampaignsResource(this.http);
|
|
2908
3029
|
this.contacts = new ContactsResource(this.http);
|
|
3030
|
+
this.media = new MediaResource(this.http);
|
|
2909
3031
|
}
|
|
2910
3032
|
/**
|
|
2911
3033
|
* Check if the client is using a test API key
|
package/dist/index.mjs
CHANGED
|
@@ -208,6 +208,44 @@ var HttpClient = class {
|
|
|
208
208
|
}
|
|
209
209
|
throw lastError || new NetworkError("Request failed after retries");
|
|
210
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Make an HTTP request with a raw body (for multipart uploads)
|
|
213
|
+
*/
|
|
214
|
+
async requestFormData(path, body, headers = {}) {
|
|
215
|
+
const url = this.buildUrl(path);
|
|
216
|
+
const baseHeaders = this.buildHeaders();
|
|
217
|
+
delete baseHeaders["Content-Type"];
|
|
218
|
+
const mergedHeaders = { ...baseHeaders, ...headers };
|
|
219
|
+
let lastError;
|
|
220
|
+
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
221
|
+
try {
|
|
222
|
+
const response = await this.executeRequest(url, {
|
|
223
|
+
method: "POST",
|
|
224
|
+
headers: mergedHeaders,
|
|
225
|
+
body
|
|
226
|
+
});
|
|
227
|
+
this.updateRateLimitInfo(response.headers);
|
|
228
|
+
const data = await this.parseResponse(response);
|
|
229
|
+
return data;
|
|
230
|
+
} catch (error) {
|
|
231
|
+
lastError = error;
|
|
232
|
+
if (error instanceof SendlyError) {
|
|
233
|
+
if (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 || error.statusCode === 404 || error.statusCode === 402) {
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
if (error instanceof RateLimitError) {
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (attempt < this.config.maxRetries) {
|
|
241
|
+
const backoffTime = this.calculateBackoff(attempt);
|
|
242
|
+
await this.sleep(backoffTime);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
throw lastError || new NetworkError("Request failed after retries");
|
|
248
|
+
}
|
|
211
249
|
/**
|
|
212
250
|
* Execute the HTTP request
|
|
213
251
|
*/
|
|
@@ -580,7 +618,8 @@ var MessagesResource = class {
|
|
|
580
618
|
text: request.text,
|
|
581
619
|
...request.from && { from: request.from },
|
|
582
620
|
...request.messageType && { messageType: request.messageType },
|
|
583
|
-
...request.metadata && { metadata: request.metadata }
|
|
621
|
+
...request.metadata && { metadata: request.metadata },
|
|
622
|
+
...request.mediaUrls && { mediaUrls: request.mediaUrls }
|
|
584
623
|
}
|
|
585
624
|
});
|
|
586
625
|
return message;
|
|
@@ -1186,6 +1225,31 @@ var WebhooksResource = class {
|
|
|
1186
1225
|
});
|
|
1187
1226
|
return transformKeys(response);
|
|
1188
1227
|
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Reset the circuit breaker for a webhook
|
|
1230
|
+
*
|
|
1231
|
+
* Manually resets an open circuit breaker so deliveries resume immediately
|
|
1232
|
+
* instead of waiting for the automatic 5-minute recovery.
|
|
1233
|
+
*
|
|
1234
|
+
* @param id - Webhook ID
|
|
1235
|
+
* @returns Reset confirmation with updated webhook
|
|
1236
|
+
*
|
|
1237
|
+
* @example
|
|
1238
|
+
* ```typescript
|
|
1239
|
+
* const result = await sendly.webhooks.resetCircuit('whk_xxx');
|
|
1240
|
+
* console.log(result.message);
|
|
1241
|
+
* ```
|
|
1242
|
+
*/
|
|
1243
|
+
async resetCircuit(id) {
|
|
1244
|
+
if (!id || !id.startsWith("whk_")) {
|
|
1245
|
+
throw new Error("Invalid webhook ID format");
|
|
1246
|
+
}
|
|
1247
|
+
const response = await this.http.request({
|
|
1248
|
+
method: "POST",
|
|
1249
|
+
path: `/webhooks/${encodeURIComponent(id)}/reset-circuit`
|
|
1250
|
+
});
|
|
1251
|
+
return transformKeys(response);
|
|
1252
|
+
}
|
|
1189
1253
|
/**
|
|
1190
1254
|
* Rotate the webhook signing secret
|
|
1191
1255
|
*
|
|
@@ -2672,6 +2736,43 @@ var ContactListsResource = class {
|
|
|
2672
2736
|
}
|
|
2673
2737
|
};
|
|
2674
2738
|
|
|
2739
|
+
// src/resources/media.ts
|
|
2740
|
+
var MediaResource = class {
|
|
2741
|
+
http;
|
|
2742
|
+
constructor(http) {
|
|
2743
|
+
this.http = http;
|
|
2744
|
+
}
|
|
2745
|
+
/**
|
|
2746
|
+
* Upload a media file for use in MMS messages
|
|
2747
|
+
*
|
|
2748
|
+
* @param file - File data as a Buffer or ReadableStream
|
|
2749
|
+
* @param options - Upload options (filename, content type)
|
|
2750
|
+
* @returns The uploaded media file with URL
|
|
2751
|
+
*
|
|
2752
|
+
* @example
|
|
2753
|
+
* ```typescript
|
|
2754
|
+
* const media = await sendly.media.upload(
|
|
2755
|
+
* fs.readFileSync('image.png'),
|
|
2756
|
+
* { filename: 'image.png', contentType: 'image/png' }
|
|
2757
|
+
* );
|
|
2758
|
+
*
|
|
2759
|
+
* console.log(media.url); // https://...
|
|
2760
|
+
* ```
|
|
2761
|
+
*
|
|
2762
|
+
* @throws {ValidationError} If the file is invalid or too large
|
|
2763
|
+
* @throws {AuthenticationError} If the API key is invalid
|
|
2764
|
+
* @throws {RateLimitError} If rate limit is exceeded
|
|
2765
|
+
*/
|
|
2766
|
+
async upload(file, options) {
|
|
2767
|
+
const filename = options?.filename || "upload.jpg";
|
|
2768
|
+
const contentType = options?.contentType || "image/jpeg";
|
|
2769
|
+
const blob = file instanceof Buffer ? new Blob([file], { type: contentType }) : file;
|
|
2770
|
+
const form = new FormData();
|
|
2771
|
+
form.append("file", blob, filename);
|
|
2772
|
+
return this.http.requestFormData("/media", form);
|
|
2773
|
+
}
|
|
2774
|
+
};
|
|
2775
|
+
|
|
2675
2776
|
// src/client.ts
|
|
2676
2777
|
var DEFAULT_BASE_URL2 = "https://sendly.live/api/v1";
|
|
2677
2778
|
var DEFAULT_TIMEOUT2 = 3e4;
|
|
@@ -2810,6 +2911,26 @@ var Sendly = class {
|
|
|
2810
2911
|
* ```
|
|
2811
2912
|
*/
|
|
2812
2913
|
contacts;
|
|
2914
|
+
/**
|
|
2915
|
+
* Media API resource - Upload media for MMS
|
|
2916
|
+
*
|
|
2917
|
+
* @example
|
|
2918
|
+
* ```typescript
|
|
2919
|
+
* // Upload a file
|
|
2920
|
+
* const media = await sendly.media.upload(fileBuffer, {
|
|
2921
|
+
* filename: 'photo.jpg',
|
|
2922
|
+
* contentType: 'image/jpeg'
|
|
2923
|
+
* });
|
|
2924
|
+
*
|
|
2925
|
+
* // Send as MMS
|
|
2926
|
+
* await sendly.messages.send({
|
|
2927
|
+
* to: '+15551234567',
|
|
2928
|
+
* text: 'Check this out!',
|
|
2929
|
+
* mediaUrls: [media.url]
|
|
2930
|
+
* });
|
|
2931
|
+
* ```
|
|
2932
|
+
*/
|
|
2933
|
+
media;
|
|
2813
2934
|
http;
|
|
2814
2935
|
config;
|
|
2815
2936
|
/**
|
|
@@ -2846,6 +2967,7 @@ var Sendly = class {
|
|
|
2846
2967
|
this.templates = new TemplatesResource(this.http);
|
|
2847
2968
|
this.campaigns = new CampaignsResource(this.http);
|
|
2848
2969
|
this.contacts = new ContactsResource(this.http);
|
|
2970
|
+
this.media = new MediaResource(this.http);
|
|
2849
2971
|
}
|
|
2850
2972
|
/**
|
|
2851
2973
|
* Check if the client is using a test API key
|