SMS
Channels

SMS

Send SMS notifications

The SMS channel is provided by @betternotify/sms. It defines a single body slot for text message content.

When to use SMS

SMS is the right channel when the message needs to reach the recipient immediately on their phone, regardless of whether they have your app installed or an internet connection. Use it for OTP codes, two-factor authentication, appointment reminders, delivery updates, or urgent alerts where reliability and reach matter more than rich formatting.

npm install @betternotify/sms

Setup

import { createNotify } from '@betternotify/core';
import { smsChannel } from '@betternotify/sms';

const sms = smsChannel();

const rpc = createNotify({ channels: { sms } });

Slots

Prop

Type

Send arguments

Prop

Type

Full example

import { createNotify, createClient } from '@betternotify/core';
import { createMockTransport } from '@betternotify/core/transports';
import { smsChannel } from '@betternotify/sms';
import { z } from 'zod';

const sms = smsChannel();
const rpc = createNotify({ channels: { sms } });

const catalog = rpc.catalog({
  otpCode: rpc
    .sms()
    .input(z.object({ code: z.string().length(6) }))
    .body(({ input }) => `Your verification code is ${input.code}. It expires in 10 minutes.`),
});

const notify = createClient({
  catalog,
  transportsByChannel: { sms: createMockTransport() },
});

await notify.otpCode.send({
  to: '+15555555555',
  input: { code: '482910' },
});

Transport

The SMS channel produces a RenderedSms with body and to. Any transport that accepts this shape works.

Twilio

The @betternotify/twilio package provides a ready-made transport:

import { twilioSmsTransport } from '@betternotify/twilio';

const transport = twilioSmsTransport({
  accountSid: process.env.TWILIO_ACCOUNT_SID!,
  authToken: process.env.TWILIO_AUTH_TOKEN!,
  fromNumber: process.env.TWILIO_FROM_NUMBER!,
});

Custom

Use createTransport to build a transport for any SMS provider (AWS SNS, Vonage, etc.):

import { createTransport } from '@betternotify/core/transports';
import type { RenderedSms } from '@betternotify/sms';

const myTransport = createTransport<RenderedSms>({
  name: 'my-sms',
  send: async (rendered) => {
    // Call your provider's API with rendered.to and rendered.body
    return { ok: true, data: { messageId: '...' } };
  },
});

On this page