Official TypeScript SDK for messages.dev. Send and receive iMessage and SMS over a simple REST API from Node.js, Bun, Deno, or the browser.
npm install @messages-dev/sdk- Sign up at app.messages.dev.
- Go to API Keys and click Create Key. Copy the
sk_live_...key, it's only shown once. - Go to the Overview tab, scan the sandbox QR code with your phone, and send the activation text. Your sandbox is now paired with your number and you have 50 free messages per day.
import { createClient } from "@messages-dev/sdk";
const client = createClient();
await client.sendMessage({
from: "+15551234567",
to: "+15559876543",
text: "Hello from the iMessage API!",
});createClient() reads your key from the MESSAGES_API_KEY environment variable. Set it in your .env:
MESSAGES_API_KEY=sk_live_...Or pass it explicitly: createClient({ apiKey: "sk_live_..." }).
Send messages with attachments and reply threading:
await client.sendMessage({
from,
to,
text,
attachments: ["file_abc"],
replyTo: "msg_xyz",
});Send reactions, typing indicators, and read receipts:
await client.sendReaction({ from, to, messageId, type: "love" });
await client.startTyping({ from, to });
await client.sendReadReceipt({ from, to });Upload files and attach them to messages:
const file = await client.uploadFile({
from,
file: buffer,
filename: "photo.jpg",
mimeType: "image/jpeg",
});
await client.sendMessage({
from,
to,
text: "Look",
attachments: [file.id],
});Create a webhook from the Webhooks tab in your dashboard. Enter your endpoint URL, select the events you want to subscribe to, and copy the signing secret.
Verify incoming deliveries with verifyWebhook. Signatures use timing-safe HMAC-SHA256 and timestamps older than 5 minutes are rejected:
import { verifyWebhook } from "@messages-dev/sdk";
app.post("/webhooks", async (req, res) => {
const event = await verifyWebhook(
req.body,
req.headers["x-webhook-signature"],
process.env.WEBHOOK_SECRET,
);
if (event.event === "message.received") {
console.log(`${event.data.sender}: ${event.data.text}`);
}
res.sendStatus(200);
});All errors extend MessagesError with code, param, status, and requestId:
import { RateLimitError, InvalidRequestError } from "@messages-dev/sdk";
try {
await client.sendMessage({ from, to, text });
} catch (err) {
if (err instanceof RateLimitError) {
// back off
} else if (err instanceof InvalidRequestError) {
console.error(err.code, err.param);
}
}createClient({
apiKey: "sk_live_...",
baseUrl: "https://api.messages.dev",
timeout: 30_000,
maxRetries: 2,
});Retries use exponential backoff on 429 and 5xx responses. 4xx errors are returned immediately.
Types ship with the package:
import type { Line, Chat, Message, Reaction, Webhook, WebhookEvent } from "@messages-dev/sdk";Zod schemas (MessageSchema, LineSchema, etc.) are also exported.
- Documentation: messages.dev/docs
- API reference: messages.dev/docs/api-reference
- Dashboard: app.messages.dev
- Issues: github.com/messages-dev/sdk/issues