🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@sendly/node

Package Overview
Dependencies
Maintainers
1
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sendly/node - npm Package Compare versions

Comparing version
3.6.0
to
3.8.0
+125
-0
dist/index.d.mts

@@ -441,2 +441,72 @@ /**

/**
* Preview result for a single message in a batch
*/
interface BatchPreviewItem {
/**
* Destination phone number
*/
to: string;
/**
* Whether this message will be sent
*/
willSend: boolean;
/**
* Number of SMS segments
*/
segments: number;
/**
* Credits required for this message
*/
creditsNeeded: number;
/**
* Warning message (e.g., quiet hours)
*/
warning?: string;
/**
* Block reason if willSend is false
*/
blockReason?: string;
}
/**
* Response from previewing a batch (dry run)
*/
interface BatchPreviewResponse {
/**
* Whether the batch can be sent
*/
canSend: boolean;
/**
* Total number of messages
*/
totalMessages: number;
/**
* Number of messages that will be sent
*/
willSend: number;
/**
* Number of messages that will be blocked
*/
blocked: number;
/**
* Total credits required
*/
creditsNeeded: number;
/**
* Current credit balance
*/
currentBalance: number;
/**
* Whether user has enough credits
*/
hasEnoughCredits: boolean;
/**
* Per-message preview details
*/
messages: BatchPreviewItem[];
/**
* Summary of why messages are blocked (if any)
*/
blockReasons?: Record<string, number>;
}
/**
* Error codes returned by the Sendly API

@@ -1086,2 +1156,25 @@ */

listBatches(options?: ListBatchesOptions): Promise<BatchListResponse>;
/**
* Preview a batch without sending (dry run)
*
* @param request - Batch request with array of messages
* @returns Preview showing what would happen if batch was sent
*
* @example
* ```typescript
* const preview = await sendly.messages.previewBatch({
* messages: [
* { to: '+15551234567', text: 'Hello User 1!' },
* { to: '+15559876543', text: 'Hello User 2!' }
* ]
* });
*
* console.log(preview.canSend); // true/false
* console.log(preview.creditsNeeded); // 2
* console.log(preview.hasEnoughCredits); // true/false
* ```
*
* @throws {ValidationError} If any message is invalid
*/
previewBatch(request: BatchMessageRequest): Promise<BatchPreviewResponse>;
}

@@ -1412,2 +1505,34 @@

}>;
/**
* Create a new API key
*
* @param name - Display name for the API key
* @param options - Optional settings
* @returns The created API key with the full key value (only shown once)
*
* @example
* ```typescript
* const { apiKey, key } = await sendly.account.createApiKey('Production');
* console.log(`Created key: ${key}`); // Full key - save this!
* console.log(`Key ID: ${apiKey.id}`);
* ```
*/
createApiKey(name: string, options?: {
expiresAt?: string;
}): Promise<{
apiKey: ApiKey;
key: string;
}>;
/**
* Revoke an API key
*
* @param id - API key ID to revoke
*
* @example
* ```typescript
* await sendly.account.revokeApiKey('key_xxx');
* console.log('API key revoked');
* ```
*/
revokeApiKey(id: string): Promise<void>;
}

@@ -1414,0 +1539,0 @@

@@ -441,2 +441,72 @@ /**

/**
* Preview result for a single message in a batch
*/
interface BatchPreviewItem {
/**
* Destination phone number
*/
to: string;
/**
* Whether this message will be sent
*/
willSend: boolean;
/**
* Number of SMS segments
*/
segments: number;
/**
* Credits required for this message
*/
creditsNeeded: number;
/**
* Warning message (e.g., quiet hours)
*/
warning?: string;
/**
* Block reason if willSend is false
*/
blockReason?: string;
}
/**
* Response from previewing a batch (dry run)
*/
interface BatchPreviewResponse {
/**
* Whether the batch can be sent
*/
canSend: boolean;
/**
* Total number of messages
*/
totalMessages: number;
/**
* Number of messages that will be sent
*/
willSend: number;
/**
* Number of messages that will be blocked
*/
blocked: number;
/**
* Total credits required
*/
creditsNeeded: number;
/**
* Current credit balance
*/
currentBalance: number;
/**
* Whether user has enough credits
*/
hasEnoughCredits: boolean;
/**
* Per-message preview details
*/
messages: BatchPreviewItem[];
/**
* Summary of why messages are blocked (if any)
*/
blockReasons?: Record<string, number>;
}
/**
* Error codes returned by the Sendly API

@@ -1086,2 +1156,25 @@ */

