message.comDevelopers

JavaScript SDK Planned

The official JavaScript SDK wraps the message.com REST API and Socket.io endpoints into one idiomatic package. Works in modern browsers, Node 18+, Bun, and Deno. ESM first with a CommonJS fallback.

This SDK is on the Q1 2026 roadmap. The REST API and Socket.io endpoints it wraps are live today, so you can build against the underlying primitives now and swap in the SDK when it ships.

Installation

Pick your package manager. The bundle is roughly 12KB minified plus gzipped for the REST surface, with Socket.io as an optional peer-installable add-on.

Terminal
npm install @message-com/sdk
# or
pnpm add @message-com/sdk
# or
yarn add @message-com/sdk

Initialise the client

Construct a single client per process. The constructor takes either an API key (server-side) or a workspace JWT (when running inside the dashboard or a logged-in agent surface). See Authentication for the two modes.

server.ts
import { Message } from "@message-com/sdk";

const msg = new Message({
  apiKey: process.env.MESSAGE_API_KEY!,   // server-side keys only
  // workspaceId is inferred from the key
});

Visitors

The most common backend job is keeping your customer records in sync with the visitor table in your workspace. The SDK exposes an idempotent visitors.upsert keyed by externalId or email.

visitor-sync.ts
// Upsert a visitor from your CRM webhook
await msg.visitors.upsert({
  email: "[email protected]",
  externalId: "crm-4567",
  name: "Alice Johnson",
  attributes: {
    plan: "pro",
    mrr: 99,
    signupDate: "2025-11-04",
  },
});

Tickets

Tickets are just conversations with channel = "ticket". The SDK ships a thin helper so you do not have to remember the channel string.

tickets.ts
// Create a ticket when Stripe tells you a charge failed
await msg.tickets.create({
  visitorEmail: "[email protected]",
  subject: "Auto-detected failed payment",
  body: "Stripe charge ch_xyz failed. Reach out within 4h.",
  tags: ["billing", "auto-created"],
});

Real-time

The realtime namespace wraps the Socket.io /agent channel. It accepts the same event names documented on the agent namespace page and returns typed payloads.

realtime.ts
// Subscribe to new conversations server-side
msg.realtime.on("conversation:new", (conv) => {
  console.log("new conversation in queue", conv.id);
});

await msg.realtime.connect();

Error handling

All errors surface as a typed MessageError with a numeric statusCode, a machine-readable error code, and a human message. The list of codes mirrors the REST API. See errors, rate limits, versioning.

Browser vs Node

The same package exports both a browser entrypoint that runs against a workspace JWT, and a node entrypoint for server-side API-key flows. Tree-shaking will eliminate the half you do not import.

  • Browser builds rely on the platform fetch and WebSocket APIs.
  • Node builds use the built-in fetch on Node 18+ (a polyfill is auto-loaded on older runtimes).
  • TypeScript types ship in-band; no separate @types package needed.

Common pitfalls

  • Do not ship your API key to the browser. If you need browser-side access, mint a workspace JWT server-side and pass it down. See the MDN reference on Authorization headers for context.
  • Always set externalId when upserting visitors. Without it we fall back to email, which can collide when a visitor changes addresses.
  • Reconnect logic is built in on the realtime client. Do not wrap it in your own retry loop.