Official Node.js SDK for the Texting Blue API. Send and receive iMessages programmatically.
Zero dependencies -- requires Node.js 18+ (uses global fetch and node:crypto).
npm install @textingblue/nodeimport TextingBlue from '@textingblue/node';
const client = new TextingBlue('tb_live_xxx');
// Send a message
const message = await client.messages.send({
to: '+15551234567',
from: '+15559876543',
content: 'Hello from Texting Blue!',
});
console.log(message.id, message.status);// Send a message
const msg = await client.messages.send({
to: '+15551234567',
from: '+15559876543',
content: 'Hello!',
media_url: 'https://example.com/image.png', // optional
});
// List messages with filters
const list = await client.messages.list({
from: '+15559876543',
status: 'delivered',
limit: 25,
cursor: 'cursor_abc',
});
// Get a single message
const single = await client.messages.get('msg_xxx');// List all numbers
const { numbers } = await client.numbers.list();
// Get a number
const number = await client.numbers.get('num_xxx');
// Update a number
const updated = await client.numbers.update('num_xxx', {
label: 'Support Line',
status: 'active',
});
// Delete a number
await client.numbers.delete('num_xxx');// Create a webhook (returns secret, shown only once)
const webhook = await client.webhooks.create({
url: 'https://example.com/webhook',
events: ['message.received', 'message.delivered'],
phone_number: '+15559876543', // optional: filter to specific number
});
console.log(webhook.secret); // save this!
// List webhooks
const { webhooks } = await client.webhooks.list();
// Update a webhook
await client.webhooks.update('wh_xxx', {
events: ['message.received'],
active: false,
});
// Delete a webhook
await client.webhooks.delete('wh_xxx');Verify incoming webhook signatures to ensure authenticity:
import TextingBlue from '@textingblue/node';
// In your webhook handler (e.g., Express)
app.post('/webhook', (req, res) => {
const signature = req.headers['x-textingblue-signature'] as string;
const payload = req.body; // raw body string
try {
const event = TextingBlue.Webhook.constructEvent(payload, signature, 'whsec_xxx');
console.log('Verified event:', event.type, event.data);
res.sendStatus(200);
} catch (err) {
console.error('Signature verification failed:', err);
res.sendStatus(400);
}
});You can also verify the signature without parsing:
const isValid = TextingBlue.Webhook.verifySignature(payload, signature, secret);import TextingBlue, {
ApiError,
AuthenticationError,
RateLimitError,
NotFoundError,
} from '@textingblue/node';
const client = new TextingBlue('tb_live_xxx');
try {
await client.messages.send({ to: '+1...', from: '+1...', content: 'Hi' });
} catch (err) {
if (err instanceof AuthenticationError) {
// 401 -- invalid API key
} else if (err instanceof RateLimitError) {
// 429 -- back off and retry
console.log('Retry after:', err.retryAfter, 'seconds');
} else if (err instanceof NotFoundError) {
// 404 -- resource not found
} else if (err instanceof ApiError) {
// Other API errors (400, 500, etc.)
console.log(err.status, err.code, err.message);
}
}| Resource | Method | HTTP |
|---|---|---|
| Messages | client.messages.send(params) |
POST /messages/send |
| Messages | client.messages.list(params?) |
GET /messages |
| Messages | client.messages.get(id) |
GET /messages/:id |
| Numbers | client.numbers.list() |
GET /numbers |
| Numbers | client.numbers.get(id) |
GET /numbers/:id |
| Numbers | client.numbers.update(id, p) |
PUT /numbers/:id |
| Numbers | client.numbers.delete(id) |
DELETE /numbers/:id |
| Webhooks | client.webhooks.create(params) |
POST /webhooks |
| Webhooks | client.webhooks.list() |
GET /webhooks |
| Webhooks | client.webhooks.get(id) |
GET /webhooks/:id |
| Webhooks | client.webhooks.update(id, p) |
PUT /webhooks/:id |
| Webhooks | client.webhooks.delete(id) |
DELETE /webhooks/:id |
MIT