TypeScript/Node.js SDK for the Sinch Messaging API (Simplified). Send and manage messages over SMS and WhatsApp with a consistent, developer-friendly API.
npm install sinch-messaging-sdkOr with yarn / pnpm:
yarn add sinch-messaging-sdk
pnpm add sinch-messaging-sdkRequirements: Node.js 18+.
Create a client with your auth token, then call the messaging APIs. All methods use camelCase; the SDK hides the API’s snake_case and mixed naming.
import {
SinchMessagingClient,
CHANNEL_SMS,
CHANNEL_WHATSAPP,
recipientForSms,
recipientForWhatsApp,
SinchApiError,
} from "sinch-messaging-sdk";
const client = new SinchMessagingClient({
authToken: process.env.SINCH_AUTH_TOKEN!,
// baseUrl: "https://messaging.api.sinch.com/v1", // optional, this is the default
});
// Send an SMS (use CHANNEL_SMS / CHANNEL_WHATSAPP)
const sent = await client.sendMessage({
channel: CHANNEL_SMS,
recipient: recipientForSms("+33612345678"),
messageContent: { textMessage: "Hello from the SDK" },
});
console.log(sent.messageId, sent.status, sent.createdAt); // createdAt is a Date
// Send to WhatsApp (object recipient)
await client.sendMessage({
channel: CHANNEL_WHATSAPP,
recipient: recipientForWhatsApp("+33612345678"),
messageContent: { textMessage: "Hi there" },
});
// List messages (paginated)
const { messages, nextPageToken } = await client.listMessages({ pageSize: 20 });
// Iterate over all messages (auto-pagination)
for await (const message of client.listMessagesIterator({ pageSize: 10 })) {
console.log(message.messageId, message.createdAt);
}
// Get one message, recall (delete) one
const msg = await client.getMessage(sent.messageId);
await client.recallMessage(sent.messageId);The API returns different error shapes (e.g. 400 vs 404). The SDK normalizes them to a single type:
try {
await client.sendMessage({ ... });
} catch (e) {
if (e instanceof SinchApiError) {
console.error(e.statusCode, e.code, e.message, e.kind); // e.g. kind: "validation" | "not_found" | "forbidden" | "server_error" | "unknown"
// e.raw has the original response body if you need it
}
throw e;
}From the repo you can run a full example (list, send, get, recall + error handling):
With mock (no API, no token):
npm run build && npm run example:mockUses fake responses so you see the full flow without a backend.
With real API: set SINCH_AUTH_TOKEN, then:
npm run build && npm run exampleWithout a valid token you’ll get 401/404; the script still demonstrates usage and error handling.
The SDK is built so developers get a stable, predictable surface while the underlying API has inconsistent naming and two error formats. Below is a short summary.
-
Structure – The code is organized in three layers (domain, application, infrastructure). The domain holds types and concepts (Message, Channel, recipient helpers). The application exposes a single client (
SinchMessagingClient) that implements the use cases. The infrastructure does HTTP and maps between API wire format and domain types. This keeps business logic separate from transport and makes testing and evolution easier. -
Naming – The public API is camelCase (
messageId,nextPageToken,messageContent.textMessage). The API uses snake_case and mixed names; the SDK translates in infrastructure mappers so callers never seemessage_idornext_page_token. -
Errors – The API returns different error bodies (e.g.
fault.codevserror_code). The SDK exposes one type,SinchApiError, withstatusCode,code,message,kind(validation, not_found, forbidden, server_error, unknown), andrawfor the original body. Callers can branch onkindwithout parsing API-specific shapes. -
Pagination – You can call
listMessages({ pageSize, pageToken })for manual pages, or uselistMessagesIterator({ pageSize })andfor await (...)to walk all messages without handling tokens. -
Recipient – For SMS you pass a string; for WhatsApp you pass an object
{ identifier, type }. The SDK providesrecipientForSms(phone)andrecipientForWhatsApp(identifier, type?)so you don’t have to remember the shapes. -
Dates – The API sends
created_atas an ISO string. The SDK parses it to aDateonMessage.createdAtso you can use it directly. -
Channel – The domain uses
"SMS"and"WHATSAPP"(constantsCHANNEL_SMS,CHANNEL_WHATSAPP). The API expects lowercase"sms"/"whatsapp"; the SDK maps between them in the infrastructure layer. -
Authentication – You configure the client once with
authToken(and optionalbaseUrl). The token is sent in theX-Sinch-Authheader on every request.
Trade-offs: A hand-written client and mappers are used instead of full OpenAPI generation to control naming, error shape, and date handling. Types are aligned with a normalized spec via npm run generate:sdk. Use npm test for tests.
| Command | Description |
|---|---|
npm run build |
Compile TypeScript to dist/ |
npm test |
Run unit tests (Vitest) |
npm run test:watch |
Run tests in watch mode |
npm run example |
Run the example script (real API; needs token) |
npm run example:mock |
Run the example with fake responses (no API) |
npm run generate:sdk |
Normalize OpenAPI spec and generate reference types |
- Video walkthrough – YouTube: SDK structure, design decisions, and demo.
- Assignment – The original instructions are in ASSIGNMENT.md.