
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
unipile-node-sdk
Advanced tools
The Unipile Node.js SDK provides powerful tools to easily integrate with LinkedIn's API, Email API, and other platforms like WhatsApp, Telegram and Instagram. With this SDK, you can seamlessly manage your LinkedIn connections, send messages (including InMail), retrieve profiles, handle invitations, and manage email communications—all using LinkedIn's API and the Email API. Whether you're automating LinkedIn tasks, building scalable messaging solutions across multiple platforms, or managing emails efficiently, Unipile makes it simple and effective.
📖 Unipile API Guide
💡Unipile API Reference
▶️ Quick Start
🗂️ Installation
💬 Messaging API
✉️ Email API
🔑 All Features
🔸 Account Connection: Generate a Hosted Auth, Implement a custom authentication
🔸 Message: Start a new chat, Send message, List messages in a chat, List chats, Retrieve a chat, List attendees, Retrieve a chat, List attendees, List all attendees from a chat
🔸 Attachment: Send file attachments, Retrieve an attachment from a message
🔸 User Profile: Retrieve users profiles, Retrieve my profile
🔸 Documentation: Access to All Messaging API Features
🔹 Send InMail LinkedIn API
🔹 Send Invitation LinkedIn API: Profile view notification, Send invitation, List pending invitation, Delete invitation
🔹 LinkedIn Posts API: List Users/Companies posts, Retrieve a post, Create a new LinkedIn Post, Send Comments in LinkedIn Post, List Post Comments, Add reaction on a post
🔹 Profiles LinkedIn API: List of contacts/Relations, Retrieve Companies Profiles
🔹 Documentation: Access to All LinkedIn API Features
🔸 Get emails history
🔸 Delete an email
🔸 Send an email
🔸 Reply to an email
🔸 Documentation: Access to All Email API Features
Node 18+ required
npm install unipile-node-sdk
Authenticate using your Unipile account credentials
import { UnipileClient } from 'unipile-node-sdk';
const client = new UnipileClient('https://{YOUR_DSN}', '{YOUR_ACCESS_TOKEN}');
Add a messaging account : LinkedIn
const response = await client.account.connectLinkedin({
username: 'your LinkedIn username',
password: 'your LinkedIn password',
});
Retrieve a LinkedIn company profile
const response = await client.users.getCompanyProfile({
account_id: linkedinAccount.id,
identifier: 'Unipile',
});
You can easily connect multiple accounts
Generate a Hosted Auth Wizard link
await client.account.createHostedAuthLink({
type: 'create', // or reconnect
expiresOn: '2024-12-22T12:00:00.701Z',
api_url: 'your api',
providers: '*', // * means all provider
success_redirect_url: 'your success url',
failure_redirect_url: 'your fail url',
notify_url: 'your notify url',
});
Implement a custom authentication to connect accounts on your application :
await client.account.connectLinkedin({
username: 'your LinkedIn username',
password: 'your LinkedIn password',
});
LinkedIn cookie/user-agent
await client.account.connectLinkedinWithCookie({
access_token: 'V2VsY29tZSB0byBVbmlwaWxlICE-gU2hhbnRheSB5b3Ugc3RheSAh',
user_agent: 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1',
});
await client.account.connectWhatsapp();
await client.account.connectInstagram({
username: 'your Instagram username',
password: 'your Instagram password',
});
await client.account.connectMessenger({
username: 'your Messenger username',
password: 'your Messenger password',
});
await client.account.connectTelegram();
await client.account.connectTwitter({
username: 'your X username',
password: 'your X password',
});
Have 2FA / OTP / In-app validation security ? Solve the checkpoint 2FA / OTP
await client.account.solveCodeCheckpoint({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
provider: 'LINKEDIN',
code: '******',
});
LinkedIn : initiate or monitor a sync process
await client.account.resyncLinkedinAccount({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
});
await client.messaging.startNewChat({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
attendees_ids: ['user id OR provider id'],
text: 'new chat with message',
});
await client.messaging.sendMessage({
chat_id: 'vISKyHtDUmagrk6vrnlXhw',
text: 'Hello World',
});
await client.messaging.getAllMessagesFromChat({
chat_id: 'vISKyHtDUmagrk6vrnlXhw',
});
await client.messaging.getAllChats();
// OR sort your chats list
await client.messaging.getAllChats({
account_type: 'LINKEDIN',
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
limit: 50,
after: '2024-07-22T12:00:00.000Z',
});
await client.messaging.getChat('vISKyHtDUmagrk6vrnlXhw');
await client.messaging.getAllAttendees({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
});
await client.messaging.getAllAttendeesFromChat('vISKyHtDUmagrk6vrnlXhw');
Send files attachments
const path = './src/unipile.png';
const fileBuffer = await fs.readFile(path);
await client.messaging.sendMessage({
chat_id: 'vISKyHtDUmagrk6vrnlXhw',
text: 'Hello World',
attachments: [['unipile.png', fileBuffer]],
});
Retrieve an attachment from a message
await client.messaging.getMessageAttachment({
attachment_id: '5882031366722404334',
message_id: '3aRdnf34UiympaebB4-NRA',
});
await client.users.getProfile({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
identifier: 'user id OR user provider id',
});
await client.users.getOwnProfile('t5XY4yQzR9WVrlNFyzPMhw');
If you want to pass some extra parameters for a request beyond what the SDK input defines, all methods allow an extra_params options.
await client.messaging.getMessageAttachment(
{
attachment_id: '5882031366722404334',
message_id: '3aRdnf34UiympaebB4-NRA',
},
{
extra_params: { my_param_name: 'my param value' },
},
);
Depending on the underlying HTTP request mode used, extra_params will be added to the request query string or json or formData body.
This may be useful if you know about and want to use a parameter that is either omitted or not yet defined in the sdk.
try {
const result = await client.messaging.getAllAttendees({
account_id,
});
} catch (err) {
if (err instanceof UnsuccessfulRequestError) {
console.log("UnsuccessfulRequestError", err.message, err.body);
const { status, type } = err.body;
// depeding on the granularity you want, use status :
switch (status) {
case 401:
// ...
break;
case 403:
// ...
break;
case 404:
// ...
break;
case 500:
// ...
break;
case 503:
// ...
break;
case 504:
// ...
break;
default:
// ...
break;
}
// or type ( or both )
switch (type) {
case "errors/missing_credentials":
// ...
break;
case "errors/multiple_sessions":
// ...
break;
case "errors/invalid_checkpoint_solution":
// ...
break;
case "errors/checkpoint_error":
// ...
break;
case "errors/invalid_credentials":
// ...
break;
case "errors/expired_credentials":
// ...
break;
case "errors/insufficient_privileges":
// ...
break;
case "errors/disconnected_account":
// ...
break;
case "errors/invalid_credentials_but_valid_account_imap":
// ...
break;
case "errors/expired_link ":
// ...
break;
case "errors/wrong_account":
// ...
break;
/*
cf https://developer.unipile.com/reference/chatattendeescontroller_listallattendees
for all used error types
*/
default:
// ...
break;
}
}
Example of using the "Get raw data" route
Refer to: https://developer.unipile.com/docs/get-raw-data-example#following-someone
This can be adapted to support all routes not included in the SDK.
const client = new UnipileClient(BASE_URL, "ACCESS_TOKEN", {});
await client.request.send({
path: ["linkedin"],
method: "POST",
parameters: { account_id: "!!YOURACCOUNTID!!" },
body: {
"body": {"patch":{"$set":{"following":true}}},
"account_id": "dfR-rG0tQfGhfeP2l5_Bdw",
"method": "POST",
"request_url": "https://www.linkedin.com/voyager/api/feed/dash/followingStates/urn:li:fsd_followingState:urn:li:fsd_profile:ACoAAAcDMMQBODyLwZrRcgYhrkCafURGqva0U4E",
"encoding": false
},
});
Send InMail LinkedIn API (message to people outside users’ network)
await client.messaging.startNewChat({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
attendees_ids: ['user provider id'],
text: 'send a inmail',
options: {
linkedin: {
api: 'classic' // recruiter / sales_navigator
inmail: true,
},
},
});
await client.users.getProfile({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
identifier: 'user provider id',
linkedin_sections: '*',
notify: true,
});
await client.users.sendInvitation({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
provider_id: 'user provider id',
message: 'Send invitation',
});
await client.users.getAllInvitationsSent({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
});
await client.users.cancelInvitationSent({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
invitation_id: '7221821214065876992',
});
await client.users.getAllPosts({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
identifier: 'user/company provider id',
});
await client.users.getPost({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
post_id: '7222176104768270337',
});
await client.users.createPost({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
text: 'post content',
});
await client.users.sendPostComment({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
post_id: '7222176104768270337',
text: 'comment',
});
await client.users.getAllPostComments({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
post_id: '7222176104768270337',
});
await client.users.sendPostReaction({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
post_id: '7222176104768270337',
reaction_type: 'funny',
});
await client.users.getAllRelations({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
});
await client.users.getProfile({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
identifier: 'user provider id',
linkedin_api: 'sales_navigator',
linkedin_sections: ['experience', 'about'],
notify: true,
});
await client.users.getCompanyProfile({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
identifier: 'Unipile',
});
List all emails
await client.email.getAll({ account_id: 't5XY4yQzR9WVrlNFyzPMhw' });
Retrieve a specific email
await client.email.getOne('TnOWcaycS52dwnhgADlb2w');
await client.email.getOne.byProvider('some email provider id', 'some account id');
await client.email.getAllFolders({ account_id: 't5XY4yQzR9WVrlNFyzPMhw' });
await client.email.getOneFolder('aG0z55cmQOO1y2180eAeuQ');
await client.email.getOneFolder.byProviderId('some folder provider id', 'some account id');
await client.email.getEmailAttachment({
email_id: 'TnOWcaycS52dwnhgADlb2w',
attachment_id: 'AQMkADAwATNiZmYAZC1jM2ZmAC00MzA1LTAwAi0wMAoARgAAA6zgXpjd',
});
await client.email.getEmailAttachment.byProviderId({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
email_id: 'some email provider id',
attachment_id: 'AQMkADAwATNiZmYAZC1jM2ZmAC00MzA1LTAwAi0wMAoARgAAA6zgXpjd',
});
await client.email.delete('TnOWcaycS52dwnhgADlb2w');
await client.email.delete.byProviderId('some email provider id', 'some account id');
await client.email.send({
account_id: 't5XY4yQzR9WVrlNFyzPMhw',
to: [{ identifier: 'unipile@gmail.com' }],
subject: 'email subject',
body: 'email body content',
});
await client.email.send({
account_id,
body: 'send a mail',
subject: 're: parent email subject',
to: [{ identifier: 'unipile@gmail.com' }],
reply_to: 'some email provider id',
});
FAQs
Unipile node SDK
We found that unipile-node-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.