This guide is for the current version of the Node.js SDK.
Looking for v1? See our Quickstart guide for our Node.js v1 SDK.
Send your first SMS with the official clicksend npm package in under 5 minutes.
This guide covers the current v2 SDK (clicksend, built on axios). If you're upgrading from the legacy @clicksend/clicksend-nodejs package, see the migration guide instead.
1. Prerequisites
Before you start, make sure you have:
Requirement | Details |
|---|---|
A ClickSend account | Sign up free if you don't have one. New accounts get free credit to test with. |
API credentials | Your username and API key, both on the API Credentials page of the dashboard. You'll authenticate with these, not your dashboard login password. |
Node.js 14 or newer | Check with |
Account credit | Sending SMS consumes credit. Free trial credit is enough for this guide; top up on the Billing page if you get an |
2. Install
Install the SDK with your package manager of choice:
npm install clicksend # yarn
yarn add clicksend
# pnpm
pnpm add clicksend 3. Configure the client
Every API class in the SDK authenticates with HTTP Basic auth, using a Configuration object built from your ClickSend username and API key (not a bearer token). Never hard-code real credentials — load them from environment variables:
export CLICKSEND_USERNAME="your-clicksend-username"
export CLICKSEND_API_KEY="your-clicksend-api-key" import { Configuration, SmsApi } from 'clicksend';
const configuration = new Configuration({
username: process.env.CLICKSEND_USERNAME, // placeholder: your ClickSend username
password: process.env.CLICKSEND_API_KEY, // placeholder: your ClickSend API key
});
const smsApi = new SmsApi(configuration); That's it — smsApi is now an authenticated client for every SMS endpoint (send, history, templates, delivery receipts, etc.). Each ClickSend resource has its own API class (MmsApi, ManagementApi, ContactsApi, ...); construct one per resource you need, reusing the same configuration.
4. Send your first SMS
This is a complete, runnable example. Save it as send-sms.ts (or .js, dropping the types), set the two environment variables from step 3, replace the to number with a real one, and run it.
import { Configuration, SmsApi } from 'clicksend';
async function main() {
const configuration = new Configuration({
username: process.env.CLICKSEND_USERNAME,
password: process.env.CLICKSEND_API_KEY,
});
const smsApi = new SmsApi(configuration);
const { data } = await smsApi.sendSms({
sendSmsRequest: {
messages: [
{
source: 'sdk',
from: 'YOUR_SENDER_ID', // placeholder: e.g. a ClickSend number, or omit to use your default sender
body: 'Hello from ClickSend!',
to: '+61411111111', // placeholder: recipient in E.164 format
},
],
},
});
console.log(data);
}
main().catch((error) => {
console.error('Failed to send SMS:', error.message);
process.exit(1);
}); Run it:
npx tsx send-sms.ts # TypeScript, no build step
# or: node send-sms.js # if you dropped the types Field names inside the request body are snake_case, not camelCase (from_email, list_id, etc. — to/from/body/source are single words so they look the same either way). Only the outer { sendSmsRequest: ... } wrapper key is camelCase. Getting this wrong doesn't throw — the server just silently ignores the misspelled field.
5. Understand the response
smsApi.sendSms(...) resolves to an axios response; the ClickSend payload is on .data. It looks like this:
{
"http_code": 200,
"response_code": "SUCCESS",
"response_msg": "Messages queued for delivery.",
"data": {
"total_price": 0.0388,
"total_count": 1,
"queued_count": 1,
"blocked_count": 0,
"messages": [
{
"to": "+61411111111",
"body": "Hello from ClickSend!",
"from": "SENDERID",
"message_id": "6811A5CE-E374-5D26-82F5-1D9E52FA9AB3",
"message_parts": 1,
"message_price": "0.0388",
"status": "SUCCESS",
"date": 1758434400
}
]
}
} The fields you'll use most:
Field | Where | Meaning |
|---|---|---|
Message ID |
| The unique ID for this message. Quote this when contacting support or looking up delivery receipts. |
Status |
| The outcome for this specific message ( |
Cost |
| Cost of this one message (string, in your account's currency). |
| Top level | The outcome of the request as a whole ( |
const { data } = await smsApi.sendSms({ sendSmsRequest });
const [message] = data.data?.messages ?? [];
console.log('Message ID:', message?.message_id);
console.log('Status:', message?.status);
console.log('Cost:', message?.message_price); 6. Common errors
The SDK is built on axios: a non-2xx HTTP response rejects the promise as an AxiosError, which you catch with try/catch. But ClickSend also reports some failures — like an invalid recipient in an otherwise-valid batch — inside a 200 OK response body, which won't throw at all. Always check status/response_code, not just whether the call threw.
import axios from 'axios';
try {
const { data } = await smsApi.sendSms({ sendSmsRequest });
// Even on HTTP 200, check each message's own status
for (const message of data.data?.messages ?? []) {
if (message.status !== 'SUCCESS') {
console.warn(`Message to ${message.to} failed: ${message.status}`);
}
}
} catch (error) {
if (axios.isAxiosError(error)) {
console.error(error.response?.status, error.response?.data);
} else {
throw error;
}
} Error | How it shows up | What it means | Fix |
|---|---|---|---|
Authentication failure | HTTP 401 Unauthorized — the promise rejects, caught in | Your | Double-check |
Invalid recipient | Request usually still returns HTTP 200 ( | The destination mobile number isn't a valid, deliverable number (bad format, wrong country, disconnected, etc). | Validate/normalize numbers to E.164 (e.g. |
Insufficient balance |
| Your account has run out of message credit. | Top up credit on the Billing page, or check balance first with |
Next steps
-
Full endpoint reference: developers.clicksend.com/docs/rest/v3
-
Every other message type (MMS, voice, campaigns) and account/contact management: the package README
-
Migrating from the legacy SDK: github.com/ClickSend/clicksend-nodejs-v2/blob/main/docs/MIGRATION.md
-
SDK source & issues: github.com/ClickSend/clicksend-nodejs-v2