Skip to content

Hurus111/sinch-messaging-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sinch Messaging SDK

TypeScript/Node.js SDK for the Sinch Messaging API (Simplified). Send and manage messages over SMS and WhatsApp with a consistent, developer-friendly API.

Install

npm install sinch-messaging-sdk

Or with yarn / pnpm:

yarn add sinch-messaging-sdk
pnpm add sinch-messaging-sdk

Requirements: Node.js 18+.

Usage

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);

Error handling

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;
}

Example script

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:mock

Uses fake responses so you see the full flow without a backend.

With real API: set SINCH_AUTH_TOKEN, then:

npm run build && npm run example

Without a valid token you’ll get 401/404; the script still demonstrates usage and error handling.

Design choices

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 see message_id or next_page_token.

  • Errors – The API returns different error bodies (e.g. fault.code vs error_code). The SDK exposes one type, SinchApiError, with statusCode, code, message, kind (validation, not_found, forbidden, server_error, unknown), and raw for the original body. Callers can branch on kind without parsing API-specific shapes.

  • Pagination – You can call listMessages({ pageSize, pageToken }) for manual pages, or use listMessagesIterator({ pageSize }) and for 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 provides recipientForSms(phone) and recipientForWhatsApp(identifier, type?) so you don’t have to remember the shapes.

  • Dates – The API sends created_at as an ISO string. The SDK parses it to a Date on Message.createdAt so you can use it directly.

  • Channel – The domain uses "SMS" and "WHATSAPP" (constants CHANNEL_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 optional baseUrl). The token is sent in the X-Sinch-Auth header 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.

Scripts

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

Links

  • Video walkthroughYouTube: SDK structure, design decisions, and demo.
  • Assignment – The original instructions are in ASSIGNMENT.md.

About

TypeScript/Node.js SDK for the Sinch Messaging API. Send SMS and WhatsApp messages.

Resources

Stars

Watchers

Forks

Contributors