listBatches(options?: ListBatchesOptions): Promise<BatchListResponse>;
/**
* Preview a batch without sending (dry run)
*
* @param request - Batch request with array of messages
* @returns Preview showing what would happen if batch was sent
*
* @example
* ```typescript
* const preview = await sendly.messages.previewBatch({
* messages: [
* { to: '+15551234567', text: 'Hello User 1!' },
* { to: '+15559876543', text: 'Hello User 2!' }
* ]
* });
*
* console.log(preview.canSend); // true/false
* console.log(preview.creditsNeeded); // 2
* console.log(preview.hasEnoughCredits); // true/false
* ```
*
* @throws {ValidationError} If any message is invalid
*/
previewBatch(request: BatchMessageRequest): Promise<BatchPreviewResponse>;
}

@@ -1412,2 +1505,34 @@

}>;
/**
* Create a new API key
*
* @param name - Display name for the API key
* @param options - Optional settings
* @returns The created API key with the full key value (only shown once)
*
* @example
* ```typescript
* const { apiKey, key } = await sendly.account.createApiKey('Production');
* console.log(`Created key: ${key}`); // Full key - save this!
* console.log(`Key ID: ${apiKey.id}`);
* ```
*/
createApiKey(name: string, options?: {
expiresAt?: string;
}): Promise<{
apiKey: ApiKey;
key: string;
}>;
/**
* Revoke an API key
*
* @param id - API key ID to revoke
*
* @example
* ```typescript
* await sendly.account.revokeApiKey('key_xxx');
* console.log('API key revoked');
* ```
*/
revokeApiKey(id: string): Promise<void>;
}

@@ -1414,0 +1539,0 @@

@@ -989,2 +989,49 @@ "use strict";

}
/**
* Preview a batch without sending (dry run)
*
* @param request - Batch request with array of messages
* @returns Preview showing what would happen if batch was sent
*
* @example
* ```typescript
* const preview = await sendly.messages.previewBatch({
* messages: [
* { to: '+15551234567', text: 'Hello User 1!' },
* { to: '+15559876543', text: 'Hello User 2!' }
* ]
* });
*
* console.log(preview.canSend); // true/false
* console.log(preview.creditsNeeded); // 2
* console.log(preview.hasEnoughCredits); // true/false
* ```
*
* @throws {ValidationError} If any message is invalid
*/
async previewBatch(request) {
if (!request.messages || !Array.isArray(request.messages) || request.messages.length === 0) {
throw new Error("messages must be a non-empty array");
}
if (request.messages.length > 1e3) {
throw new Error("Maximum 1000 messages per batch");
}
for (const msg of request.messages) {
validatePhoneNumber(msg.to);
validateMessageText(msg.text);
}
if (request.from) {
validateSenderId(request.from);
}
const preview = await this.http.request({
method: "POST",
path: "/messages/batch/preview",
body: {
messages: request.messages,
...request.from && { from: request.from },
...request.messageType && { messageType: request.messageType }
}
});
return preview;
}
};

@@ -1429,2 +1476,50 @@

}
/**
* Create a new API key
*
* @param name - Display name for the API key
* @param options - Optional settings
* @returns The created API key with the full key value (only shown once)
*
* @example
* ```typescript
* const { apiKey, key } = await sendly.account.createApiKey('Production');
* console.log(`Created key: ${key}`); // Full key - save this!
* console.log(`Key ID: ${apiKey.id}`);
* ```
*/
async createApiKey(name, options) {
if (!name) {
throw new Error("API key name is required");
}
const response = await this.http.request({
method: "POST",
path: "/account/keys",
body: {
name,
...options?.expiresAt && { expiresAt: options.expiresAt }
}
});
return response;
}
/**
* Revoke an API key
*
* @param id - API key ID to revoke
*
* @example
* ```typescript
* await sendly.account.revokeApiKey('key_xxx');
* console.log('API key revoked');
* ```
*/
async revokeApiKey(id) {
if (!id) {
throw new Error("API key ID is required");
}
await this.http.request({
method: "DELETE",
path: `/account/keys/${encodeURIComponent(id)}`
});
}
};

