๐ฑ SMSGate JS/TS API Client
August 20, 2026 ยท View on GitHub
A TypeScript-first client for seamless integration with the SMSGate API. Programmatically send SMS messages through your Android devices with strict typing and modern JavaScript features.
Note: The API doesn't provide CORS headers, so the library cannot be used in a browser environment directly.
๐ Table of Contents
- ๐ฑ SMSGate JS/TS API Client
๐ Authentication
The SMSGate client supports two authentication methods: Basic Authentication and JWT (JSON Web Token) Authentication. JWT is the recommended approach for production environments due to its enhanced security features and support for scoped permissions.
Basic Authentication
Basic Authentication uses a username and password to access the API. This method is simple but less secure for production use.
When to use:
- Simple integrations
- Development and testing
- Legacy systems
JWT Authentication
JWT Authentication uses bearer tokens with configurable scopes to access the API. This method provides enhanced security and fine-grained access control.
When to use:
- Production environments
- Applications requiring scoped permissions
- Systems with multiple components needing different access levels
โจ Features
- TypeScript Ready: Full type definitions out of the box
- Flexible HTTP Clients: Works with any HTTP library (fetch, axios, node-fetch, etc.)
- Promise-based API: Async/await ready
- Webhook Management: Create, read, and delete webhooks
- Device Management: List and remove devices
- Health Check: Monitor system status
- Inbox Export: Export received messages
- Log Retrieval: Get system logs with time filtering
- Settings Management: Get, update, and partially update settings
- Customizable Base URL: Point to different API endpoints
- Server-Side Focus: Designed for Node.js environments
โ๏ธ Requirements
- Node.js v18+
- npm/yarn/bun package manager
๐ฆ Installation
npm install android-sms-gateway
# or
yarn add android-sms-gateway
# or
bun add android-sms-gateway
๐ Quickstart
Basic Usage
import Client, { MessagePriority } from 'android-sms-gateway';
// First, create a client with Basic Auth to generate a JWT token
const basicAuthClient = new Client(
process.env.ANDROID_SMS_GATEWAY_LOGIN!,
process.env.ANDROID_SMS_GATEWAY_PASSWORD!
);
// Generate a JWT token with specific scopes
async function generateJWTToken() {
try {
const tokenRequest = {
scopes: [
"messages:send",
"messages:read",
"devices:list"
],
ttl: 3600 // Token expires in 1 hour
};
const tokenResponse = await basicAuthClient.generateToken(tokenRequest);
console.log('JWT Token generated, expires at:', tokenResponse.expires_at);
return tokenResponse.access_token;
} catch (error) {
console.error('Token generation failed:', error);
throw error;
}
}
// Initialize client with JWT Authentication
async function initializeJWTClient() {
const jwtToken = await generateJWTToken();
// Initialize client with JWT token (empty string for login, token for password)
const jwtClient = new Client(
"", // Empty string for login when using JWT
jwtToken // JWT token
);
return jwtClient;
}
// Send message using JWT Authentication
async function sendSMS() {
try {
const jwtClient = await initializeJWTClient();
const message = {
phoneNumbers: ['+1234567890'],
message: 'Secure OTP: 123456 ๐',
priority: MessagePriority.Default
};
const state = await jwtClient.send(message);
console.log('Message ID:', state.id);
// Check status after 5 seconds
setTimeout(async () => {
const updatedState = await jwtClient.getState(state.id);
console.log('Message status:', updatedState.state);
}, 5000);
} catch (error) {
console.error('Sending failed:', error);
}
}
// Revoke a JWT token
async function revokeJWTToken(jti: string) {
try {
await basicAuthClient.revokeToken(jti);
console.log('JWT token revoked successfully');
} catch (error) {
console.error('Token revocation failed:', error);
}
}
sendSMS();
Webhook Management
// Create webhook
const webhook = {
url: 'https://your-api.com/sms-callback',
event: WebHookEventType.SmsReceived,
};
api.registerWebhook(webhook)
.then(created => console.log('Webhook created:', created.id))
.catch(console.error);
// List webhooks
api.getWebhooks()
.then(webhooks => console.log('Active webhooks:', webhooks.length));
Device Management
// List devices
api.getDevices()
.then(devices => console.log('Devices:', devices.map(d => d.name)))
.catch(console.error);
// Remove a device
api.deleteDevice('device-id')
.then(() => console.log('Device removed'))
.catch(console.error);
Health Check
// Check system health
api.getHealth()
.then(health => {
console.log('System status:', health.status);
console.log('Checks:', Object.keys(health.checks).length);
})
.catch(console.error);
Inbox Refresh
// Refresh inbox messages (async - server returns 202 Accepted and processes in the background)
const since = new Date('2024-01-01T00:00:00Z');
const until = new Date('2024-01-02T00:00:00Z');
await api.refreshInbox({
deviceId: 'device-id',
since,
until,
messageTypes: [IncomingMessageType.SMS, IncomingMessageType.MMS],
webhookDelivery: WebhookDelivery.Batch, // deliver webhooks for refreshed messages as ordered batches
});
Log Retrieval
// Get logs
const from = new Date('2024-01-01T00:00:00Z');
const to = new Date('2024-01-02T00:00:00Z');
api.getLogs(from, to)
.then(logs => console.log('Logs retrieved:', logs.length))
.catch(console.error);
Settings Management
// Get settings
api.getSettings()
.then(settings => console.log('Settings:', settings))
.catch(console.error);
// Update settings
const newSettings = {
messages: { limitPeriod: 'PerDay', limitValue: 100 },
webhooks: { internetRequired: true, retryCount: 3 },
};
api.updateSettings(newSettings)
.then(() => console.log('Settings updated'))
.catch(console.error);
// Partially update settings
const partialSettings = {
messages: { limitValue: 200 },
};
api.patchSettings(partialSettings)
.then(() => console.log('Settings partially updated'))
.catch(console.error);
๐ค Client Guide
Client Configuration
The Client class accepts the following constructor arguments:
| Argument | Description | Default |
|---|---|---|
login | Username or empty string | Required |
password | Password or JWT token | Required |
httpClient | HTTP client implementation | fetch |
baseUrl | API base URL | "https://api.sms-gate.app/3rdparty/v1" |
Authentication Configuration
Basic Authentication:
const api = new Client(
process.env.ANDROID_SMS_GATEWAY_LOGIN!, // Username
process.env.ANDROID_SMS_GATEWAY_PASSWORD! // Password
);
JWT Authentication:
const api = new Client(
"", // Empty string for login when using JWT
jwtToken // JWT token
);
The client automatically detects which authentication method to use based on the login parameter:
- If
loginis a non-empty string: Uses Basic Authentication - If
loginis an empty string: Uses JWT Authentication with the provided token
Core Methods
| Method | Description | Returns |
|---|---|---|
| Messages | ||
send(message: Message, options?: { skipPhoneValidation?: boolean }) | Send SMS message | Promise<MessageState> |
getState(messageId: string) | Check message status | Promise<MessageState> |
| Webhooks | ||
getWebhooks() | List registered webhooks | Promise<WebHook[]> |
registerWebhook(request: RegisterWebHookRequest) | Register new webhook | Promise<WebHook> |
deleteWebhook(webhookId: string) | Remove webhook | Promise<void> |
| Devices | ||
getDevices() | List registered devices | Promise<Device[]> |
deleteDevice(deviceId: string) | Remove device | Promise<void> |
| Health | ||
getHealth() | Check system health | Promise<HealthResponse> |
| Inbox | ||
refreshInbox(request: InboxRefreshRequest) | Refresh inbox messages (async, 202 Accepted) | Promise<void> |
| Logs | ||
getLogs(from?: Date, to?: Date) | Get logs within time range | Promise<LogEntry[]> |
| Settings | ||
getSettings() | Get settings | Promise<DeviceSettings> |
updateSettings(settings: DeviceSettings) | Update settings | Promise<void> |
patchSettings(settings: Partial<DeviceSettings>) | Partially update settings | Promise<void> |
| JWT Token Management | ||
generateToken(request: TokenRequest) | Generate new JWT token | Promise<TokenResponse> |
revokeToken(jti: string) | Revoke JWT token by ID | Promise<void> |
Type Definitions
/**
* The fields common to all SMS message variants.
*/
interface MessageCommon {
/**
* The ID of the message, generated if not provided.
* @default null
*/
id?: string | null;
/**
* The optional device ID for explicit device selection.
* @default null
*/
deviceId?: string | null;
/**
* Whether the message content is encrypted.
* @default false
*/
isEncrypted?: boolean;
/**
* The time-to-live (TTL) of the message in seconds.
* Conflicts with `validUntil`.
* @default null
*/
ttl?: number | null;
/**
* The phone numbers to send the message to.
*/
phoneNumbers: string[];
/**
* The SIM number to send the message from.
* @default null
*/
simNumber?: number | null;
/**
* Whether to include a delivery report for the message.
* @default true
*/
withDeliveryReport?: boolean | null;
/**
* The message priority, -128..127 (default 0).
* Values > 99 bypass sending limits and delays.
* @default 0
*/
priority?: number;
/**
* Valid until (RFC3339 date-time). Conflicts with `ttl`.
* @default null
*/
validUntil?: Date | null;
/**
* Schedule delivery at; must be in the future and <= `validUntil`.
* @default null
*/
scheduleAt?: Date | null;
}
interface TextMessagePayload {
text: string;
}
interface DataMessagePayload {
data: string;
port: number;
}
/**
* Represents an SMS message to send.
* Exactly one of `message`, `textMessage`, or `dataMessage` must be provided;
* this constraint is enforced by the server at runtime.
*/
interface Message extends MessageCommon {
/**
* The message content.
* @deprecated Use textMessage
*/
message: string;
/**
* The text message payload.
* Must not be provided together with `message` or `dataMessage`.
*/
textMessage?: TextMessagePayload;
/**
* The data message payload.
* Must not be provided together with `message` or `textMessage`.
*/
dataMessage?: DataMessagePayload;
}
/**
* Message priority constants.
*/
const MessagePriority = {
Minimum: -128,
Default: 0,
BypassThreshold: 100,
Maximum: 127,
} as const;
interface MessageState {
id: string;
state: ProcessState;
recipients: RecipientState[];
}
interface WebHook {
id: string;
event: WebHookEventType;
url: string;
deviceId: string;
}
interface Device {
id: string;
name: string;
createdAt: string;
lastSeen: string;
updatedAt: string;
deletedAt?: string | null;
}
interface DeviceSettings {
messages?: SettingsMessages;
webhooks?: SettingsWebhooks;
gateway?: SettingsGateway;
encryption?: SettingsEncryption;
logs?: SettingsLogs;
ping?: SettingsPing;
}
interface HealthResponse {
status: HealthStatus;
version: string;
releaseId: number;
checks: { [checkName: string]: HealthCheck };
}
interface LogEntry {
id: number;
createdAt: string;
module: string;
priority: LogEntryPriority;
message: string;
context?: Record<string, string>;
}
interface MessagesExportRequest {
deviceId: string;
since: Date;
until: Date;
}
interface InboxRefreshRequest {
deviceId?: string;
since: Date;
until: Date;
messageTypes?: IncomingMessageType[];
webhookDelivery?: WebhookDelivery;
}
enum IncomingMessageType {
SMS = 'SMS',
DATA_SMS = 'DATA_SMS',
MMS = 'MMS',
MMS_DOWNLOADED = 'MMS_DOWNLOADED',
}
enum WebhookDelivery {
Disabled = 'Disabled',
Individual = 'Individual',
Batch = 'Batch',
}
// JWT Authentication Types
interface TokenRequest {
/**
* The scopes to include in the token.
*/
scopes: string[];
/**
* The time-to-live (TTL) of the token in seconds.
*/
ttl?: number;
}
interface TokenResponse {
/**
* The JWT access token.
*/
access_token: string;
/**
* The type of the token.
*/
token_type: string;
/**
* The unique identifier of the token.
*/
id: string;
/**
* The expiration time of the token.
*/
expires_at: string;
}
For more details, see the domain.ts.
๐ HTTP Clients
The library comes with fetch-based built-in HTTP client. You can provide your own implementation of the HttpClient interface:
interface HttpClient {
get<T>(url: string, headers?: Record<string, string>): Promise<T>;
post<T>(url: string, body: any, headers?: Record<string, string>): Promise<T>;
put<T>(url: string, body: any, headers?: Record<string, string>): Promise<T>;
patch<T>(url: string, body: any, headers?: Record<string, string>): Promise<T>;
delete<T>(url: string, headers?: Record<string, string>): Promise<T>;
}
๐ Security Notes
โ ๏ธ Important Security Practices
- Always store credentials in environment variables
- Never expose credentials in client-side code
- Use HTTPS for all production communications
- Rotate passwords regularly
- Use strong, unique passwords
- Use appropriate TTL values based on your security requirements
- Apply the principle of least privilege
- Implement proper token revocation workflows
๐ API Reference
For complete API documentation including all available methods, request/response schemas, and error codes, visit: ๐ Official API Documentation
๐ฅ Contributing
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Development Setup
git clone https://github.com/android-sms-gateway/client-ts.git
cd client-ts
bun install
bun run build
bun test
๐ License
Distributed under the Apache 2.0 License. See LICENSE for more information.
Note: Android is a trademark of Google LLC. This project is not affiliated with or endorsed by Google.