Documentation Index
Fetch the complete documentation index at: https://messages.dev/docs/llms.txt
Use this file to discover all available pages before exploring further.
Install
npm install @messages-dev/sdk
Initialize
import { createClient } from "@messages-dev/sdk";
const client = createClient();
The client automatically reads MESSAGES_API_KEY from your environment. To pass a key explicitly:
const client = createClient({ apiKey: "sk_live_..." });
Send a message
await client.sendMessage({
from: "+15551234567",
to: "+15559876543",
text: "Hello from Messages.dev!",
});
Receive messages via webhooks
Create a webhook from the Webhooks page in your dashboard
and copy the signing secret. Then handle incoming events on your server:
import { verifyWebhook } from "@messages-dev/sdk";
app.post("/webhooks", async (req, res) => {
const event = await verifyWebhook(
req.body,
req.headers["x-webhook-signature"],
"your_webhook_secret",
);
switch (event.event) {
case "message.received":
console.log(`New message from ${event.data.sender}: ${event.data.text}`);
break;
case "message.sent":
console.log(`Message delivered: ${event.data.id}`);
break;
}
res.sendStatus(200);
});
If the signature is invalid, verifyWebhook throws a SignatureVerificationError.
List messages
const messages = await client.listMessages({
from: "+15551234567",
to: "+15559876543",
});
Reactions
await client.sendReaction({
from: "+15551234567",
to: "+15559876543",
messageId: "msg_abc123",
type: "love",
});
const reactions = await client.listReactions({
messageId: "msg_abc123",
});
Typing indicators
await client.startTyping({
from: "+15551234567",
to: "+15559876543",
});
await client.stopTyping({
from: "+15551234567",
to: "+15559876543",
});
Read receipts
await client.sendReadReceipt({
from: "+15551234567",
to: "+15559876543",
});
const receipts = await client.listReadReceipts({
from: "+15551234567",
to: "+15559876543",
});
Files
Upload files to send as message attachments:
const file = await client.uploadFile({
from: "+15551234567",
file: Buffer.from(imageData),
filename: "photo.jpg",
mimeType: "image/jpeg",
});
await client.sendMessage({
from: "+15551234567",
to: "+15559876543",
text: "Check this out!",
attachments: [file.id],
});
const { url } = await client.getFileUrl({ id: "file_abc123" });
Delivery tracking
await client.getOutboxItem({ id: "obx_xyz789" });
Lines
const lines = await client.listLines();
for (const line of lines.data) {
console.log(line.handle, line.service, line.isActive);
}
Chats
const chats = await client.listChats({
from: "+15551234567",
});
for (const chat of chats.data) {
console.log(chat.identifier, chat.name, chat.lastMessageAt);
}
Webhooks
await client.createWebhook({
from: "+15551234567",
url: "https://example.com/webhooks",
events: ["message.received", "message.sent"],
});
const webhooks = await client.listWebhooks({
from: "+15551234567",
});
await client.deleteWebhook({ id: "wh_abc123" });
List methods return a page object with data, hasMore, and nextCursor. Use for await...of to iterate through all results:
const page = await client.listMessages({
from: "+15551234567",
to: "+15559876543",
limit: 10,
});
if (page.hasMore) {
const nextPage = await client.listMessages({
from: "+15551234567",
to: "+15559876543",
cursor: page.nextCursor,
});
}
const messages = await client.listMessages({
from: "+15551234567",
to: "+15559876543",
});
for await (const message of messages) {
console.log(message.text);
}
Error handling
All errors extend MessagesError and include the error type, code, and message from the API:
import { createClient, AuthenticationError, AuthorizationError, InvalidRequestError, NotFoundError } from "@messages-dev/sdk";
try {
await client.sendMessage({
from: "+15551234567",
to: "+15559876543",
text: "Hello!",
});
} catch (err) {
if (err instanceof AuthenticationError) {
console.error("Bad API key:", err.code);
} else if (err instanceof AuthorizationError) {
console.error("Forbidden:", err.code);
} else if (err instanceof InvalidRequestError) {
console.error("Bad request:", err.code, err.param);
} else if (err instanceof NotFoundError) {
console.error("Not found:", err.code);
}
}
Every error includes:
| Property | Type | Description |
|---|
type | string | Error category (e.g. authentication_error) |
code | string | Machine-readable code (e.g. invalid_api_key) |
message | string | Human-readable explanation |
param | string | undefined | The parameter that caused the error |
status | number | HTTP status code |
requestId | string | Unique request ID for debugging |
Configuration
All options are passed to createClient:
const client = createClient({
apiKey: "sk_live_...",
baseUrl: "https://api.messages.dev",
timeout: 30_000,
maxRetries: 2,
});
TypeScript
The SDK is written in TypeScript and exports types for all resources:
import { createClient } from "@messages-dev/sdk";
import type {
Line,
Chat,
Message,
Reaction,
Webhook,
OutboxItem,
WebhookEvent,
} from "@messages-dev/sdk";