@@ -1431,0 +1526,0 @@

@@ -929,2 +929,49 @@ // src/errors.ts

}
/**
* Preview a batch without sending (dry run)
*
* @param request - Batch request with array of messages
* @returns Preview showing what would happen if batch was sent
*
* @example
* ```typescript
* const preview = await sendly.messages.previewBatch({
* messages: [
* { to: '+15551234567', text: 'Hello User 1!' },
* { to: '+15559876543', text: 'Hello User 2!' }
* ]
* });
*
* console.log(preview.canSend); // true/false
* console.log(preview.creditsNeeded); // 2
* console.log(preview.hasEnoughCredits); // true/false
* ```
*
* @throws {ValidationError} If any message is invalid
*/
async previewBatch(request) {
if (!request.messages || !Array.isArray(request.messages) || request.messages.length === 0) {
throw new Error("messages must be a non-empty array");
}
if (request.messages.length > 1e3) {
throw new Error("Maximum 1000 messages per batch");
}
for (const msg of request.messages) {
validatePhoneNumber(msg.to);
validateMessageText(msg.text);
}
if (request.from) {
validateSenderId(request.from);
}
const preview = await this.http.request({
method: "POST",
path: "/messages/batch/preview",
body: {
messages: request.messages,
...request.from && { from: request.from },
...request.messageType && { messageType: request.messageType }
}
});
return preview;
}
};

@@ -1369,2 +1416,50 @@

}
/**
* Create a new API key
*
* @param name - Display name for the API key
* @param options - Optional settings
* @returns The created API key with the full key value (only shown once)
*
* @example
* ```typescript
* const { apiKey, key } = await sendly.account.createApiKey('Production');
* console.log(`Created key: ${key}`); // Full key - save this!
* console.log(`Key ID: ${apiKey.id}`);
* ```
*/
async createApiKey(name, options) {
if (!name) {
throw new Error("API key name is required");
}
const response = await this.http.request({
method: "POST",
path: "/account/keys",
body: {
name,
...options?.expiresAt && { expiresAt: options.expiresAt }
}
});
return response;
}
/**
* Revoke an API key
*
* @param id - API key ID to revoke
*
* @example
* ```typescript
* await sendly.account.revokeApiKey('key_xxx');
* console.log('API key revoked');
* ```
*/
async revokeApiKey(id) {
if (!id) {
throw new Error("API key ID is required");
}
await this.http.request({
method: "DELETE",
path: `/account/keys/${encodeURIComponent(id)}`
});
}
};

@@ -1371,0 +1466,0 @@

+1
-1
{
"name": "@sendly/node",
"version": "3.6.0",
"version": "3.8.0",
"description": "Official Sendly Node.js SDK for SMS messaging",

@@ -5,0 +5,0 @@ "main": "./dist/index.js",

@@ -171,2 +171,12 @@ # @sendly/node

const { data: batches } = await sendly.messages.listBatches();
// Preview batch (dry run) - validates without sending
const preview = await sendly.messages.previewBatch({
messages: [
{ to: '+15551234567', text: 'Hello User 1!' },
{ to: '+447700900123', text: 'Hello UK!' }
]
});
console.log(`Total credits needed: ${preview.totalCredits}`);
console.log(`Valid: ${preview.valid}, Invalid: ${preview.invalid}`);
```

@@ -311,2 +321,13 @@

console.log(`Credits used: ${usage.creditsUsed}`);
// Create a new API key
const newKey = await sendly.account.createApiKey({
name: 'Production Key',
type: 'live',
scopes: ['sms:send', 'sms:read']
});
console.log(`New key: ${newKey.key}`); // Only shown once!
// Revoke an API key
await sendly.account.revokeApiKey('key_xxx');
```

@@ -313,0 +334,0 @@