Skip to content

Node.js

@divergent.dev/connect sends and manages SMS and email with the v2 API. It needs Node.js 18 or later, has no dependencies and comes with TypeScript types.

Terminal window
npm install @divergent.dev/connect@preview

The 0.5.x versions are for the v1 API.

import { ConnectClient } from "@divergent.dev/connect";
const connect = new ConnectClient({
apiKey: process.env.CONNECT_API_KEY,
defaultSmsSender: "YourBrand",
defaultEmailSender: "hello@yourcompany.com",
});
OptionDescription
apiKeyYour v2 API key. Required
defaultSmsSenderUsed when an SMS or batch doesn’t set sender
defaultEmailSenderUsed when an email doesn’t set sender
apiKeyId, signingSecretSigns every request, for keys that need signed requests
signingKeySigns with an ECDSA P-256 private key instead, for keys registered with a public key
baseUrlDefaults to https://api.connect.ms
fetchYour own fetch. Defaults to the built-in one

Every request is sent with Connect-Version: 2026-10-01, the version the client is written for.

const sms = await connect.sms.send({
recipient: "+447700900123",
content: "Hi Sam, your order has shipped.",
});
console.log(sms.id, sms.status);

The request and the returned message are the same as the API’s. See Send SMS and Track SMS.

MethodAPI
sms.send(request)POST /v2/sms
sms.get(id)GET /v2/sms/{id}
sms.list(query), sms.listAll(query)GET /v2/sms
sms.cancel(id)DELETE /v2/sms/{id}
sms.createBatch(request), sms.getBatch(id), sms.cancelBatch(id)Batches
await connect.email.send({
recipient: "sam@example.com",
subject: "Your order has shipped",
content: { html: "<p>Hi Sam, your order is on its way.</p>", text: "Hi Sam, your order is on its way." },
});

Attachment content is base64. See Send Email.

The email methods are send, get, list, listAll and cancel, like sms.

list returns one page, { data, nextCursor }. Pass nextCursor back as cursor for the next page. listAll fetches every page for you:

for await (const message of connect.sms.listAll({ status: "failed", since: "2026-10-01T00:00:00Z" })) {
console.log(message.id, message.reason?.description);
}

Every POST has an Idempotency-Key, so a retry never sends twice. The client makes one up, or you can pass your own:

await connect.sms.send(request, { idempotencyKey: "order-991-shipped" });

Network errors, 5xx and 429 responses are retried twice, waiting for Retry-After when there is one.

Any other error throws a ConnectApiError:

import { ConnectApiError } from "@divergent.dev/connect";
try {
await connect.sms.send(request);
} catch (e) {
if (e instanceof ConnectApiError) console.log(e.status, e.code, e.detail, e.errors, e.requestId);
else throw e;
}

errors lists validation problems by field. Quote requestId when you contact support.

To receive events, see Node.js webhooks.