TypeScript SDK

TypeScript SDK

The official TypeScript SDK for Sent LogoSent provides type-safe access to the entire Sent API. Built for modern Node.js applications with native ESM and CommonJS support, automatic retries, and comprehensive error handling.

Installation

npm install @sentdm/sentdm
yarn add @sentdm/sentdm
pnpm add @sentdm/sentdm
bun add @sentdm/sentdm

Quick Start

Initialize the client

import SentDm from '@sentdm/sentdm';

const client = new SentDm();  // Uses SENT_DM_API_KEY env var by default

Send your first message

const response = await client.messages.send({
  to: ['+1234567890'],
  template: {
    id: '7ba7b820-9dad-11d1-80b4-00c04fd430c8',
    name: 'welcome',
    parameters: {
      name: 'John Doe'
    }
  }
});

console.log('Message sent:', response.data.messages[0].id);
console.log('Status:', response.data.messages[0].status);

Authentication

The client can be configured using environment variables or explicitly:

import SentDm from '@sentdm/sentdm';

// Using environment variables (recommended)
// SENT_DM_API_KEY=your_api_key
const client = new SentDm();

// Or explicit configuration
const client = new SentDm({
  apiKey: 'your_api_key',
});

Send Messages

Send a message

const response = await client.messages.send({
  to: ['+1234567890'],
  template: {
    id: '7ba7b820-9dad-11d1-80b4-00c04fd430c8',
    name: 'welcome',
    parameters: {
      name: 'John Doe',
      order_id: '12345'
    }
  },
  channels: ['whatsapp', 'sms']  // Optional: defaults to template channels
});

console.log('Message ID:', response.data.messages[0].id);
console.log('Status:', response.data.messages[0].status);

Test mode

Use testMode to validate requests without sending real messages:

const response = await client.messages.send({
  to: ['+1234567890'],
  template: {
    id: '7ba7b820-9dad-11d1-80b4-00c04fd430c8',
    name: 'welcome'
  },
  testMode: true  // Validates but doesn't send
});

// Response will have test data
console.log('Validation passed:', response.data.messages[0].id);

Handle errors

When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of APIError will be thrown:

try {
  const response = await client.messages.send({
    to: ['+1234567890'],
    template: {
      id: '7ba7b820-9dad-11d1-80b4-00c04fd430c8',
      name: 'welcome'
    }
  });
} catch (err) {
  if (err instanceof SentDm.APIError) {
    console.log(err.status); // 400
    console.log(err.name); // BadRequestError
    console.log(err.headers); // {server: 'nginx', ...}
  } else {
    throw err;
  }
}

Error codes are as follows:

Status CodeError Type
400BadRequestError
401AuthenticationError
403PermissionDeniedError
404NotFoundError
422UnprocessableEntityError
429RateLimitError
>=500InternalServerError
N/AAPIConnectionError

Retries

Certain errors will be automatically retried 2 times by default, with a short exponential backoff. Connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors will all be retried by default.

// Configure the default for all requests:
const client = new SentDm({
  maxRetries: 0, // default is 2
});

// Or, configure per-request:
await client.messages.send({
  to: ['+1234567890'],
  template: { id: 'welcome-template', name: 'welcome' }
}, {
  maxRetries: 5,
});

Timeouts

Requests time out after 1 minute by default. You can configure this with a timeout option:

// Configure the default for all requests:
const client = new SentDm({
  timeout: 20 * 1000, // 20 seconds (default is 1 minute)
});

// Override per-request:
await client.messages.send({
  to: ['+1234567890'],
  template: { id: 'welcome-template', name: 'welcome' }
}, {
  timeout: 5 * 1000,
});

Contacts

Create and manage contacts:

// Create a contact
const contact = await client.contacts.create({
  phoneNumber: '+1234567890',
});

console.log('Contact ID:', contact.data.id);

// List contacts
const contacts = await client.contacts.list({
  limit: 100,
});

console.log('Total:', contacts.data.length);

// Get a contact
const contact = await client.contacts.get('contact-uuid');

// Update a contact
const updated = await client.contacts.update('contact-uuid', {
  phoneNumber: '+1987654321',
});

// Delete a contact
await client.contacts.delete('contact-uuid');

Templates

List and retrieve templates:

// List all templates
const templates = await client.templates.list();

for (const template of templates.data) {
  console.log(`${template.name} (${template.status}): ${template.id}`);
}

// Get a specific template
const template = await client.templates.get('template-uuid');

console.log('Template name:', template.data.name);
console.log('Status:', template.data.status);

Framework Integration

NestJS

See the NestJS Integration guide for complete dependency injection, module setup, and testing examples.

// messages/messages.service.ts
import { Injectable, Inject } from '@nestjs/common';
import SentDm from '@sentdm/sentdm';
import { SENT_CLIENT } from '../sent/sent.module';

@Injectable()
export class MessagesService {
  constructor(
    @Inject(SENT_CLIENT) private readonly sentClient: SentDm,
  ) {}

  async sendWelcomeMessage(phoneNumber: string, name: string) {
    const response = await this.sentClient.messages.send({
      to: [phoneNumber],
      template: {
        id: 'welcome-template',
        name: 'welcome',
        parameters: { name }
      }
    });
    return response.data.messages[0];
  }
}

Next.js (App Router)

See the Next.js Integration guide for complete Server Actions, Route Handlers, and Edge Runtime examples.

// app/api/send-message/route.ts
import SentDm from '@sentdm/sentdm';
import { NextResponse } from 'next/server';

const client = new SentDm();

export async function POST(request: Request) {
  const { phoneNumber, templateId, variables } = await request.json();

  try {
    const response = await client.messages.send({
      to: [phoneNumber],
      template: {
        id: templateId,
        name: 'welcome',
        parameters: variables
      }
    });

    return NextResponse.json({
      messageId: response.data.messages[0].id,
      status: response.data.messages[0].status,
    });
  } catch (error) {
    if (error instanceof SentDm.APIError) {
      return NextResponse.json(
        { error: error.message },
        { status: error.status }
      );
    }
    throw error;
  }
}

Express.js

See the Express.js Integration guide for complete dependency injection, validation, and structured logging examples.

import express from 'express';
import SentDm from '@sentdm/sentdm';

const app = express();
const client = new SentDm();

app.use(express.json());

app.post('/send-message', async (req, res) => {
  const { phoneNumber, templateId, variables } = req.body;

  try {
    const response = await client.messages.send({
      to: [phoneNumber],
      template: {
        id: templateId,
        name: 'welcome',
        parameters: variables
      }
    });

    res.json({
      success: true,
      message: response.data,
    });
  } catch (error) {
    if (error instanceof SentDm.APIError) {
      res.status(error.status).json({ error: error.message });
    } else {
      res.status(500).json({ error: 'Internal server error' });
    }
  }
});

app.listen(3000);

Logging

The log level can be configured via the SENT_DM_LOG environment variable or using the logLevel client option:

import SentDm from '@sentdm/sentdm';

const client = new SentDm({
  logLevel: 'debug', // Show all log messages
});

Available log levels: 'debug', 'info', 'warn' (default), 'error', 'off'

Source & Issues

Getting Help

On this page